Counter and ASM Question
Hey there,
I'm trying to learn ASM for the prop. Right now I'm going through the Propeller Counters document. As far as I can understand you basically have two counters per cog. Does that mean that you could have two separate PWM generators per cog? I'd like to know if it is possible before I embark on my journey to modify the below into something that generates two different PWM signal on two separate pins. I don't want to strand my (asm)-ship before I've even set sail. So if it's doable, please let me know. I am not looking for the code, I'd like to try that myself, only to know if it can be done [noparse]:)[/noparse]
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
I'm trying to learn ASM for the prop. Right now I'm going through the Propeller Counters document. As far as I can understand you basically have two counters per cog. Does that mean that you could have two separate PWM generators per cog? I'd like to know if it is possible before I embark on my journey to modify the below into something that generates two different PWM signal on two separate pins. I don't want to strand my (asm)-ship before I've even set sail. So if it's doable, please let me know. I am not looking for the code, I'd like to try that myself, only to know if it can be done [noparse]:)[/noparse]
{{
Demonstration of scaling Duty Cycle
}}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long parameter
PUB go | x
cognew(@entry, @parameter)
repeat
'parameter := 50
repeat x from 0 to period ' linearly advance parameter from 0 to 100
parameter := x ' a constant here locks to x percent high
waitcnt(1000 + cnt) ' wait a little while before the next update
DAT
org
entry mov dira, diraval ' set APIN to output
mov ctra, ctraval ' establish counter A mode and APIN
mov frqa, #1 ' set counter to increment 1 each cycle
mov time, cnt ' record current time
add time, period ' establish next period
:loop rdlong value, par ' get an up to date duty cycle
waitcnt time, period ' wait until next period
neg phsa, value ' backup up phsa so that it
jmp #:loop ' loop for next cycle
diraval long |< 0 ' APIN direction (0)
ctraval long %00100 << 26 + 0 ' NCO/PWM APIN=0 {BPIN=1} <- not used
period long 100 ' 800kHz period ( clkfreq / period )
time res 1
value res 1
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
Comments
{{ Demonstration of scaling Duty Cycle }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 VAR long parameter PUB go | x cognew(@entry, @parameter) repeat 'parameter := 50 repeat x from 0 to period ' linearly advance parameter from 0 to 100 parameter[noparse][[/noparse]0] := x ' a constant here locks to x percent high parameter := period - x waitcnt(1000 + cnt) ' wait a little while before the next update DAT org entry mov dira, diraval ' set APIN to output mov ctra, ctraval ' establish counter A mode and APIN mov frqa, #1 ' set counter to increment 1 each cycle mov ctrb, ctrbval ' establish counter B and mov frqb, #1 mov time, cnt ' record current time add time, period ' establish next period :loop rdlong value, par ' get an up to date duty cycle mov value2, par add value2, #4 ' Get the address for the 2nd long rdlong value2, value2 ' read the 2nd argument from the HUB waitcnt time, period ' wait until next period neg phsa, value neg phsb, value2 jmp #:loop ' loop for next cycle diraval long |< 2 + |< 3 ' APIN direction (0) ctraval long %00100 << 26 + 2 ' NCO/PWM APIN=3 ctrbval long %00100 << 26 + 3 ' NCO/PWM APIN=4 period long 1000 ' 800kHz period ( clkfreq / period ) time res 1 value res 1 value2 res 1
Also, this is running at a breakneck speed of 800kHz, which is great when you're running this program in GEAR, but what kind of frequency should I be looking at when using PWM for a motor? 800kHz seems a little excessively fast. I am also going to need some diodes apart from the H bridge. What kind should I get? The max current the motors draw when stalled is about 1A. I saw on voti.nl (a local-ish online electronic shop) that the UF4007 is fast and can deal with 1A. Would this do the trick for me?
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
mov time, cnt ' record current time add time, period ' establish next period
Why "period" .. this is highly irrelevant in this place...
When you enter the loop you will first wait THIS time before any PHS is set.
diraval long |< 2 + |< 3 ' APIN direction (0) ctraval long %00100 << 26 + 2 ' NCO/PWM APIN=3 ctrbval long %00100 << 26 + 3 ' NCO/PWM APIN=4
I should use constant NAMES rather "1" and "2"
period long 1000 ' 800kHz period ( clkfreq / period )
You can read the ckfreq value also in "PASM" - do you know how?
mov time, cnt ' record current time add time, period ' establish next period
Well, to be honest with you, I copied most of this code from the Propeller counter application notes code examples. I merely tweaked to be able to handle two PWM signals [noparse]:)[/noparse] Why is it highly irrelevant? What would be more appropriate?
period long 1000 ' 800kHz period ( clkfreq / period )
No, I do not. What would that allow me to do in this case? I picked 1000 because it allows me to see the waves very nicely in the GEAR simulator when it runs at 80MHz. In the Prop manual I see this: My guess is that this has something to do with it, although tbh, I am not sure yet in what way [noparse]:)[/noparse]
Thanks for looking at this stuff and giving me feedback, it's highly appreciated.
Gr,
Mightor
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
| To know recursion, you must first know recursion.
You see, you are entering the main loop at its WAIT-instruction, without presetting the PWM mechanism. So what is the use of waiting? Or how long? Why "period". Well it's a value as any value... Nevertheless it can also be a shorter or a longer time - what I wanted to say: No connection with the "period " in any way here. I myself would have coded:
mov time, cnt ' record current time add time, period ' establish next period JMP #:loopEntry :loop rdlong value, par ' get an up to date duty cycle mov value2, par add value2, #4 ' Get the address for the 2nd long rdlong value2, value2 ' read the 2nd argument from the HUB waitcnt time, period ' wait until next period :loopEntry neg phsa, value neg phsb, value2 jmp #:loop
But as it is generally frowned upon using "unstructured" constructs, you can now reshape the loop:
mov time, cnt ' record current time add time, period ' establish next period :loop rdlong value, par ' get an up to date duty cycle mov value2, par add value2, #4 ' Get the address for the 2nd long rdlong value2, value2 ' read the 2nd argument from the HUB neg phsa, value neg phsb, value2 waitcnt time, period ' wait until next period jmp #:loop
Using the clock frequency stored in HUB cell 0 is easy
[noparse][[/noparse]code]
RDLONG t0, #0 ' read clock frequency
MOV t1, reqFreq
CALL #divide
MOV period, t0
reqFreq LONG 80_000 ' 80 kHz
I think it's 80kHz you are using, not 800...
You of course have to insert the standard 32/16 bit division routine..
However the values have now be harmonized with the values read from memory... At the moment you use "per thousend" which is quite transparent and will work (the duty cycle at least) independent of the clock speed.
But it is always a good idea to set the _PLLX to 4 from time to time , just to see whether one's program still runs with another clock...