Code to control output On and Off pulse times with pots

Visser

Well-known member
Thank you for the info
I will remove the zener. It was there for protection if pot goes to zero
I will try the voltage divider with a 2k2 in series with a 2k pot. That will ensure I never get more than 5V on the adc input if input voltage goes to 16V which will never happen
And then I can fine tune
There was a dry joint on the board on the pic supply. I also replaced the igbt with a big fet. FDA032N08 . The heatsink runs cold while the motor gets hot. I wanted to use an 18V isolated supply chip and mosfet driver but that doesn't seems to be necessary. Driving the fet straight from 5V works good

 

Attachments

Last edited:

Visser

Well-known member
Hi
I need to get pwm out when an input pin goes high and vice versa on an 8M
I have this code but don't know how to simulate it.
Will it work ?


#Picaxe 08M
SYMBOL SENSEPIN = PIN1
MAIN:
DO
LOOP UNTIL SENSEPIN = 1
DO
pwmout 2, 49, 99 ; 20000Hz at 50% @ 4MHz
LOOP UNTIL SENSEPIN = 0
GOTO MAIN
 
Last edited:

AllyCat

Senior Member
Hi,

PWMOUT is basically a Hardware function, but the Simulator is primarily for Software emulation. All the simulator does is to mark the PWM output pin in a Green colour, maybe with a "square wave" symbol inside.

You don't need to put the PWMOUT instruction inside a loop. First execution of the command starts the PWM output and then you can stop the output with a PWMOUT pin , OFF , or re-issue the command with a Duty Cycle value of 0 (zero) or 200 (or greater) depending how you want the PWM to be disabled.
Code:
#Picaxe 08M
SYMBOL SENSEPIN = PIN1
MAIN:
DO  :  LOOP UNTIL SENSEPIN = 1
   pwmout 2, 49, 100             ; 20000Hz at 50% @ 4MHz
DO  :  LOOP UNTIL SENSEPIN = 0
   pwmout 2 , OFF
GOTO MAIN
Cheers, Alan.
 

Visser

Well-known member
Hi
I found this idea to toggle 2 outputs every ten minutes. It should stay high for a second only
Is there a simpler way to do it?

#Picaxe 08M
#No_Data
DO
HIGH 1 ;output1 goes HIGH
PAUSE 1000 ;PAUSE 1 SEC
LOW 1 ;output 1 goes LOW
for b1 = 1 to 10 ;10 loops
pause 60000 ;wait 60 secondS
next b1
HIGH 2 ;output2 goes HIGH
PAUSE 1000 ;PAUSE 1 SEC
LOW 2 ;output 2 goes LOW
for b1 = 1 to 10 ;10 loops
pause 60000 ;wait 60 secondS
next b1
LOOP
 

AllyCat

Senior Member
Hi,

If you really are using an 08M , then that's probably about the best that can be done. But if you have the current 08M2 then the following will probably work (but the simulation is rather tedious). However, it doesn't save many bytes of codespace (about 33 instead of 38 bytes).

Code:
#picaxe 08m2
#no_data
	setfreq m2
	low c.1 : low c.2
do
	time = 0
	pulsout c.1,50000             ; 1 second with 2 MHz clock
	do : loop until time = 300    ; 10 minutes with 2 MHz clock
	pulsout c.2,50000
	do : loop until time = 600
loop
Cheers, Alan.
 

Visser

Well-known member
Hi,

If you really are using an 08M , then that's probably about the best that can be done. But if you have the current 08M2 then the following will probably work (but the simulation is rather tedious). However, it doesn't save many bytes of codespace (about 33 instead of 38 bytes).

Code:
#picaxe 08m2
#no_data
    setfreq m2
    low c.1 : low c.2
do
    time = 0
    pulsout c.1,50000             ; 1 second with 2 MHz clock
    do : loop until time = 300    ; 10 minutes with 2 MHz clock
    pulsout c.2,50000
    do : loop until time = 600
loop
Cheers, Alan.
Thank you. I will get some 08M2 chips
 

AllyCat

Senior Member
Hi,

There's nothing "wrong" with the original program, nor the 08M, but they both can be "improved" by using [code ] .. [/code] tags in the forum, some more "meaningful comments", and the newer features of PE6 (the Program Editor). For example, I would probably write it as follows (but others might have different ideas) :

Code:
#Picaxe 08M      ; And more recent PICAXEs such as 08M2
#No_Data          ; Saves a little time downloading the program
DO                 ; Start main loop
    HIGH C.1          ; Start a pulse on Pin 1 (now named C.1 in recent Editors such as PE6)
      PAUSE 1000       ; Wait for 1 second (= 1000 milli-seconds)
    LOW C.1            ; End the pulse
    for b1 = 1 to 10        ; Start a "counting" program loop
        WAIT 60          ; Alternative to PAUSE in seconds (but 60 is still the maximum value)
    next b1
    HIGH C.2            ; Start a pulse on Pin 2
      PAUSE 1000          ; MilliSeconds
    LOW C.2
    for b1 = 1 to 10
        WAIT 60           ; Seconds
    next b1
