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, $B4Thanks, 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,$B4Thanks,
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,$B4Just 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] DATCould 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