Is there any more example code for the COG timers? I have studied the wave playing example and sort of understand it (been wading through the Parallax docs), would be good to
have some other other examples though ... i.e pulse PWM, motor control, Freq/Duty measurement etc ... the timers are so powerful, I would like to get my head around them ...
Is there any more example code for the COG timers? I have studied the wave playing example and sort of understand it (been wading through the Parallax docs), would be good to
have some other other examples though ... i.e pulse PWM, motor control, Freq/Duty measurement etc ... the timers are so powerful, I would like to get my head around them ...
Cheers,
Bernie
There's the PWM code that's built in for 8 channels although it's a fairly easy matter to make it 32 channels so that you can choose arbitrary pins to suit. There's also the DAC function which could just as easily have a VOLTS function frontend to make it easier to set a voltage. So besides these and the frequency generation words that you can play with I think that it's easy enough to go to the next step of measuring etc. Have you had a look at the Introduction page? If you have something specific in mind I can work on that.
I actually have the W5200 code and FAT32 file + virtual memory available soon. It's all been dragging out as a WIP until I start feeling the whip itself after which I get the job finished. Let me know if there are specific chips that need interfacing such as the RTCs and Bluetooth etc.
There's the PWM code that's built in for 8 channels although it's a fairly easy matter to make it 32 channels so that you can choose arbitrary pins to suit. There's also the DAC function which could just as easily have a VOLTS function frontend to make it easier to set a voltage. So besides these and the frequency generation words that you can play with I think that it's easy enough to go to the next step of measuring etc. Have you had a look at the Introduction page? If you have something specific in mind I can work on that.
Hmmm, been looking at the PWM code ... very confused. Code is:
org _RUNMOD
_PWM mov deltaR,tos ' use supplied delta value from tos
mov target,tos
add target,cnt
mov R1,#0
pwmlp mov X,REG0 ' read base address of table
add X,R1 ' add in read index
rdbyte X,X
shl X,REG1 ' shift up to pwmpins
mov outa,X ' update outputs
add R1,#1
and R1,#$FF
waitcnt target,deltaR
jmp #pwmlp
PWM byte _WORD,(@_PWM+s)>>8,@_PWM+s,_BYTE,13,XOP,xLOADMOD,EXIT
It seems to me that your only using the cog timer for a delay right? all io is bit-bashed rather than using outa,outb?
Also, I don't see how the above loop ends ... and ther is no jump to next or drop at the end of the code ... where does it go to?
Seems I am missing a big chunk of information here ... also "org _RUNMOD" confuses me as it is used above each PASM code module, doesn't that mean they will all be assembled at the same place in memory?
My head hurts.....
EDIT: Why is the code I post all mashed up ... tried copy/pasting through different editors but still rubbish ..
Hmmm, been looking at the PWM code ... very confused. Code is:
org _RUNMOD
_PWM mov deltaR,tos ' use supplied delta value from tos
mov target,tos
add target,cnt
mov R1,#0
pwmlp mov X,REG0 ' read base address of table
add X,R1 ' add in read index
rdbyte X,X
shl X,REG1 ' shift up to pwmpins
mov outa,X ' update outputs
add R1,#1
and R1,#$FF
waitcnt target,deltaR
jmp #pwmlp
PWM byte _WORD,(@_PWM+s)>>8,@_PWM+s,_BYTE,13,XOP,xLOADMOD,EXIT
It seems to me that your only using the cog timer for a delay right? all io is bit-bashed rather than using outa,outb?
Also, I don't see how the above loop ends ... and ther is no jump to next or drop at the end of the code ... where does it go to?
Seems I am missing a big chunk of information here ... also "org _RUNMOD" confuses me as it is used above each PASM code module, doesn't that mean they will all be assembled at the same place in memory?
My head hurts.....
EDIT: Why is the code I post all mashed up ... tried copy/pasting through different editors but still rubbish ..
Bernie
COG memory is very limited and Tachyon squeezes the VM and stacks in there and there's no room really left over for specialized operations that really require PASM. That's where RUNMOD comes in as I sacrifice 16 to 24 longs for specialized modules which are compiled to run at that address but only one module can be loaded at a time. These specialized modules include SPI, I2C, SD, and PWM etc. The PWM module is designed to run in it's own cog as it's an endless loop where another cog/task can control the parameters. Of course the PWM cog doesn't need all the Tachyon VM in it after that but it's easy to load the module in the normal fashion.
So PWM doesn't use the counters, only WAITCNT but you mentioned PWM in your list which is different to duty-cycle modulation ( fixed pulse width, variable frequency).
As for your head hurting can I suggest a Pepperjack Cab Sav. If that doesn't work then increase the dose.
Getting an Asus TF300T tomorrow. Any tips on using the RN-42 with Blueterm?
The DS3231 is compatible enough with the MCP79410 that you should be able to use it as is, just change the device address. The first 7 registers are compatible although the 79410 does uses some of the otherwise unused bits for control purposes but that won't affect the 3231. Try it and let me know how is goes.
The device address can be changed either in the source code: $DE == @rtc
to
$B0 == @rtc
Or you can write directly to the constant at runtime with:
$B0 ' @rtc 1+ !
The RN42 should just work in slave mode and you should be able to change it's default baudrate to 230400.
I'm starting to get close to finishing the FAT32 file support, I've just been getting my head around where everything is and how it works by Googling bits of information and interacting with the code and card to check it all out. I know a FAT32 driver has been written but I haven't referenced it at all which may sound a bit odd seeing that the code is all there. The thing is I would have to get my head around the code and I'd much rather get my head around FAT32 and SDHC cards themselves, that way I can produce a nice clean interface and so far it's been working out that way. The code size is under 1.5K at present and probably will not increase too much more. Here's a capture of a quick session I did in mounting a card, checking the card info and performing a couple of operations on it and even accessing a file as virtual memory (me in red).
since Peter was busy I continued my experiments and now I understand partly,
why it could only work in this special case.
I am revectoring KEY via ukey to read from a string.
which can only work at the end of the input line, when the input loop comes back to calling KEY again.
@Peter
based on your new STRING words I wanted to build an EVAL
which works - almost fine.
BUT:
1. maybe it would be better to suppress the echo of the evaluated string and show just the result
(could be done using NULLOUT & CON see below )
2. if used multiple times in one line or inside a loop, only the last EVAL seems to get executed.
seems I still miss s.th. important
\
pub (EVALSTR) ( strAddr -- )
C@++ DUP 0= IF DROP ukey W~ $0D THEN ; ok
ok
pub EVAL ( strAddr -- \ evaluate the FORTH sentence in the null-teminated string starting at strAddr )
' (EVALSTR) ukey W! ; ok
{ without output
pub (EVALSTR) ( strAddr -- )
C@++ DUP 0= IF DROP CON $0D THEN ;
\ just deliver one char after the other, on last one add $0D to get it executed and set reader back to CONsole
pub EVAL ( strAddr -- \ evaluate the FORTH sentence in the null-teminated string starting at strAddr )
NULLOUT \ suppress output
' (EVALSTR) ukey W! ;
}
" 1 1 + . " EVAL ok
1 1 + . 2 ok
" 2 2 + . " EVAL ok
2 2 + . 4 ok
" : TT1 $17 . ; " $20 STRING TESTSTR ok
TESTSTR EVAL ok
: TT1 $17 . ; ok
TT1 17 ok
ok
\ let's define a WORD, that generates other words ... ( I worked many years with LISP ;-) - so I love EVAL )
: TTT
0 6 ADO "0" I + TESTSTR 4 + C! "0" I + TESTSTR 8 + C! TESTSTR .STR CR TESTSTR [COLOR=#020FC0][B]EVAL [/B][/COLOR]LOOP
; ok
ok
TTT : TT0 $10 . ;
: TT1 $11 . ;
: TT2 $12 . ;
: TT3 $13 . ;
: TT4 $14 . ;
: TT5 $15 . ;
ok
: TT5 $15 . ; ok
so I tried the following modifications, which at least seem to work on the input line.
But it is still not possible to put this inside a loop or definition of a word.
in other words - I can not compile it.
Since now I had to define EVAL as IMMEDIATE to work at least this far.
pub (EVALSTR) ( strAddr -- )
C@++ DUP 0= IF DROP CON $0D THEN ;
\ just deliver one char after the other, on last one add $0D to get it executed and set reader back to CONsole
pub EVAL ( strAddr -- \ evaluate the FORTH sentence in the null-teminated string starting at strAddr )
[COMPILE] GRAB
\ NULLOUT \ suppress output
' (EVALSTR) ukey W! ;
IMMEDIATE
" 1 1 + . " EVAL " 2 2 + . " EVAL " 3 3 + . " EVAL 1 1 +
I assume I need to take a completely different approach for EVAL to do what I imagine.
I'm starting to get close to finishing the FAT32 file support, I've just been getting my head around where everything is and how it works by Googling bits of information and interacting with the code and card to check it all out. I know a FAT32 driver has been written but I haven't referenced it at all which may sound a bit odd seeing that the code is all there. The thing is I would have to get my head around the code and I'd much rather get my head around FAT32 and SDHC cards themselves, that way I can produce a nice clean interface and so far it's been working out that way. The code size is under 1.5K at present and probably will not increase too much more. Here's a capture of a quick session I did in mounting a card, checking the card info and performing a couple of operations on it and even accessing a file as virtual memory (me in red).
COG memory is very limited and Tachyon squeezes the VM and stacks in there and there's no room really left over for specialized operations that really require PASM. That's where RUNMOD comes in as I sacrifice 16 to 24 longs for specialized modules which are compiled to run at that address but only one module can be loaded at a time. These specialized modules include SPI, I2C, SD, and PWM etc. The PWM module is designed to run in it's own cog as it's an endless loop where another cog/task can control the parameters. Of course the PWM cog doesn't need all the Tachyon VM in it after that but it's easy to load the module in the normal fashion.
So PWM doesn't use the counters, only WAITCNT but you mentioned PWM in your list which is different to duty-cycle modulation ( fixed pulse width, variable frequency).
As for your head hurting can I suggest a Pepperjack Cab Sav. If that doesn't work then increase the dose.
Will do ... although I had to replace the Pepperjack with a Local Merlot ..... distinct lack of Oz wines over here ....
By the way, what I am trying to do is this:
My interest is Electric Cars ... currently I am building one based on a 200HP Industrial motor running at 650V. (Biggest problem is the cost of the controller ... even when I got the power module off eBay)
That is all good, but for my next project I would like to use a BLDC motor being driven by a Prop1 (in sensorless mode) or maybe a Prop2 if I run out of resources .... seems to me I can get the cost of the controller right down ...
So I would like to start the coding based on the Prop1 and see how far I get ... and obviously I would like to do this in Tachyon Forth ..
.... So I am thinking for the 3 Phase PWM, maybe I could use 3 cogs running a low level PWM word that could be phase shifted relative to each other .... (using timers)
Another cog would interface to the sensorless circuitry (zero-crossing detector) and would self modify the phase shifting .. (phase shift is normally 60deg in a six step BLDC)
Be interested in what you think of that approach and what the best words would be to achieve the building blocks ..
NB: I have seen the 32 channel PWM code that Parallax have coded up to do this sort of thing in pure assembly, but surely we can use cog timers for this ....
Will do ... although I had to replace the Pepperjack with a Local Merlot ..... distinct lack of Oz wines over here ....
By the way, what I am trying to do is this:
My interest is Electric Cars ... currently I am building one based on a 200HP Industrial motor running at 650V. (Biggest problem is the cost of the controller ... even when I got the power module off eBay)
That is all good, but for my next project I would like to use a BLDC motor being driven by a Prop1 (in sensorless mode) or maybe a Prop2 if I run out of resources .... seems to me I can get the cost of the controller right down ...
So I would like to start the coding based on the Prop1 and see how far I get ... and obviously I would like to do this in Tachyon Forth ..
.... So I am thinking for the 3 Phase PWM, maybe I could use 3 cogs running a low level PWM word that could be phase shifted relative to each other .... (using timers)
Another cog would interface to the sensorless circuitry (zero-crossing detector) and would self modify the phase shifting .. (phase shift is normally 60deg in a six step BLDC)
Be interested in what you think of that approach and what the best words would be to achieve the building blocks ..
NB: I have seen the 32 channel PWM code that Parallax have coded up to do this sort of thing in pure assembly, but surely we can use cog timers for this ....
Cheers,
Bernie
I can't see how a 32 channel PWM could be implemented by counters or even without a cog involved. It could be possible to use the video register though for 8 channels and I'm not sure if that's been done yet but it would still need a cog dedicated to it. The present PWM runs 8-bit PWM up to around 5kHz which means it's updating every 781ns as it needs to read from a table in hub ram (slow) which can be updated by another cog. Sure you could place the table in COG RAM but how do you change it without upsetting the PWM updates? I could update the 8-bit method to read in a long each time if I want to speed it up but I'd have to time the hub access to make sure it's synchronized too.
Remember the Prop design philosopy, the cog is the peripheral, you don't have UARTs, SPI, I2C, ADC, DAC, DMA, VGA, A/V, PWM etc hardwired in, but each cog can do just that. Although each cog is a CPU, it's not necessarily THE CENTRAL processing unit and unlike prima donnas they are humble and flexible enough to be what they need to be ("be a radio"! Okay!)
BTW, Pepperjack is a very lovely red for sure but it's kinda like my baseline red Life is too short to drink cheap wine I say!
I can't see how a 32 channel PWM could be implemented by counters or even without a cog involved. It could be possible to use the video register though for 8 channels and I'm not sure if that's been done yet but it would still need a cog dedicated to it. The present PWM runs 8-bit PWM up to around 5kHz which means it's updating every 781ns as it needs to read from a table in hub ram (slow) which can be updated by another cog. Sure you could place the table in COG RAM but how do you change it without upsetting the PWM updates? I could update the 8-bit method to read in a long each time if I want to speed it up but I'd have to time the hub access to make sure it's synchronized too.
Remember the Prop design philosopy, the cog is the peripheral, you don't have UARTs, SPI, I2C, ADC, DAC, DMA, VGA, A/V, PWM etc hardwired in, but each cog can do just that. Although each cog is a CPU, it's not necessarily THE CENTRAL processing unit and unlike prima donnas they are humble and flexible enough to be what they need to be ("be a radio"! Okay!)
BTW, Pepperjack is a very lovely red for sure but it's kinda like my baseline red Life is too short to drink cheap wine I say!
No, I don't want or need 32 channels, just quoting some example code that was entirely bit bashed PASM code ...
All I need is 3Phase PWM that is gated by the commutation circuitry ..I was thinking of using a cog each for the 3 PWM, and stopping/starting cogs to gate them ..not sure if this is the best approach.
As you know BLDC is usually a six step waveform across the 3 phases, 60deg apart, and each step could be either a duty cycle controlled PWM of fully on or fully off. The commutation determines when the start of these steps happens.
So there will be 6 (3 complementary ) outputs (timers in PWM mode) and three inputs .... the three inputs really need to go through a comparator , which for the P1 looks like I will need external ones, looks like the P2 could do this with it's comparator on each pin.
So, I am going to build some interface circuitry on the Prop Proto board and would like to play around with some interfacing code and the PWM stuff ..
As far as the current PWM word, I may have some suggestions to modify it to allow gating ... that would help my application .. (instead of Cog on/off stuff)
No, I don't want or need 32 channels, just quoting some example code that was entirely bit bashed PASM code ...
All I need is 3Phase PWM that is gated by the commutation circuitry ..I was thinking of using a cog each for the 3 PWM, and stopping/starting cogs to gate them ..not sure if this is the best approach.
As you know BLDC is usually a six step waveform across the 3 phases, 60deg apart, and each step could be either a duty cycle controlled PWM of fully on or fully off. The commutation determines when the start of these steps happens.
So there will be 6 (3 complementary ) outputs (timers in PWM mode) and three inputs .... the three inputs really need to go through a comparator , which for the P1 looks like I will need external ones, looks like the P2 could do this with it's comparator on each pin.
So, I am going to build some interface circuitry on the Prop Proto board and would like to play around with some interfacing code and the PWM stuff ..
As far as the current PWM word, I may have some suggestions to modify it to allow gating ... that would help my application .. (instead of Cog on/off stuff)
Thanks,
Bernie
for the table driven PWM code Peter gives:
This version is set to run up to 8 channels of 8-bit PWM at 1kHz (Tested to 5kHz)
so this would work for a slow motor
and as you write, COG on/off is slow and not a good option.
Updating the PWM tables even in tha PASM version takes
New kernel module method to speed-up updates = 233us total
which gives you a 4kHz update rate - if this is fast enough depends on your motor dynamics.
At what RPM do you run?
Adding gating to the PWM-Code module inside the Tachyon core shouldn't be to difficult.
org _RUNMOD
_PWM mov deltaR,tos ' use supplied delta value from tos
mov target,tos
add target,cnt
mov R1,#0
pwmlp
mov X,REG0 ' read base address of table
add X,R1 ' add in read index
rdbyte X,X
[SIZE=3][B]' here you can read and check a HUB variable with a gate MASK
rdbyte R2,REG3 ' use e.g. REG3 to hold the gate mask HUB address for all 8 channels
and X,R2[/B][/SIZE] ' [B][SIZE=3]mask the PWM [/SIZE][/B]- depending on positive or negative logic might need to be inverted
shl X,REG1 ' shift up to pwmpins
mov outa,X ' update outputs
add R1,#1
and R1,#$FF
pwmwait waitcnt target,deltaR
jmp #pwmlp
PWM byte _WORD,(@_PWM+s)>>8,@_PWM+s,_BYTE,1[SIZE=5][B]5[/B][/SIZE],XOP,xLOADMOD,EXIT ' adapt PASM line count
It took me quite some time to figure out, what STRING is really doing.
So I commented the code - hope it is right.
If not please correct somebody / Peter ...
\ commented by Markus Baer MJB ( for my understanding - hope this is correct )
pub STRING ( str max -- ) \ Specify max size of string else use 0 for string length
[COMPILE] GRAB \ execute input before STRING
?DUP 0= IF DUP STRLEN 1+ THEN SWAP ( max str ) \ max is STRLEN+1 if max given was 0
codes W@ 4 ALIGN codes W! ALLOCATED ( size str ) \ make long aligned, adjust here
( since the string literal is in the place where we want to create the STRING variable, we need to save the string somewhere further up in the buffer.
CREATE not only compiles the VARB byte code, but also appends an EXIT
because of this we can not move the string const to the final place yet,
but we need to move up 1 char more )
HERE 5 + OVER STRLEN 1+ <CMOVE \ move out of the way
$80 HERE C! \ set the attribute byte, first byte of the STRING header
DUP HERE 1+ C! \ store the size in the second byte of STRING header
HERE 4 + STRLEN HERE 2+ C! \ calc the null terminated string len and store it in third byte of STRING header
3 ALLOT \ allocate space for the 3 header bytes, adjust here
[COMPILE] CREATE \ since CREATE is immediate we need to prefix with [COMPILE]
\ CREATE creates a variable, that returns its address to TOS
( now we need to move the string literal value to the right position replacing the EXIT byte code compiled in by CREATE, which we don't need )
HERE 1+ DUP STRLEN 1+ OVER 1- SWAP CMOVE
( now move the here pointer to the end of the string by allocating the requested length or if this was 0 then the length of the string const plus the 0 end byte.
HERE 3 - C@ ALLOT
;
IMMEDIATE \ make this an immediate so the STRING is created direcly
reverse engineering Peter's code raises my insight, and I hope, TACHYON 3.0 will not be too different inside and I have to relearn all again ...
sorry - I just can't get the comments aligned correctly
so this would work for a slow motor
and as you write, COG on/off is slow and not a good option.
Updating the PWM tables even in tha PASM version takes
which gives you a 4kHz update rate - if this is fast enough depends on your motor dynamics.
At what RPM do you run?
Adding gating to the PWM-Code module inside the Tachyon core shouldn't be to difficult.
org _RUNMOD
_PWM mov deltaR,tos ' use supplied delta value from tos
mov target,tos
add target,cnt
mov R1,#0
pwmlp
mov X,REG0 ' read base address of table
add X,R1 ' add in read index
rdbyte X,X
[SIZE=3][B]' here you can read and check a HUB variable with a gate MASK
rdbyte R2,REG3 ' use e.g. REG3 to hold the gate mask HUB address for all 8 channels
and X,R2[/B][/SIZE] ' [B][SIZE=3]mask the PWM [/SIZE][/B]- depending on positive or negative logic might need to be inverted
shl X,REG1 ' shift up to pwmpins
mov outa,X ' update outputs
add R1,#1
and R1,#$FF
pwmwait waitcnt target,deltaR
jmp #pwmlp
PWM byte _WORD,(@_PWM+s)>>8,@_PWM+s,_BYTE,1[SIZE=5][B]5[/B][/SIZE],XOP,xLOADMOD,EXIT ' adapt PASM line count
Hi MJB,
Thanks. I do actually need much faster PWM ... in the order of 10..15Khz, which is why I was wondering about using the Cog timers in PWM mode with complementary outputs and gating those some how,
rather than doing bit-bashing as per Peter's code ..
My other requirement is to have a cog act as a re-triggerable mono-stable as part of the commutation side ... I wonder if that can also be done using a Cog timer.
Thanks. I do actually need much faster PWM ... in the order of 10..15Khz, which is why I was wondering about using the Cog timers in PWM mode with complementary outputs and gating those some how,
rather than doing bit-bashing as per Peter's code ..
a very simple method for gating would be setting the pins to inputs with pullup or pull downs as appropriate, while the counter-PWM continues
My other requirement is to have a cog act as a re-triggerable mono-stable as part of the commutation side ... I wonder if that can also be done using a Cog timer.
B.
you can easily implement a SW monoflop - if timing is sufficient.
I use a COG to implement a legacy bus interface - kind a SW CPLD.
Reaction is 25 .. 50 ns for the most time critical transition.
a very simple method for gating would be setting the pins to inputs with pullup or pull downs as appropriate, while the counter-PWM continues
I don't think that would work, I need to turn those outputs on or off when they are not PWM outputs. I wonder about changing the pwm mode in a way that they go high or low?
you can easily implement a SW monoflop - if timing is sufficient.
Can you elaborate with some Pseudo code on how that would work?
@bmentink: would something like http://obex.parallax.com/object/482 work for you (3ctrx variant)? It may need some work but everything is done inside the prop (there is at least one other implementation available).
Can you elaborate with some Pseudo code on how that would work?
B.
a monoflop is very simple.
e.g.:
output is low
trigger
set output high
set timer variable / manual countdown counter with value for impuls time
looplabel
... on retrigger event reload counter variable with original value ...
djnz looplabel
set output low
using waitcnt will not work, since there must be s.th. to check for retrigger signal
so you can just use a simple tight polling loop.
I don't see how counters could be used for this.
@bmentink: would something like http://obex.parallax.com/object/482 work for you (3ctrx variant)? It may need some work but everything is done inside the prop (there is at least one other implementation available).
an interresting question might be:
Is PWM really needed to drive the motor - or would duty mode be useful as well?
It can be easily generated with the counters.
the important feature is to generate the appropriate average current within the time interval.
Inductivity averages it - so I wonder if the exact phase of PWM is a must have. ...???
a monoflop is very simple.
e.g.:
output is low
trigger
set output high
set timer variable / manual countdown counter with value for impuls time
looplabel
... on retrigger event reload counter variable with original value ...
djnz looplabel
set output low
using waitcnt will not work, since there must be s.th. to check for retrigger signal
so you can just use a simple tight polling loop.
I don't see how counters could be used for this.
Thanks, that makes sense .. I could not work out how it could work with a cog counter either ..
I need three of these, so guess I could use one cog to do all three in PASM as above ..
an interresting question might be:
Is PWM really needed to drive the motor - or would duty mode be useful as well?
It can be easily generated with the counters.
the important feature is to generate the appropriate average current within the time interval.
Inductivity averages it - so I wonder if the exact phase of PWM is a must have. ...???
I think PWM is needed as duty mode would give some interesting motor noises as you sped up and down due to motor resonances .. I think you do need a constant frequency.
I though PWM mode (NCO mode) generated a constant frequency, with variable duty .... am I wrong?
Thanks, that makes sense .. I could not work out how it could work with a cog counter either ..
I need three of these, so guess I could use one cog to do all three in PASM as above ..
I think PWM is needed as duty mode would give some interesting motor noises as you sped up and down due to motor resonances .. I think you do need a constant frequency.
I though PWM mode (NCO mode) generated a constant frequency, with variable duty .... am I wrong?
Bernie, if you want to see what the different modes do then hook-up a scope and sit at the terminal and try the modes. It's very simple and all the words are there (in EXTEND.fth) to allow you to change things easily and of course interactively.
Yes of course I will do that ... just someone has stolen my Prop board for that express purpose ... to play with Forth ( a new convert) ... so I am giving him some head ..
When I get the board back I will be into it ... just thought I could get a quick answer back wile i wait ..
I need to generate a HEX file from Tachyon Forth that can be loaded and burnt to EEPROM. Which of the various "dump" words produces a bootable hex file?
I need to generate a HEX file from Tachyon Forth that can be loaded and burnt to EEPROM. Which of the various "dump" words produces a bootable hex file?
TNX in advance .... cheers ... BBR
\ Adjust and dump the current Tachyon binary image in Intel hex format for conversion at the PC end to a bin file
\ The bin file should be renamed as .binary to suit the Prop tool
I need to generate a HEX file from Tachyon Forth that can be loaded and burnt to EEPROM. Which of the various "dump" words produces a bootable hex file?
TNX in advance .... cheers ... BBR
The BINARYDUMP word will dump the whole 32K less the top 32 bytes in Intel hex format with the correct Spin header checksum so you can run a HEX2BIN or equivalent on the PC end. Just make sure that the binary is named with the .binary extension so the Prop tool can handle it.
The discussions on i/o redirection came to me today as I was editing my BBR_Extensions.fth file for the umpteenth time ... and I wondered if I could apply our ever-so-slippery "variable constant" technique to the same end result ...
The discussions on i/o redirection came to me today as I was editing my BBR_Extensions.fth file for the umpteenth time ... and I wondered if I could apply our ever-so-slippery "variable constant" technique to the same end result ...
.... it worked ... the serial LCD on Pin2 displayed the string (.LSTR word invokes LCD does a string print and returns the CONsole)
Hi Brian,
I'm scrathing my head as to why it is done this way which looks awkward plus I'm not sure what .LSTR does that's different from the normal ." word or even the .STR or TYPE$ words. However I don't really see the need for redirection unless I had multiple serial displays and that would be easy enough too. The rewritable constant is actually redundant if you see how I would handle a couple of different serial devices using SEROUT:
[SIZE=3][FONT=courier new]: LCDEMIT #P2 SEROUT ;
\ Set baudrate for the LCD and select the txd pin used
: LCD ' LCDEMIT uemit W! #19200 SERBAUD ;
: TTYEMIT #P7 SEROUT ;
: TELETYPE ' TTYEMIT uemit W! #300 SERBAUD ;
\ Test out these words
LCD ." HELLO WORLD" CON
TELETYPE ." HELLO WORLD, THIS IS " .VER CON[/FONT][/SIZE]
It's also more desirable to set the baudrate once when the output device is selected as baudrate is a redundant and time-consuming calculation that ends up repeating for every character that's sent.
If I had multiple LCDs I might add a parameter to LCD and invoke it like this:
#P2 LCD ." HELLO WORLD" #P7 LCD ." HELLO WORLD FROM ME TOO" CON
There's even this version of the LCD and TELETYPE snippet that uses a common output word that uses a variable to hold the pin.
[SIZE=3][FONT=courier new]
BYTE serout
: SEROUT2 serout C@ SEROUT ;
\ Set baudrate for the LCD and select the txd pin used
: LCD ' SEROUT2 uemit W! #19200 SERBAUD #P2 serout C! ;
: TELETYPE ' SEROUT2 uemit W! #300 SERBAUD #P7 serout C! ;[/FONT][/SIZE]
Comments
Is there any more example code for the COG timers? I have studied the wave playing example and sort of understand it (been wading through the Parallax docs), would be good to
have some other other examples though ... i.e pulse PWM, motor control, Freq/Duty measurement etc ... the timers are so powerful, I would like to get my head around them ...
Cheers,
Bernie
Bluetooth: RN-42 http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/Rn-42/List/0/SortField/4/ProductID/890/Default.aspx
Getting an Asus TF300T tomorrow. Any tips on using the RN-42 with Blueterm?
Hmmm, been looking at the PWM code ... very confused. Code is:
It seems to me that your only using the cog timer for a delay right? all io is bit-bashed rather than using outa,outb?
Also, I don't see how the above loop ends ... and ther is no jump to next or drop at the end of the code ... where does it go to?
Seems I am missing a big chunk of information here ... also "org _RUNMOD" confuses me as it is used above each PASM code module, doesn't that mean they will all be assembled at the same place in memory?
My head hurts.....
EDIT: Why is the code I post all mashed up ... tried copy/pasting through different editors but still rubbish ..
Bernie
COG memory is very limited and Tachyon squeezes the VM and stacks in there and there's no room really left over for specialized operations that really require PASM. That's where RUNMOD comes in as I sacrifice 16 to 24 longs for specialized modules which are compiled to run at that address but only one module can be loaded at a time. These specialized modules include SPI, I2C, SD, and PWM etc. The PWM module is designed to run in it's own cog as it's an endless loop where another cog/task can control the parameters. Of course the PWM cog doesn't need all the Tachyon VM in it after that but it's easy to load the module in the normal fashion.
So PWM doesn't use the counters, only WAITCNT but you mentioned PWM in your list which is different to duty-cycle modulation ( fixed pulse width, variable frequency).
As for your head hurting can I suggest a Pepperjack Cab Sav. If that doesn't work then increase the dose.
The DS3231 is compatible enough with the MCP79410 that you should be able to use it as is, just change the device address. The first 7 registers are compatible although the 79410 does uses some of the otherwise unused bits for control purposes but that won't affect the 3231. Try it and let me know how is goes.
The device address can be changed either in the source code:
$DE == @rtc
to
$B0 == @rtc
Or you can write directly to the constant at runtime with:
$B0 ' @rtc 1+ !
The RN42 should just work in slave mode and you should be able to change it's default baudrate to 230400.
Now my head hurts because this wine is not available in the USA!
Gonna have to place an Intl order
why it could only work in this special case.
I am revectoring KEY via ukey to read from a string.
which can only work at the end of the input line, when the input loop comes back to calling KEY again.
so I tried the following modifications, which at least seem to work on the input line.
But it is still not possible to put this inside a loop or definition of a word.
in other words - I can not compile it.
Since now I had to define EVAL as IMMEDIATE to work at least this far.
I assume I need to take a completely different approach for EVAL to do what I imagine.
Can't wait but I will.
Perfect for logging, writing and running profiles for my Tachyon/Forth machine.
Will this be available in V2.1? or 3.x only?
Pre thanks Peter.
Will do ... although I had to replace the Pepperjack with a Local Merlot ..... distinct lack of Oz wines over here ....
By the way, what I am trying to do is this:
My interest is Electric Cars ... currently I am building one based on a 200HP Industrial motor running at 650V. (Biggest problem is the cost of the controller ... even when I got the power module off eBay)
That is all good, but for my next project I would like to use a BLDC motor being driven by a Prop1 (in sensorless mode) or maybe a Prop2 if I run out of resources .... seems to me I can get the cost of the controller right down ...
So I would like to start the coding based on the Prop1 and see how far I get ... and obviously I would like to do this in Tachyon Forth ..
.... So I am thinking for the 3 Phase PWM, maybe I could use 3 cogs running a low level PWM word that could be phase shifted relative to each other .... (using timers)
Another cog would interface to the sensorless circuitry (zero-crossing detector) and would self modify the phase shifting .. (phase shift is normally 60deg in a six step BLDC)
Be interested in what you think of that approach and what the best words would be to achieve the building blocks ..
NB: I have seen the 32 channel PWM code that Parallax have coded up to do this sort of thing in pure assembly, but surely we can use cog timers for this ....
Cheers,
Bernie
here my attempt at a generalization of it.
comments and optimizations welcome.
I can't see how a 32 channel PWM could be implemented by counters or even without a cog involved. It could be possible to use the video register though for 8 channels and I'm not sure if that's been done yet but it would still need a cog dedicated to it. The present PWM runs 8-bit PWM up to around 5kHz which means it's updating every 781ns as it needs to read from a table in hub ram (slow) which can be updated by another cog. Sure you could place the table in COG RAM but how do you change it without upsetting the PWM updates? I could update the 8-bit method to read in a long each time if I want to speed it up but I'd have to time the hub access to make sure it's synchronized too.
Remember the Prop design philosopy, the cog is the peripheral, you don't have UARTs, SPI, I2C, ADC, DAC, DMA, VGA, A/V, PWM etc hardwired in, but each cog can do just that. Although each cog is a CPU, it's not necessarily THE CENTRAL processing unit and unlike prima donnas they are humble and flexible enough to be what they need to be ("be a radio"! Okay!)
BTW, Pepperjack is a very lovely red for sure but it's kinda like my baseline red Life is too short to drink cheap wine I say!
No, I don't want or need 32 channels, just quoting some example code that was entirely bit bashed PASM code ...
All I need is 3Phase PWM that is gated by the commutation circuitry ..I was thinking of using a cog each for the 3 PWM, and stopping/starting cogs to gate them ..not sure if this is the best approach.
As you know BLDC is usually a six step waveform across the 3 phases, 60deg apart, and each step could be either a duty cycle controlled PWM of fully on or fully off. The commutation determines when the start of these steps happens.
So there will be 6 (3 complementary ) outputs (timers in PWM mode) and three inputs .... the three inputs really need to go through a comparator , which for the P1 looks like I will need external ones, looks like the P2 could do this with it's comparator on each pin.
So, I am going to build some interface circuitry on the Prop Proto board and would like to play around with some interfacing code and the PWM stuff ..
As far as the current PWM word, I may have some suggestions to modify it to allow gating ... that would help my application .. (instead of Cog on/off stuff)
Thanks,
Bernie
and as you write, COG on/off is slow and not a good option.
Updating the PWM tables even in tha PASM version takes which gives you a 4kHz update rate - if this is fast enough depends on your motor dynamics.
At what RPM do you run?
Adding gating to the PWM-Code module inside the Tachyon core shouldn't be to difficult.
So I commented the code - hope it is right.
If not please correct somebody / Peter ...
reverse engineering Peter's code raises my insight, and I hope, TACHYON 3.0 will not be too different inside and I have to relearn all again ...
sorry - I just can't get the comments aligned correctly
Hi MJB,
Thanks. I do actually need much faster PWM ... in the order of 10..15Khz, which is why I was wondering about using the Cog timers in PWM mode with complementary outputs and gating those some how,
rather than doing bit-bashing as per Peter's code ..
My other requirement is to have a cog act as a re-triggerable mono-stable as part of the commutation side ... I wonder if that can also be done using a Cog timer.
B.
a very simple method for gating would be setting the pins to inputs with pullup or pull downs as appropriate, while the counter-PWM continues
you can easily implement a SW monoflop - if timing is sufficient.
I use a COG to implement a legacy bus interface - kind a SW CPLD.
Reaction is 25 .. 50 ns for the most time critical transition.
I don't think that would work, I need to turn those outputs on or off when they are not PWM outputs. I wonder about changing the pwm mode in a way that they go high or low?
Can you elaborate with some Pseudo code on how that would work?
Thanks,
B.
e.g.:
output is low
trigger
set output high
set timer variable / manual countdown counter with value for impuls time
looplabel
... on retrigger event reload counter variable with original value ...
djnz looplabel
set output low
using waitcnt will not work, since there must be s.th. to check for retrigger signal
so you can just use a simple tight polling loop.
I don't see how counters could be used for this.
there are some more:
http://obex.parallax.com/object/211 (looks slow)
search OBEX for PWM or MOTOR
an interresting question might be:
Is PWM really needed to drive the motor - or would duty mode be useful as well?
It can be easily generated with the counters.
the important feature is to generate the appropriate average current within the time interval.
Inductivity averages it - so I wonder if the exact phase of PWM is a must have. ...???
Thanks, that makes sense .. I could not work out how it could work with a cog counter either ..
I need three of these, so guess I could use one cog to do all three in PASM as above ..
I think PWM is needed as duty mode would give some interesting motor noises as you sped up and down due to motor resonances .. I think you do need a constant frequency.
I though PWM mode (NCO mode) generated a constant frequency, with variable duty .... am I wrong?
Bernie, if you want to see what the different modes do then hook-up a scope and sit at the terminal and try the modes. It's very simple and all the words are there (in EXTEND.fth) to allow you to change things easily and of course interactively.
Yes of course I will do that ... just someone has stolen my Prop board for that express purpose ... to play with Forth ( a new convert) ... so I am giving him some head ..
When I get the board back I will be into it ... just thought I could get a quick answer back wile i wait ..
I need to generate a HEX file from Tachyon Forth that can be loaded and burnt to EEPROM. Which of the various "dump" words produces a bootable hex file?
TNX in advance .... cheers ... BBR
The BINARYDUMP word will dump the whole 32K less the top 32 bytes in Intel hex format with the correct Spin header checksum so you can run a HEX2BIN or equivalent on the PC end. Just make sure that the binary is named with the .binary extension so the Prop tool can handle it.
The discussions on i/o redirection came to me today as I was editing my BBR_Extensions.fth file for the umpteenth time ... and I wondered if I could apply our ever-so-slippery "variable constant" technique to the same end result ...
I typed .... it worked ... the serial LCD on Pin2 displayed the string (.LSTR word invokes LCD does a string print and returns the CONsole)
Hi Brian,
I'm scrathing my head as to why it is done this way which looks awkward plus I'm not sure what .LSTR does that's different from the normal ." word or even the .STR or TYPE$ words. However I don't really see the need for redirection unless I had multiple serial displays and that would be easy enough too. The rewritable constant is actually redundant if you see how I would handle a couple of different serial devices using SEROUT:
It's also more desirable to set the baudrate once when the output device is selected as baudrate is a redundant and time-consuming calculation that ends up repeating for every character that's sent.
If I had multiple LCDs I might add a parameter to LCD and invoke it like this:
#P2 LCD ." HELLO WORLD" #P7 LCD ." HELLO WORLD FROM ME TOO" CON
There's even this version of the LCD and TELETYPE snippet that uses a common output word that uses a variable to hold the pin.