LOOP               ; Repeat the loop continuously
For larger programs, Subroutines (or sometimes MACROs) can be used to make the code more "maintainable" and more "Self-Documenting", but I'm not sure that they really help here (and in this case use MORE Program Memory) :
Code:
#Picaxe 08M        ; And most other PICAXEs
#No_Data          ; EEPROM/DATA Download is not needed
Symbol tempb = b1          ; A "temporary" or "Local" Variable to use when needed
Symbol PinNumber = b13      ; Variable to allow the Program(mer) to use different pin numbers
Symbol WAITMINUTES = 10     ; Maximum 255 set by use of byte variable "tempb"
Symbol PULSEWIDTH = 1       ; Seconds (maximum 60)
DO                     ; Main Program loop
    PinNumber = C.1 : GOSUB  PulsePin     ; Width set by constant "PULSEWIDTH"
    GOSUB WaitForMinutes                ; Period set by constant "WAITMINUTES"
    PinNumber = C.2 : GOSUB  PulsePin 
    GOSUB WaitForMinutes
LOOP         ; Forever
; SubRoutines :
PulsePin:
    HIGH PinNumber
    WAIT PULSEWIDTH           ; In seconds (maximum 60)
    LOW PinNumber
Return       ; End of Subroutine (DON'T use a GOTO ! )
WaitForMinutes:
    for tempb = 1 to WAITMINUTES
        PAUSE 60000              ; MilliSeconds
    next tempb
Return
Cheers, Alan.
 

Visser

Well-known member
Hallo
I need to combine these 2 codes to run on one 08M chip
I'm not sure how to do it. Can someone help me with this one please
The first part is to switch an output high for 20msec when an adc goes higher than 4.8V
The 2nd part must give me a PWM output while the input is high
Regards
Vissie

#Picaxe 08M
#No_Data
main:
readadc 4,b0 ; read ADC1 into variable b0
if b0 > 245 then pulse ;voltage > 4.8v
goto main
pulse: high 1 ; switch on output 1
pause 20 ; stay on for 20 msec
low 1


SYMBOL SENSEPIN = PIN3
DO : LOOP UNTIL SENSEPIN = 1
pwmout 2, 3, 7 ; 250KHz at 50%
DO : LOOP UNTIL SENSEPIN = 0
pwmout 2 , OFF
GOTO MAIN
 
Last edited:

AllyCat

Senior Member
Hi,

If it's an 08M (not an M2) chip, then probably change the second section to:
Code:
;     GOTO  start1                 ; Uncomment for an 08M2   (closes the first loop)
SYMBOL SENSEPIN = PIN3
start2:            ; Initiates multi-tasking with M2 chips (otherwise it's a normal label)
IF SENSEPIN = 1 THEN
   pwmout 2, 3, 7      ; 250KHz at 50%
ELSE
    pwmout 2 , OFF
ENDIF
    GOTO  main          ; Or change to start2 with an 08M2
But the PWM will not chang during the 20 ms pulse. If you actually have an 08M2 then you can use mult-tasking, probably by changing the mains to start1 (not tested).

Cheers, Alan.
 
Last edited:

Visser

Well-known member
Hi,

If it's an 08M (not an M2) chip, then probably change the second section to:
Code:
;     GOTO  start1                 ; Uncomment for an 08M2   (closes the first loop)
SYMBOL SENSEPIN = PIN3
start2:            ; Initiates multi-tasking with M2 chips (otherwise it's a normal label)
IF SENSEPIN = 1 THEN
   pwmout 2, 3, 7      ; 250KHz at 50%
ELSE
    pwmout 2 , OFF
ENDIF
    GOTO  main          ; Or change to start2 with an 08M2
But the PWM will not chang during the 20 ms pulse. If you actually have an 08M2 then you can use mult-tasking, probably by changing the mains to start1 (not tested).

Cheers, Alan.
Thank you
But now I'm even more confused. I have a handful of 08M chips but can get m2's if I have to
 

AllyCat

Senior Member
Hi,

Personally, I've never found the need for the multitasking feature of M2s (it's an "easy" way to do mutitasking) so you can use one of your 08Ms. Just use the code I gave to replace your section beginning "SYMBOL....".

If the input is above 4.8 volts then the program will output a 20ms pulse and then "fall through" into the second part, but you would need to change the first "GOTO main" to "GOTO start2" to execute the second part. So perhaps it's better to re-write the whole program to use "structured" code without any GOTOs at all:

Code:
#Picaxe 08M
#No_Data
SYMBOL SENSEPIN = PIN3
SYMBOL ADCI = 4                 ; ADC Input
    Low 1                               ; Initialise for pulsout
do
    readadc ADCI , b0               ; read ADC1 into variable b0
    IF b0 > 245 then                 ;  pulse if voltage > 4.8v (If 5volt supply)
        pulsout 1 , 2000           ; pulse output #1 for 20 ms (or could still use the HIGH.. :  PAUSE .. :  LOW .. structure)
    ENDIF
    IF SENSEPIN = 1 THEN
        pwmout 2 , 3 , 7              ; 250KHz at 50%
    ELSE
        pwmout 2 , OFF
    ENDIF
loop
Cheers, Alan.
 

Visser

Well-known member
Hi,

Personally, I've never found the need for the multitasking feature of M2s (it's an "easy" way to do mutitasking) so you can use one of your 08Ms. Just use the code I gave to replace your section beginning "SYMBOL....".

If the input is above 4.8 volts then the program will output a 20ms pulse and then "fall through" into the second part, but you would need to change the first "GOTO main" to "GOTO start2" to execute the second part. So perhaps it's better to re-write the whole program to use "structured" code without any GOTOs at all:

Code:
#Picaxe 08M
#No_Data
SYMBOL SENSEPIN = PIN3
SYMBOL ADCI = 4                 ; ADC Input
    Low 1                               ; Initialise for pulsout
do
    readadc ADCI , b0               ; read ADC1 into variable b0
    IF b0 > 245 then                 ;  pulse if voltage > 4.8v (If 5volt supply)
        pulsout 1 , 2000           ; pulse output #1 for 20 ms (or could still use the HIGH.. :  PAUSE .. :  LOW .. structure)
    ENDIF
    IF SENSEPIN = 1 THEN
        pwmout 2 , 3 , 7              ; 250KHz at 50%
    ELSE
        pwmout 2 , OFF
    ENDIF
loop
Cheers, Alan.
Thank you
I will try it soon when boards are build. It simulates beautifully
 

Visser

Well-known member
My previous code modified to work with READADC10 would be -
Code:
#Picaxe 18M2
Do
  ReadAdc10 C.1, w1 : w1 = w1 * 25
  ReadAdc10 C.0, w0 : w0 = w0 * 25
  High B.6
  Pause w1
  Low B.6
  Pause w0
Loop
If you wish to use SYMBOL statements to name the variables -
Code:
#Picaxe 18M2

Symbol FreqAdj1 = w0
Symbol FreqAdj2 = w1
Symbol onpulse  = w2
Symbol offpulse = w3

Do
  ReadAdc10 C.1, FreqAdj1 : onpulse  = FreqAdj1 * 25
  ReadAdc10 C.0, FreqAdj2 : offpulse = FreqAdj2 * 25
  High B.6
  Pause onpulse
  Low B.6
  Pause offpulse
Loop
[/QUOTE]
Part of the problem is using "setfreq m32". That will make all your PAUSE commands 8 times shorter than you want.

You are also setting your "onpulse = FreqAdj1 min 0 max 1023". There is no need for either a min or max as the FreqAdj1 value can only be 0 to 1023 from a READADC10.

What you are doing is making the onpulse value the same as the pot value, giving it a range of 0 to 1023. Then you use that in a PAUSE which pauses in increments of 1ms. With a full pot value of 1023 that means a 1023ms delay, about 1 second, an 1/8th of that due to the SETFREQ M32.

So first thing is to remove the SETFREQ M32, if you haven't already..

Next is to increase the onpulse so it's the right value for PAUSE to deliver the delay you want. If a full pot of 1023 means 25 seconds, 25000ms, you need to multiply FreqAdj1 by approximately 25 : 1023 x 25 = 25575, ~25000ms, ~25 seconds.

Likewise for offpulse.

So your calculations should be -

onpulse = FreqAdj1 * 25
offpulse = FreqAdj2 * 25

Finally, remove multiple "pause onpulse" and multiple "pause offpulse". With the correct onpulse and offpulse values, calculated as above, you will only need one of each.

My previous code modified to work with READADC10 would be -
Code:
#Picaxe 18M2
Do
  ReadAdc10 C.1, w1 : w1 = w1 * 25
  ReadAdc10 C.0, w0 : w0 = w0 * 25
  High B.6
  Pause w1
  Low B.6
  Pause w0
Loop
If you wish to use SYMBOL statements to name the variables -
Code:
#Picaxe 18M2

Symbol FreqAdj1 = w0
Symbol FreqAdj2 = w1
Symbol onpulse  = w2
Symbol offpulse = w3

Do
  ReadAdc10 C.1, FreqAdj1 : onpulse  = FreqAdj1 * 25
  ReadAdc10 C.0, FreqAdj2 : offpulse = FreqAdj2 * 25
  High B.6
  Pause onpulse
  Low B.6
  Pause offpulse
Loop
Hi
I need code similar to this above that Hippy wrote for me, but for much shorter pulses
I need a square wave output that can be pot adjusted from 50Hz to 500Hz and also the duty cycle to be pot adjusted. Duty cycle between 10 and 50%.
And I need to do it on an 08M if possible
Regards
Vissie
 

AllyCat

Senior Member
Hi,

In principle you should be able to generate the output waveform with simple PULSOUT and PAUSEUS commands, but you will need to change how or when the Potentiometers are read. With a 500 Hz output at 50% duty cycle there is only a 1 ms gap between the LOW ant HIGH instructions and you certainly can't read two ADC inputs and do the calculations in that time. Particularly if using an 08M with a maximum clock frequency of 8 MHz, but it would be quite tricky even with an M2 at 32 MHz.

A possible solution would be to use a/the PWM output, but that can't be used (easily) below about 65 Hz, which doesn't quite meet your specification. Or, using your present concept, you could add a push-button to instruct the program to (briefly stop the output pulses and) read the Pots and update the pulse width and gap values. But anyway, it's best to start with a clear specification, for example are you building a "Frequency Generator" or a "Pulse Generator":

You have said that you want the Pots. to control "Frequency" and "Duty Cycle" ranges, but you have Symbolised the Pot. inputs as "FreqAdj1" and "FreqAdj2" which are NOT even Frequency controls, but Period (time delay) values. Also,both Pots control the frequency so you can't use a "Pointer Knob" (or even the scewdriver slot of a pre-set type) with a marked scale to indicate the frequency. If you actually want the pots to control "Pulse High time" and "Period between Pulses" then that can be done, but it's best to call them that !

Note that the Pulse (High) time has a large range, from 10% of 2ms (i.e. at 500 Hz) to 50% of 20ms (i.e. at 50 Hz), or 0.2 to 10 ms = 1 : 50. But a dedicated "Frequency" control would need a range of only 1 : 10, and the "Duty Cycle" control a range of 1 : 5. Then, the frequency is determined by the sum of the (Pulse) High and Low times (e.g. Period = Onpulse + Offpulse), but to make the Pot. rotate in the "Correct Direction" (i.e. increasing the ADCINput voltage Increases the frequency) and perhaps to give a better "Law" (Logarithmic versus Linear scale) needs a mathematical Division, e.g. Period = {A scale constant} / Frequency where the Constant is chosen to give a suitable integer result range. Similarly, a Duty Cycle Pot. can determine the Onpulse time by multiplication (and scaling) , e.g. Onpulse = TotalPeriod * DutyCycle * ScaleConstant and of course the Offpulse = Period - Onpulse.

So quite a lot of "Food for Thought" to define how you actually want to use the "Pulse Generator" hardware, or how the program should work.

Cheers, Alan.
 

Visser

Well-known member
Hi,

In principle you should be able to generate the output waveform with simple PULSOUT and PAUSEUS commands, but you will need to change how or when the Potentiometers are read. With a 500 Hz output at 50% duty cycle there is only a 1 ms gap between the LOW ant HIGH instructions and you certainly can't read two ADC inputs and do the calculations in that time. Particularly if using an 08M with a maximum clock frequency of 8 MHz, but it would be quite tricky even with an M2 at 32 MHz.

A possible solution would be to use a/the PWM output, but that can't be used (easily) below about 65 Hz, which doesn't quite meet your specification. Or, using your present concept, you could add a push-button to instruct the program to (briefly stop the output pulses and) read the Pots and update the pulse width and gap values. But anyway, it's best to start with a clear specification, for example are you building a "Frequency Generator" or a "Pulse Generator":

You have said that you want the Pots. to control "Frequency" and "Duty Cycle" ranges, but you have Symbolised the Pot. inputs as "FreqAdj1" and "FreqAdj2" which are NOT even Frequency controls, but Period (time delay) values. Also,both Pots control the frequency so you can't use a "Pointer Knob" (or even the scewdriver slot of a pre-set type) with a marked scale to indicate the frequency. If you actually want the pots to control "Pulse High time" and "Period between Pulses" then that can be done, but it's best to call them that !

Note that the Pulse (High) time has a large range, from 10% of 2ms (i.e. at 500 Hz) to 50% of 20ms (i.e. at 50 Hz), or 0.2 to 10 ms = 1 : 50. But a dedicated "Frequency" control would need a range of only 1 : 10, and the "Duty Cycle" control a range of 1 : 5. Then, the frequency is determined by the sum of the (Pulse) High and Low times (e.g. Period = Onpulse + Offpulse), but to make the Pot. rotate in the "Correct Direction" (i.e. increasing the ADCINput voltage Increases the frequency) and perhaps to give a better "Law" (Logarithmic versus Linear scale) needs a mathematical Division, e.g. Period = {A scale constant} / Frequency where the Constant is chosen to give a suitable integer result range. Similarly, a Duty Cycle Pot. can determine the Onpulse time by multiplication (and scaling) , e.g. Onpulse = TotalPeriod * DutyCycle * ScaleConstant and of course the Offpulse = Period - Onpulse.

So quite a lot of "Food for Thought" to define how you actually want to use the "Pulse Generator" hardware, or how the program should work.

Cheers, Alan.
Hi Alan
What I need is a square wave signal to drive one of the phases of a direct drive washing machine. It works well with a 30V ac sine wave of 50 Hz.
I got it running with a square wave of 50Hz at about 30% duty cycle. And If I can get it to run at a certain duty cycle I need the duty cycle to not vary as I take the frequency up to see if the motor will run faster.
Using the minimum PWM output from 61 Hz can also work for me.
I have a square wave oscillator using a cd 4093 chip, but when I adjust the frequency up the duty cycle also change. I was hoping the picaxe would be able to solve that problem. So its fine if I can adjust the duty to say 40% and then leave it untouched while I only adjust the frequency
Will that be possible?
 

tmfkam

Senior Member
For initial experimentation purposes, you could rig up a simple 555 timer. It is possible to use them to generate a variable frequency with adjustable PWM. As I recall, the frequency and PWM interact with one another a little but might be enough to prove your theory before moving on to something more elegant?
 

tmfkam

Senior Member
I designed a unit that generates a variable PWM at a variable (low) frequency for work (in a different dialect of BASIC). To get around the problem of leaving 'glitches' in the duty cycle and frequency I generate a fixed number of cycles, say 100, at the current parameters, read the values from a pot then generate another fixed number of cycles at the 'new' parameters, check the pots again... This works very well. There is a small delay before the frequency or PWM is updated, depending on how many cycles are produced and at what frequency. There is also a small dropout every 100 cycles, though this is minimal. This is all done by calculating the delays required for setting a pin high then low at a given frequency then setting that pin high or low for the percentage of time to give the required duty cycle.

I can gladly post the demonstration code, it wouldn't (shouldn't?) take much work to convert it from the current dialect to PicAxe BASIC. Though I might be tempted to start from scratch. It is often easier to extract the idea, than it is to extract the code.
 

