Working with Fractions/real numbers and the like

FunFlyer

New Member
In an algorithm to come up with a value to be fed into a PWMOUT command, it has to do calculations of the type A=7/5. The result is clearly no integer, but should be stored correctly. I wrote a litte progam to test, wether the PWMOut command would accept it.

Symbol oPWM1 = c.2
symbol bPWMDuty = b0

main:
PWMOut oPWM1, 63, 0
bpwmduty = 12/5
debug bpwmduty
pause 5000
PWMDuty oPWM1, bPWMDuty
end


I have two questions:

1. Is there an (easy) way to convert my bPWMDuty value into an integer, e.g. round it to 0 decimals, or simply cut of the decimal part?

2. Can I "Debug" this program in the editor without the need for a connected PICAXE (in this case an 08M2)? I thougt the DEBUG command in the program would do the trick, but I was mistaken.
 
The Picaxe has ONLY integer values and all arithmetic is integer. If you write
b0 = 7/5
then b0 will contain 1 (the truncation of the result).

If you want to show what is happening in the simulator, use the sertxd() function which allows you to display output on the simulator terminal screen. Your code would look something like this:
Code:
Symbol oPWM1   = c.2    
symbol bPWMDuty = b0

main:
   PWMOut oPWM1, 63, 0
   bpwmduty = 12/5
   sertxd(#bpwmduty,CR,LF)
   pause 5000
   PWMDuty oPWM1, bPWMDuty
end

PS - to make it easier for others to read your code, enclose it between [ CODE ] and [ / CODE ] (but remove the spaces in what I just wrote)
 
Hi,

The PWMOUT instruction only accepts Integer numbers so, it's hardly relevant that PICaxe Basic works "only" with integers, you just need to perform the calculation "correctly". ;)

The PWMOUT command is of the form PWMOUT pin , period , duty where the period is a Byte value from 0 to 255 and the duty may need to be a Word value from 0 to 1023 . The period value has "1" added and is then multiplied by 4 to set up a "timebase" with from 4 to 1024 "timeslots" and then the duty value selects the number of timeslots (from 0 to 1023) when the PWM output is to be active (High). Note that the duty cannot take a value of 1024 (which wraps back to zero), so if you need a 100% output waveform then the maximum period value must be 254 not 255 (giving 1020 timeslots).

The PWM duty period might be typically defined as a percentage, which needs to be multiplied by the number of timeslots in the period. For example (untested) : DUTY (word) = PERIOD + 1 * dutypercent / 25 should give a reasonable result (note the 25 is = 100 / 4 , i.e. percent / periodtimeslots, to keep within the bounds of a Word calculation).

Alternatively, it's possible to consider the duty as a "fractional binary" number, i.e. where the Most Significant Bit has a value of 1/2 (a half) the next as 1/4 (a quarter) . etc. up to 1/256 for a Byte, or 1/65536 for a Word. Conversion to "decimal" values is "messy", but it can work very easily in binary using the ** operator, because this "automatically" divides by 65536, so a "normal" word value is treated as a fractional binary value (maximum value approx 0.99999).

Cheers, Alan.
 
Thanks for Your input.

I got it to work. Fortunately everything works fine, without any problems with type conversions. Don´t ask me why. I just gave it a shot. I included some english comments. So just disregard the "german stuff". Hope it makes any sense to You.

One question remains. As You can see I used some IF constructs. I wanted to compare the input signal to an expression

Code:
 If I_aktuell - I_m <= I_th then
        I_aktuell = Ampl_tot
        bpwmduty = I_aktuell  * 51 / 10
        PWMDuty oPWM1, bPWMDuty
    end if

That didn´t work. So I introduced a "Vergleichswert" variabel and modified the code as follows

Code:
    Vergleichswert1 = I_aktuell - I_m

    If Vergleichswert1 <= I_th then
        I_aktuell = Ampl_tot
        bpwmduty = I_aktuell  * 51 / 10
        PWMDuty oPWM1, bPWMDuty
    end if

That works fine. So I cant´t use an expression for comparisn in an IF statement?

so here is the code:

Code:
;Software zur Steuerung des Luefters fue?r einen Rauchgenerator. Das Eingangssignal wird direkt am Empfaenger am Ausgang fuer den Fahrtregler abgenommen. 
;Das Programm funkrionier bei Vorwaerts- und Rueckwaertsfahrt. Es kann eine Totzone eingerichtet werden, so dass der Rauch auch ausgeblasen wird, wenn der Motor aus ist.
;Eine EXPO funktion ist integriert, um den maximalen Ausstoss schon vor erreichen der Maximalfahrt zu erreichen.

;(c) Herbert Guenterberg 2025

;This software controlls a fan for a steam generator for a radiocontrolled boat. The input signal is taken direct from the motor channel (line 61).
;It works forward and backwards (66-68). It is possible to incorporate a neutral zone around the center stick position, where the fan is still running, while the Proppeller is stopped.
;An "exponential " function is implemented, so that the fan reaches full RPM before the Propeller turn at max RPM - which it rarely does.

Symbol oPWM1                       = c.2
Symbol I_m                              = b1 ; Mittelstellung/neutral position
Symbol I_th                              = b2 ; halbe Totzone/half of the neutral zone
Symbol Ampl_tot                     = b3 ; Amplitude in der Totzone/RPM for neutral zone
Symbol Max_Ampl_wann         = b4 ; ab wann wird MaxDrehzahl erreicht/from hereon MaxRPM is applied
Symbol Max_Ampl_Wert          = b5 ; Hoehe MaxDrehzahl/MaxRPM
Symbol Differenz_Impuls         = b6 ; Impulsdifferenz von Totzone bis erreichen MaxDrehzahl
Symbol Differenz_Amplitude   = b7 ; Ampltidendifferenz Totzone bis MaxDrehzahl
Symbol I_aktuell                       = b8 ; aktueller Impulswert, inklusive Umrechnungen/Input signal
Symbol Vergleichswert1           = b9 ; wird zu vergleichszwecken benoetigt/reference value
Symbol Vergleichswert2           = b10 ; wird zu vergleichszwecken benoetigt/refernce value

symbol bPWMDuty                  = w10


Init:

; Setzen Parameter
; Initialize parameters

    I_m  = 150
    I_th = 3
    Ampl_tot = 10
    Max_Ampl_wann = 25
    Max_Ampl_Wert = 200
    
; Berechnen Parameter fuer Steigung im EXPO Bereich
; calculate slope for "EXPO" portion of the curve

    Differenz_Amplitude = Max_Ampl_Wert - I_m - Ampl_tot
    Differenz_Impuls = Max_Ampl_wann - I_th
    
; Intitialisieren PWM Generator
; initialize PWM generator

    PWMOut oPWM1, 63, 0
    
; manuelle Eingabe der Impulslaenge f?r Testzwecke. Dann PULSIN command auskommentieren
; for test purposes
    
     ;I_aktuell = 152
    

 main:
 
; Einlesen aktuellen Impuls aus Empfaenger
; read signal

    PULSIN c.3,1,I_aktuell
    
; Hochklappen. Sorgt dafuer, dass  es auch bei Rueckwaertsfahrt funktioniert. Das ist quasi der Gleichrichter.
; flip the "nagative" side of the input curve up

    If I_aktuell < I_m then
        I_aktuell = 300 - I_aktuell
    end if


; Mittelstellung bis Ende Totzone
; neutral zone
    
    Vergleichswert1 = I_aktuell - I_m
    
     If Vergleichswert1 <= I_th then
        I_aktuell = Ampl_tot
        bpwmduty = I_aktuell  * 51 / 10
        PWMDuty oPWM1, bPWMDuty
    end if


; "exponentielle" Steigung
; "EXPO" part

    Vergleichswert1 = I_m + I_th
    Vergleichswert2 = I_m + Max_Ampl_wann
    
    If I_aktuell >= Vergleichswert1 and I_aktuell <= Vergleichswert2 then
        I_aktuell = I_aktuell - I_m - I_th
        I_aktuell = I_aktuell * Differenz_Amplitude / Differenz_Impuls
        I_aktuell = I_aktuell + I_m + Ampl_tot
        I_aktuell = I_aktuell - I_m
    
        bpwmduty = I_aktuell  * 51 / 10
        PWMDuty oPWM1, bPWMDuty

    end if

; Erreichen oberes Ende EXPO bis Max Ausschlag
; max RPM
    
    Vergleichswert1 = I_m + Max_Ampl_wann
    
    If I_aktuell >= Vergleichswert1 then
        I_aktuell = Max_Ampl_Wert
        I_aktuell = I_aktuell - I_m
        bpwmduty = I_aktuell  * 51 / 10
        PWMDuty oPWM1, bPWMDuty
        
    end if


    goto main
    
end
 
As you have discovered (and as it says in the manual):
Code:
Syntax:
IF variable ?? value {AND/OR variable ?? value ...} THEN
{code}
ELSEIF variable ?? value {AND/OR variable ?? value ...} THEN
{code}
ELSE
{code}
ENDIF
the IF statement takes a VARIABLE for the first part of its test and then a VALUE or a VARIABLE for the second part. You cannot use expressions - they have to be calculated and stored in a variable before the test.
 
Back
Top