Array and cognew
Hi,
I have an object that reads the data from a GM ALDL link and displays the desired values on a TV screen. It works well and I can display at least 10 different parameters from the ECU (engine control unit) in real time. My next step is to put the method that gathers the data into a new cog to run continuously. The code that works follows, I have eliminated all but one display value for clarity:
When I run the following code, I get only one sample after reset. I have had my scope connected to the TX out of the prop and see only one request come through, with the previous code I get continuous data.
I suspect a problem with variables, any tips will be appreciated.
Thanks,
JL
I have an object that reads the data from a GM ALDL link and displays the desired values on a TV screen. It works well and I can display at least 10 different parameters from the ECU (engine control unit) in real time. My next step is to put the method that gathers the data into a new cog to run continuously. The code that works follows, I have eliminated all but one display value for clarity:
{The purpose of this object is to acquire data continuously from the Engine Control Unit in one cog and display the results with another cog}
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
VAR
long request[5]
long data[67]
OBJ
ser : "FullDuplexSerialPlus"
term : "tv_text"
PUB Main | i, r, tmp, throt
request[0] := $F4
request[1] := $57
request[2] := $01
request[3] := $00
request[4] := $B4
ser.start(7, 6, %0000, 8192) 'Start ALDL communications with FullDuplexSerial
term.start(12) 'Start TV Terminal
waitcnt(clkfreq + cnt) 'Give methods chance to start
term.str(@title) 'Print Title on TV screen
repeat
ser.rxflush 'Clear receive buffer
repeat i from 0 to 4 'Send command string to ECU
ser.tx(request[i])
repeat r from 0 to 66 'Fill array
data[r]:= ser.rx
term.str(string($A,1,$B,1,$0D)) 'Set display position
tmp := data[49] 'Word 49 is raw throttle position
throt := tmp 'No conversion, display raw count
term.str(String("TPS ")) 'Print label
term.str(string($A,10,$B,2)) 'Set display location to column 10
term.dec(throt) 'Print value
term.str(String(" ")) 'Put a couple blank spaces after the value is displayed
term.str(String($0D)) 'Newline
DAT
title byte "ALDL MONITOR",13,13,0
When I run the following code, I get only one sample after reset. I have had my scope connected to the TX out of the prop and see only one request come through, with the previous code I get continuous data.
{The purpose of this object is to acquire data continuously from the Engine Control Unit in one cog and display the results with another cog}
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
VAR
long stack[16] 'Stack space for new cog
long data[67] 'Space for data array
OBJ
ser : "FullDuplexSerialPlus"
term : "tv_text"
PUB Main | d, tmp, throt
ser.start(7, 6, %0000, 8192) 'Start ALDL communications with FullDuplexSerial
term.start(12) 'Start TV Terminal
waitcnt(clkfreq + cnt) 'Give methods chance to start
term.str(@title) 'Print Title on TV screen
cognew(GetData(@data), @stack) 'Continuously get ECU data
repeat
term.str(string($A,1,$B,1,$0D)) 'Set display position
tmp := data[49] 'Word 22 is raw coolant temp
throt := tmp 'No conversion, display raw count
term.str(String("TPS ")) 'Print label
term.str(string($A,10,$B,2)) 'Set display location
term.dec(throt) 'Print value
term.str(String(" ")) 'Put a couple blank spaces after the value is displayed
term.str(String($0D)) 'Newline
PUB GetData (dataAddr) | i, r, request[5]
request[0] := $F4
request[1] := $57
request[2] := $01
request[3] := $00
request[4] := $B4
repeat
ser.rxflush
repeat i from 0 to 4 'Send command string to ECU
ser.tx(request[i])
repeat r from 0 to 66 'Fill array
long[dataAddr][r]:= ser.rx
DAT
title byte "ALDL MONITOR",13,13,0
I suspect a problem with variables, any tips will be appreciated.
Thanks,
JL
Comments
That said, why do you use a long array (data[]) for storing bytes (ser.rx)?
You should also store your command array as DAT byte sequence, e.g.
DAT request byte $F4, $57, $01, $00, $B4
Thanks, I changed my longs to bytes and the working code still worked. Next I tried storing my command array as a DAT byte sequence and it no longer worked. Is there an error in my code that deals with data transfer?
(In the code that uses another cog I tried sizing my stack up to 255 longs and still no success.)
repeat ser.rxflush 'Clear receive buffer repeat i from 0 to 4 'Send command string to ECU ser.tx(@request[i]) repeat r from 0 to 66 'Fill array data[r]:= ser.rx term.str(string($A,1,$B,1,$0D)) 'Set display position tmp := data[49] 'Word 49 is raw throttle position throt := tmp 'No conversion, display raw count term.str(String("TPS ")) 'Print label term.str(string($A,10,$B,2)) 'Set display location to column 10 term.dec(throt) 'Print value term.str(String(" ")) 'Put a couple blank spaces after the value is displayed term.str(String($0D)) 'Newline DAT title byte "ALDL MONITOR",13,13,0 request byte $F4,$57,$01,$00,$B4
Thanks,
JL
repeat ser.rxflush 'Clear receive buffer repeat i from 0 to 4 'Send command string to ECU ser.tx([COLOR="red"]@[/COLOR]request[i]) repeat r from 0 to 66 'Fill array data[r]:= ser.rx term.str(string($A,1,$B,1,$0D)) 'Set display position tmp := data[49] 'Word 49 is raw throttle position throt := tmp 'No conversion, display raw count term.str(String("TPS ")) 'Print label term.str(string($A,10,$B,2)) 'Set display location to column 10 term.dec(throt) 'Print value term.str(String(" ")) 'Put a couple blank spaces after the value is displayed term.str(String($0D)) 'Newline DAT title byte "ALDL MONITOR",13,13,0 request byte $F4,$57,$01,$00,$B4
Just get rid of the @ symbol here. request is a DAT array (as opposed to VAR). Adressing is the same, i.e. first element is request[0].I have a look at the cognew issue.
CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 VAR long stack[32] 'Stack space for new cog byte data[67] 'Space for data array OBJ ser: "FullDuplexSerial" dbg: "FullDuplexSerial" PUB Main [COLOR="orange"]cognew(ecu_method, @ecu_stack)[/COLOR] 'Fake ECU ser.start(7, 6, %0000, 8192) 'Start ALDL communications with FullDuplexSerial dbg.start(31, 30, %0000, 115200) 'Start debug Terminal waitcnt(clkfreq*3 + cnt) 'Give methods chance to start dbg.tx(0) 'Clear screen cognew(GetData(@data), @stack) 'Continuously get ECU data repeat dbg.str(string("TPS ")) 'Print label dbg.hex(data[49], 2) 'Print value dbg.tx(1) waitcnt(clkfreq/10 + cnt) PRI GetData(dataAddr) | i repeat ser.rxflush repeat i from 0 to 4 'Send command string to ECU ser.tx(request[i]) repeat i from 0 to 66 'Fill array byte[dataAddr][i]:= ser.rx DAT title byte "ALDL MONITOR",13,13,0 request byte $F4, $57, $01, $00, $B4 [COLOR="orange"]VAR long ecu_stack[32] byte cmds[5] OBJ ecu: "FullDuplexSerial" PRI ecu_method | i ecu.start(6, 7, %0000, 8192) repeat repeat i from 0 to 4 cmds[i] := ecu.rx repeat i from 0 to 66 ecu.tx(cmds[frqa // 5]) frqa++ waitcnt(clkfreq + cnt) [/COLOR] DAT
Could it be that the ECU needs some time to recover before it can take the next command sequence? In your no-extra-cog example you have debug output between receiving all data and sending a new command sequence. For the extra-cog example this delay doesn't exist (command sequence is sent immediately).Thanks, I have changed longs to bytes and put the request array in DAT. The working code is still working but much cleaner in the VAR department.
My attempts at running the data acquistion in a new cog result in the same - it replies once with the correct value then it appears (viewing Tx with a scope) to quit sending requests.
JL
My cleaned up code trying to start new cog:
{The purpost of this object is to acquire data continuously from the Engine Control Unit in one cog and display the results with another cog} CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 VAR long stack[255] 'Stack space for new cog byte data[67] 'Space for data array OBJ ser : "FullDuplexSerialPlus" term : "tv_text" PUB Main | tmp, throt ser.start(7, 6, %0000, 8192) 'Start ALDL communications with FullDuplexSerial term.start(12) 'Start TV Terminal waitcnt(clkfreq + cnt) 'Give methods chance to start term.str(@title) 'Print Title on TV screen cognew(GetData(@data), @stack) 'Continuously get ECU data repeat term.str(string($A,1,$B,1,$0D)) 'Set display position tmp := data[49] 'Word 22 is raw coolant temp throt := tmp 'No conversion, display raw count term.str(String("TPS ")) 'Print label term.str(string($A,10,$B,2)) 'Set display location term.dec(throt) 'Print value term.str(String(" ")) 'Put a couple blank spaces after the value is displayed term.str(String($0D)) 'Newline PUB GetData (dataAddr) | i, r repeat ser.rxflush repeat i from 0 to 4 'Send command string to ECU ser.tx(request[i]) repeat r from 0 to 66 'Fill array byte[dataAddr][r]:= ser.rx DAT title byte "ALDL MONITOR",13,13,0 request byte $F4,$57,$01,$00,$B4
- before rxflush
- before command sequence is sent
- before receive loop is entered
- maybe also indicate how often it goes around the loop
The code structure as such is OK. Now I'm trying to figure out if it's a timing issue (see last comment in post #5).-Phil
It WAS a timing issue, I put a 10 millisecond delay at the end of the repeat loop and now it works. I will try shorter values until I find the optimum time.
Thank you very much for all your tips. I can move on with the project, my next step will be to add some floating point code to display some two-byte parameters that are in milliseconds, and other non-integer scaling formulas.
JL
Thanks, I missed seeing your reply earlier. The code works as it is now with calling ser.start from the Main method. I will try that though, it makes good sense.
BTW, Thanks for your altimeter object. I added a quadrature encoder so that I could adjust the barometric pressure from a local setting. (there's an iPhone app called AeroWeather that you can program for favorite locations) I put the breadboard on the seat of my airplane and with the local (Troutdale, OR) altimeter setting it was right on with my airport at Camas. As soon as I was up to speed, it read a little higher due to lower cabin pressure but that error was pretty consistent all the way up to 9500 feet!
JL
I'm glad to hear the altimeter object worked out for you and that it's proven good to nearly 10K feet!
-Phil