Visser

Well-known member
I designed a unit that generates a variable PWM at a variable (low) frequency for work (in a different dialect of BASIC). To get around the problem of leaving 'glitches' in the duty cycle and frequency I generate a fixed number of cycles, say 100, at the current parameters, read the values from a pot then generate another fixed number of cycles at the 'new' parameters, check the pots again... This works very well. There is a small delay before the frequency or PWM is updated, depending on how many cycles are produced and at what frequency. There is also a small dropout every 100 cycles, though this is minimal. This is all done by calculating the delays required for setting a pin high then low at a given frequency then setting that pin high or low for the percentage of time to give the required duty cycle.

I can gladly post the demonstration code, it wouldn't (shouldn't?) take much work to convert it from the current dialect to PicAxe BASIC. Though I might be tempted to start from scratch. It is often easier to extract the idea, than it is to extract the code.
Thank you. You may post t the demonstration code , but I'm not sure if I will be able to do something with it with my programming knowledge...
In the meantime I will work out a 555 circuit to try. Thank you
It seems like in an astable 555 circuit the duty cycle can never be 50% or lower when I look at the online calculators. So maybe using an inverter mosfet driver will do the thing.
I had a look at the PWM wizard and see that its easy to keep the frequency constant and change the duty cycle by pots but not the other way round.....
 
Last edited:

Goeytex

Senior Member
It seems like in an astable 555 circuit the duty cycle can never be 50% or lower when I look at the online calculators.
It certainly can. You can get a free copy of "555 Timer Pro" . It will show several methods for achieving duty cycle < 50%

You can also use a 555 timer along with a comparator or op amp to generate a nice adjustable PWM from 0 - 100 percent duty
 
Last edited:

AllyCat

Senior Member
Hi,

Yes, it's easier to arrange a "hardware" oscillator to give a frequency that is controlled by a single pot., than a "software" (PICaxe) arrangement which tends to have High and Low cycle times (as the thread title suggests). The same applies to the on-chip PWM hardware, which has another disadvantage that the frequency may "glitch" (or jump) whenever the values are changed. PICaxe has a PWMDUTY command to change the Duty Cycle with a constant Frequency, but NOT a method to change the Frequency with a constant Duty Cycle. Glitches might cause problems if controlling an ac motor.

However, it is possible to arrange a program to calculate suitable High and Low "Pause" values for any given Frequency and Duty Cycle inputs (defined by separate Pot. levels). I was going to see what could be achieved with an 08M, but it appears that this chip is so "old" that it only operates up to 8 MHz, it does not have the PAUSEUS command, nor the PWMDIV64 parameter (so it cannot operate below about 240 Hz). Therefore, I've written test code for an M2, which can operate at up to 32 MHz. Only checked in the Simulator and I had to "guess" at some of the timing parameters, but I believe it should work with "independent" Pot. controls for 50 - 500 Hz and a Duty Cycle range of 20% - 60%. In principle those ranges can be changed by some of the "Magic Numbers", but there are more than I would normally include, because there are too many "Unknowns" at the moment.

If you set the Frequency Pot. to minimum (earth) and Duty Cycle to middle of track then you may be able (or need) to "calibrate" the Frequency to 50 Hz and a Duty Cycle of 40% by changing the symbol values for ONMIN and OFFMIN. These values are also used as "Endstops" to prevent the program calculating values that give "impossible" (negative) time delays, so the Pots might not give adjustment over their full range(s).
Code:
#picaxe 08m2
symbol onpulse = w2        ; Min = 2ms * 20% = 400us, Max = 20ms * 60% = 12000us
symbol offpulse = w3        ; Min = 2ms * 60% = 1200us, Max = 20ms * 80% = 16000us
symbol freqadc = w4        ; Minimum (0) = 50 Hz, Max (255) = 500 Hz
symbol dutyadc = w5        ; Centre (128) = 40%, range (0 - 255) = 20 - 60%
symbol period = w6         ; 40000 @ 50Hz (ADC=0)/28; 4000 @ 500Hz (adc = 255)/280
symbol freqpin = c.4
symbol dutypin = c.1
symbol outpin = c.2
symbol ONMIN = 260        ; Pauseus units
symbol OFFMIN = 850        ; Pauseus units

setfreq m32                    ; Pauseus units = 1.25 us
    freqadc = 0                ; For 50 Hz (255 = 500 Hz)
    dutyadc = 128             ; For 40%    (0 = 20%, 255 = 60%)
do
    LOW outpin                                                        ; 30 = Total 260 pauseus units
    freqadc = freqadc + 28                                        ; 70
    period = 64000 / freqadc * 7                                ;200
    onpulse = dutyadc + 128 * 102                                ;150 ; 100% = 65536
    onpulse = onpulse ** period MIN ONMIN - ONMIN        ;150
    offpulse = period - onpulse MIN OFFMIN - OFFMIN        ;100
    PAUSEUS offpulse                                                ;+70
    readadc freqpin,freqadc                                        ; 80
    HIGH outpin                                                        ; 30 = Total 850 pauseus units
    readadc dutypin,dutyadc                                        ; 80
    PAUSEUS onpulse                                                ;+70
loop                                                                    ; 80
Cheers, Alan.
 

Visser

Well-known member
Hi,

Yes, it's easier to arrange a "hardware" oscillator to give a frequency that is controlled by a single pot., than a "software" (PICaxe) arrangement which tends to have High and Low cycle times (as the thread title suggests). The same applies to the on-chip PWM hardware, which has another disadvantage that the frequency may "glitch" (or jump) whenever the values are changed. PICaxe has a PWMDUTY command to change the Duty Cycle with a constant Frequency, but NOT a method to change the Frequency with a constant Duty Cycle. Glitches might cause problems if controlling an ac motor.

However, it is possible to arrange a program to calculate suitable High and Low "Pause" values for any given Frequency and Duty Cycle inputs (defined by separate Pot. levels). I was going to see what could be achieved with an 08M, but it appears that this chip is so "old" that it only operates up to 8 MHz, it does not have the PAUSEUS command, nor the PWMDIV64 parameter (so it cannot operate below about 240 Hz). Therefore, I've written test code for an M2, which can operate at up to 32 MHz. Only checked in the Simulator and I had to "guess" at some of the timing parameters, but I believe it should work with "independent" Pot. controls for 50 - 500 Hz and a Duty Cycle range of 20% - 60%. In principle those ranges can be changed by some of the "Magic Numbers", but there are more than I would normally include, because there are too many "Unknowns" at the moment.

If you set the Frequency Pot. to minimum (earth) and Duty Cycle to middle of track then you may be able (or need) to "calibrate" the Frequency to 50 Hz and a Duty Cycle of 40% by changing the symbol values for ONMIN and OFFMIN. These values are also used as "Endstops" to prevent the program calculating values that give "impossible" (negative) time delays, so the Pots might not give adjustment over their full range(s).
Code:
#picaxe 08m2
symbol onpulse = w2        ; Min = 2ms * 20% = 400us, Max = 20ms * 60% = 12000us
symbol offpulse = w3        ; Min = 2ms * 60% = 1200us, Max = 20ms * 80% = 16000us
symbol freqadc = w4        ; Minimum (0) = 50 Hz, Max (255) = 500 Hz
symbol dutyadc = w5        ; Centre (128) = 40%, range (0 - 255) = 20 - 60%
symbol period = w6         ; 40000 @ 50Hz (ADC=0)/28; 4000 @ 500Hz (adc = 255)/280
symbol freqpin = c.4
symbol dutypin = c.1
symbol outpin = c.2
symbol ONMIN = 260        ; Pauseus units
symbol OFFMIN = 850        ; Pauseus units

setfreq m32                    ; Pauseus units = 1.25 us
    freqadc = 0                ; For 50 Hz (255 = 500 Hz)
    dutyadc = 128             ; For 40%    (0 = 20%, 255 = 60%)
do
    LOW outpin                                                        ; 30 = Total 260 pauseus units
    freqadc = freqadc + 28                                        ; 70
    period = 64000 / freqadc * 7                                ;200
    onpulse = dutyadc + 128 * 102                                ;150 ; 100% = 65536
    onpulse = onpulse ** period MIN ONMIN - ONMIN        ;150
    offpulse = period - onpulse MIN OFFMIN - OFFMIN        ;100
    PAUSEUS offpulse                                                ;+70
    readadc freqpin,freqadc                                        ; 80
    HIGH outpin                                                        ; 30 = Total 850 pauseus units
    readadc dutypin,dutyadc                                        ; 80
    PAUSEUS onpulse                                                ;+70
loop                                                                    ; 80
Cheers, Alan.
Wow. Thank you. I will go get some 08M2 chips on Monday and try this.
 

tmfkam

Senior Member
For the 555 circuit, I was thinking of something like this circuit. It should do 0-100% duty. If not, close to. I've used similar designs in a number of quick PWM projects, light dimmers and brushed motor speed controllers.

24638
 

tmfkam

Senior Member
The code provided by AllyCat (Alan) above does much the same as my code. As mine is not in PicAxe BASIC, I see little point in posting it.

The changes I would make would be to enclose the PWM generation commands in a loop that repeated a fixed number of times, then grab the pot values, calculate the time delays again then generate a fixed number of cycles of PWM.

Alan's code:
Code:
#picaxe 08m2
symbol onpulse = w2        ; Min = 2ms * 20% = 400us, Max = 20ms * 60% = 12000us
symbol offpulse = w3        ; Min = 2ms * 60% = 1200us, Max = 20ms * 80% = 16000us
symbol freqadc = w4        ; Minimum (0) = 50 Hz, Max (255) = 500 Hz
symbol dutyadc = w5        ; Centre (128) = 40%, range (0 - 255) = 20 - 60%
symbol period = w6         ; 40000 @ 50Hz (ADC=0)/28; 4000 @ 500Hz (adc = 255)/280
symbol freqpin = c.4
symbol dutypin = c.1
symbol outpin = c.2
symbol ONMIN = 260        ; Pauseus units
symbol OFFMIN = 850        ; Pauseus units

setfreq m32                    ; Pauseus units = 1.25 us
    freqadc = 0                ; For 50 Hz (255 = 500 Hz)
    dutyadc = 128             ; For 40%    (0 = 20%, 255 = 60%)

Do
    LOW outpin                                                        ; 30 = Total 260 pauseus units
    freqadc = freqadc + 28                                        ; 70
    period = 64000 / freqadc * 7                                ;200
    onpulse = dutyadc + 128 * 102                                ;150 ; 100% = 65536
    onpulse = onpulse ** period MIN ONMIN - ONMIN        ;150
    offpulse = period - onpulse MIN OFFMIN - OFFMIN        ;100
    PAUSEUS offpulse                                                ;+70
    readadc freqpin,freqadc                                        ; 80
    HIGH outpin                                                        ; 30 = Total 850 pauseus units
    readadc dutypin,dutyadc                                        ; 80
    PAUSEUS onpulse                                                ;+70
loop
Changed by me to pseudo code:
The "Repeat - End Repeat" may need changing to a For - Next loop?

Code:
#picaxe 08m2
symbol onpulse = w2        ; Min = 2ms * 20% = 400us, Max = 20ms * 60% = 12000us
symbol offpulse = w3        ; Min = 2ms * 60% = 1200us, Max = 20ms * 80% = 16000us
symbol freqadc = w4        ; Minimum (0) = 50 Hz, Max (255) = 500 Hz
symbol dutyadc = w5        ; Centre (128) = 40%, range (0 - 255) = 20 - 60%
symbol period = w6         ; 40000 @ 50Hz (ADC=0)/28; 4000 @ 500Hz (adc = 255)/280
symbol freqpin = c.4
symbol dutypin = c.1
symbol outpin = c.2
symbol ONMIN = 260        ; Pauseus units
symbol OFFMIN = 850        ; Pauseus units

setfreq m32                    ; Pauseus units = 1.25 us
    freqadc = 0                ; For 50 Hz (255 = 500 Hz)
    dutyadc = 128             ; For 40%    (0 = 20%, 255 = 60%)

Do
    LOW outpin    ; 30 = Total 260 pauseus units
   
    readadc freqpin,freqadc                                        ; 80
    readadc dutypin,dutyadc                                        ; 80

  
    freqadc = freqadc + 28                                        ; 70
    period = 64000 / freqadc * 7                                ;200
    onpulse = dutyadc + 128 * 102                                ;150 ; 100% = 65536
    onpulse = onpulse ** period MIN ONMIN - ONMIN        ;150
    offpulse = period - onpulse MIN OFFMIN - OFFMIN        ;100
  
    Repeat 100 ;Code to be repeated to generate 100 continuous cycles
      LOW outpin
      PAUSEUS offpulse                                                ;+70
      HIGH outpin                                                        ; 30 = Total 850 pauseus unit
      PAUSEUS onpulse                                                ;+70
    End Repeat
loop
 
Last edited:

Visser

Well-known member
Hi,

Personally, I've never found the need for the multitasking feature of M2s (it's an "easy" way to do mutitasking) so you can use one of your 08Ms. Just use the code I gave to replace your section beginning "SYMBOL....".

If the input is above 4.8 volts then the program will output a 20ms pulse and then "fall through" into the second part, but you would need to change the first "GOTO main" to "GOTO start2" to execute the second part. So perhaps it's better to re-write the whole program to use "structured" code without any GOTOs at all:

Code:
#Picaxe 08M
#No_Data
SYMBOL SENSEPIN = PIN3
SYMBOL ADCI = 4                 ; ADC Input
    Low 1                               ; Initialise for pulsout
do
    readadc ADCI , b0               ; read ADC1 into variable b0
    IF b0 > 245 then                 ;  pulse if voltage > 4.8v (If 5volt supply)
        pulsout 1 , 2000           ; pulse output #1 for 20 ms (or could still use the HIGH.. :  PAUSE .. :  LOW .. structure)
    ENDIF
    IF SENSEPIN = 1 THEN
        pwmout 2 , 3 , 7              ; 250KHz at 50%
    ELSE
        pwmout 2 , OFF
    ENDIF
loop
Cheers, Alan.
Hi Alan
If I only want to use this part of the code, but I want to be able to adjust that "pulsout 1 , 2000" with a pot on a adc input. How can that be done
I found that the period I need is more like 2 msec instead of 200msec so I changed it to pulsout 1 , 200
But I want to be able to adjust it as the situation change from say about 1msec to 200Msec as now I have to remove the chip every time and put it into my program board and try again
What it does is to discharge a capacitor when it reach a certain voltage and that happens real fast and I want the pulse to go low as soon as the cap is discharged so it can start charging again. I found that the discharge periods are different for different uF size caps
Is that possible?

Code:
#Picaxe 08M
#No_Data
SYMBOL SENSEPIN = PIN3
SYMBOL ADCI = 4                 ; ADC Input
    Low 1                               ; Initialise for pulsout
do
    readadc ADCI , b0               ; read ADC1 into variable b0
    IF b0 > 245 then                 ;  pulse if voltage > 4.8v (If 5volt supply)
        pulsout 1 , 2000           ; pulse output #1 for 20 ms (or could still use the HIGH.. :  PAUSE .. :  LOW .. structure)
    ENDIF
 

AllyCat

Senior Member
Hi,
What it does is to discharge a capacitor when it reach a certain voltage ....... and I want the pulse to go low as soon as the cap is discharged ...
SYMBOL ADCI = 4 ; ADC Input
What is ADCI ? A potentiometer wiper, or the Voltage across a Capacitor ?

If you're trying to create a Ramp-Generator / Oscillator, rather like a 555 timer, then you could emulate that directly with something like:
Code:
do
   Low 1
   do
      readadc ADCI , b0       ; Voltage on Capacitor
   loop while b0 < 245       ; Wait for upper threshold (Vdd * 96%)
   High 1
   do
      readadc ADCI , b0
   loop while b0 > 10           ; Wait for lower threshold (will probably overshoot to Vss)
loop
Or if you want a long (variable) Pulsout, then you could get up to 650 ms using PULSOUT 1 , w1 (e.g. with w1 = b0 * 80 for up to 200ms), but the problem with a large range is that the resolution at the low end will be rather coarse, typically steps of nearly 1 ms (using READADC).

However, you could emulate a "LOGarithmic" Pot (from a normal LINear Pot) to give "Piecewise Linear" scales of 200us - 5ms and 5ms - 200ms with something like:
Code:
   readadc ADCI, b0
   if b0 < 120 then
      w1 = b0 * 4 + 20               ;  200 - 5000 us (40 us steps)
   else
      w1 = b0 - 120 * 145 + 500         ; 5 - 201 ms   (1.45 ms steps)
   endif
   pulsout  1 , w1
Cheers, Alan.
 

Visser

Well-known member
Hi,

What is ADCI ? A potentiometer wiper, or the Voltage across a Capacitor ?

If you're trying to create a Ramp-Generator / Oscillator, rather like a 555 timer, then you could emulate that directly with something like:
Code:
do
   Low 1
   do
      readadc ADCI , b0       ; Voltage on Capacitor
   loop while b0 < 245       ; Wait for upper threshold (Vdd * 96%)
   High 1
   do
      readadc ADCI , b0
   loop while b0 > 10           ; Wait for lower threshold (will probably overshoot to Vss)
loop
Or if you want a long (variable) Pulsout, then you could get up to 650 ms using PULSOUT 1 , w1 (e.g. with w1 = b0 * 80 for up to 200ms), but the problem with a large range is that the resolution at the low end will be rather coarse, typically steps of nearly 1 ms (using READADC).

However, you could emulate a "LOGarithmic" Pot (from a normal LINear Pot) to give "Piecewise Linear" scales of 200us - 5ms and 5ms - 200ms with something like:
Code:
   readadc ADCI, b0
   if b0 < 120 then
      w1 = b0 * 4 + 20               ;  200 - 5000 us (40 us steps)
   else
      w1 = b0 - 120 * 145 + 500         ; 5 - 201 ms   (1.45 ms steps)
   endif
   pulsout  1 , w1
Cheers, Alan.
Hi. I want to use a 10K linear pot over 5v range
I do think a pulse between 1 to 50 msec will be enough as a cap discharge very fast into a battery
The code as is works perfect
I only want to able to adjust this part,
pulsout 1 , 2000 with a pot between 1 to 50 msec
 
Last edited:

AllyCat

Senior Member
Hi,

The READADC ADCI , b0 will read a value range of 0 to 255 . You require a PULSOUT 1 , w1 range of 100 to 5000 (10us units) so first calculate 5000 - 100 / 255 (which equals 19. 21) that you can write in the program, or pre-calculate it as : w1 = 19 * b0 + 100 which should get from 1.0 ms up to 49.5 ms. Or use a multiplier of 20 to go slightly past 50 ms.
Code:
#picaxe 08m
readadc 4 , b0
w1 = 5000 - 100 / 255 * b0 + 100
pulsout 1 , w1
Cheers, Alan.
 

Visser

Well-known member
Hi
It must still do this:

#Picaxe 08M
#No_Data
SYMBOL ADCI = 4 ; ADC Input
Low 1 ; Initialise for pulsout
do
readadc ADCI , b0 ; read ADC1 into variable b0
IF b0 > 245 then ; pulse if voltage > 4.8v (If 5volt supply)
pulsout 1 , 200 ; pulse output #1 for 2 ms (or could still use the HIGH.. : PAUSE .. : LOW .. structure)
ENDIF
loop

But I want to be able to control the pulse width (pulsout 1 , 200) with a pot on adc 2 input
Sorry for the confusion from my side
 

AllyCat

Senior Member
Hi,

It seems that you just need to change the Readadc command in my previous post to READADC 2 , w1 and put those lines of code in place of your PULSOUT 1 , 200 command.

I do think a pulse between 1 to 50 msec will be enough as a cap discharge very fast into a battery
LOW 1 : PULSOUT 1 , w1 is almost identical to HIGH 1 : PAUSEUS w1 : LOW 1 but only the PULSOUT (not PAUSEUS) is available with the 08M PICaxe. You can't use the HIGH xxx : PAUSE xxx : LOW xxx structure to (accurately) control pulses as short as 1 ms.

Cheers, Alan.
 

Visser

Well-known member
Hi,

It seems that you just need to change the Readadc command in my previous post to READADC 2 , w1 and put those lines of code in place of your PULSOUT 1 , 200 command.


LOW 1 : PULSOUT 1 , w1 is almost identical to HIGH 1 : PAUSEUS w1 : LOW 1 but only the PULSOUT (not PAUSEUS) is available with the 08M PICaxe. You can't use the HIGH xxx : PAUSE xxx : LOW xxx structure to (accurately) control pulses as short as 1 ms.

Cheers, Alan.
Cool thank you!!! It simulates nice. I will try and post a video some time of scope as cap charge up and discharge while I adjust the pot for discharge time. Just have some real work to do first.

#Picaxe 08M
#No_Data
SYMBOL ADCI = 4 ; ADC Input
Low 1 ; Initialise for pulsout
do
readadc ADCI , b0 ; read ADC1 into variable b0
IF b0 > 245 then ; pulse if voltage > 4.8v (If 5volt supply)
readadc 2 , W1
w1 = 5000 - 100 / 255 * b0 + 100
pulsout 1 , w1 ; pulse output #1 ,pot ADJUSTED between 1 to 50 msec
ENDIF
loop
 
Top