Shop OBEX P1 Docs P2 Docs Learn Events
Serial Communication and Variable Storage — Parallax Forums

Serial Communication and Variable Storage

tdeyletdeyle Posts: 85
edited 2007-07-08 03:55 in Propeller 1
Hey everyone;

Simply put, I have an ELM322 OBDII (On-Board Diagnostic) device that I am trying to get to communicate with the Prop.

The protocol between the two is simple since the chip accepts regular ASCII Symbols with an "AT" prefix when giving direction to the ELM322; or hex characters, with no prefix, to give direction to the OBDII system. Both type of commands are terminated with a carriage return, "13".

I am looking to interface the two chips to display polled results to an LCD.

I am quite the beginner with the Prop, and programming general, and as such, arrived at a standstill. I am now trying to see if someone could lend a hand.

My issue is that I have been able to, with the Prop, reset the ELM322 ("ATZ" command), turn character echoing off ("ATE0" command), and display the Chip's version number, ("ATI").

I am working on getting the ELM chip to transmit back the status of the Fuel System from the OBDII, ("0103" command). I have come as far as getting the Prop to display the result on a Serial LCD. Since I do not have the ability to work on the program whilst in the vehicle, I end up getting a "NO DATA" reply.

My issue is, I would like to store this reply into a variable so that I can manipulate it, i.e., some of the replies will require formula to display data that makes sense and instead of a "NO DATA" reply, I could put N/A with a CASE loop.

I need the variable to hold enough data, the longest result would be "NO DATA". I am currently using the Extended Full Duplex Serial Object to communicate and find that it is near impossible, due to my lack of understanding, to store the replies into a variable.

I am looking to do this with nine different parameters, or PIDs as they are called, looped as fast as the ELM322 can manage to transmit them, since the ELM is based on a much slower PIC12C5XX Micro, it is rated at a nominal data rate of 9600 Baud.

Any help given is greatly appreciated.

Let me know if I need to post the code...

TDII

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-04 05:57
    Have a look at the Extended FullDuplexSerial driver in the Propeller Object Exchange (ww1.parallax.com/Default.aspx?tabid=65 - 2nd page). It allows you to parse formatted strings and numeric information.

    If you just want to store the information, you can use an array of bytes for each string you want to store and terminate each string with a zero byte. You'll have to store the text one character at a time since the only receive routines in the FullDuplexSerial driver are single character routines. There are built-in routines in Spin for copying a block of bytes (BYTEMOVE), comparing two strings for equality (STRCOMP), and determining the length of a string (STRSIZE).
  • tdeyletdeyle Posts: 85
    edited 2007-07-04 07:13
    Thanks, Mike.

    So I have to store the strings that I know will come up, then compare them to the strings that are sent from the ELM chip?

    Or store them as they are received one byte at a time?

    It looks as though you are saying that I have a few avenues...

    TDII
  • tdeyletdeyle Posts: 85
    edited 2007-07-04 17:30
    Here is what I have tried so far:

    This is from the DAT block were I have created two byte arrays named Error and CAP_FS_Str. The Error array shows the string that will be produced if there is no data response from the ELM chip.

    Error                   byte    ">NO DATA"
    CAP_FS_Str              byte
    
    



    Below is the Public block setup for the CAPture Fuel System Method. It sends out a string, 0103, with carriage return, that will instruct the ELM chip to reply with the status of the Fuel System. The Prop will store the reply into the CAP_FS_Str array. A case loop compares the two arrays to see if they match, if they do, it displays "N/A".

    pub CAP_FS
    
    'Fuel System Status
    
      serial.str(string("0103",13))                         'Query ELM322 to reply with Fuel System Status
      lcd.gotoxy(0,0)                                       'Go home on LCD
    
      serial.rxstr(@cap_fs_str)                             'Receive String from ELM and store into array
    
      CASE @cap_fs_str                                      'Begin CASE loop that will determine whether array has useful data
        @error : lcd.str(string("N/A"))                     'If CAP_FS_STR array equals ERROR array, display N/A on LCD                                             
        OTHER : lcd.str(@cap_fs_str)                        'OTHERwise, display contents of CAP_FS_STR array
    
      timing.pause1s(1)
    
      lcd.cls
      
      lcd.gotoxy(0,0)
      lcd.str(@cap_fs_str)
      lcd.gotoxy(0,1)
      lcd.str(@error)
    
      timing.pause1s(1)
    
    



    I added a snippet at the end to clear the screen and display the contents of both arrays. The problem I see is that the display shows:

    >NO DATA
    >NO DATA>NO DATA
    



    When I erase the contents of the @ERROR array in the DAT block, I find I get:

    >NO DATA
    >NO DATA
    



    So, I thought maybe I am mentioning the error array somewhere else in the program and it is "mirroring" the received data that is filled into the other array, but I am not.

    What am I missing?

    Any help is appreciated.

    TDII
  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-04 17:49
    You are comparing the addresses of the strings, not the contents. You have to do something like:
    if strcomp(@error,@cap_fs_str)
       lcd.str(string("N/A"))
    else
       lcd.str(@cap_fs_str)
    
    
  • tdeyletdeyle Posts: 85
    edited 2007-07-04 18:04
    Thanks again, Mike.

    I tried that before, but thought I needed to add a Zero to the end of the string in CAP_FS_STR.

    It works now!

    Thanks again.

    TDII
  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-04 18:41
    You do need a zero byte at the end of the string in Cap_fs_str. The strcomp stops the comparison when the first zero byte is detected in either string.
  • tdeyletdeyle Posts: 85
    edited 2007-07-04 21:28
    If that is the case, the ELM chip must include one...
  • tdeyletdeyle Posts: 85
    edited 2007-07-06 19:26
    Same Post, new problem

    I have successfully, with Mike's help, been able to get the Prop chip and the ELM chip to exchange information with each other for several different OBDII parameters, or PIDs.

    I have found that, due to my knowledge of proper coding, I make my code as bulky as possible then try to trim it after it works. In my opinion, it is not the way I would like to do it, I believe one should be able to draw up "lean" code at the onset of the project.

    Below is a snippet of code that compares the contents of a pair of Arrays that are given by a previous method.

    if strcomp(@error, VARIABLE)                          ''Compare the ERROR array and the array given with VARIABLE
        LCD.str(string("N/A"))                             ''If the arrays match, then display "N/A"
    
      else
    
        if VARIABLE == @EL_DatStr2
          ELcalc
    



    This leads to the following piece:


    pub ELcalc (LCDx, LCDy)| Index
      
      LCD.gotoxy(LCDx, LCDy)
    
      Idx := 0                                              ''Initalizes the Idx counter
    
      repeat until Idx > 2                                  ''Repeats the loop twice
        
        EL_TempVar[noparse][[/noparse]Idx] := BYTE[noparse][[/noparse]@EL_DatStr2][noparse][[/noparse]Idx+4]         ''Reads the byte value of @EL_DatStr2 at the Idx+4 location
                                                            ''and stores it in the Idx byte location of EL_TempVar 
        case EL_TempVar[noparse][[/noparse]Idx]                                ''Due to the byte received from the ELM chip is actually given as
                                                            ''an ASCII symbol, a conversion must take place. eg."FF" is not
                                                            ''the hex FF but the letters FF, thus in Dec, they equal "7070"
          48..57 : EL_CalcVar[noparse][[/noparse]Idx] := EL_TempVar[noparse][[/noparse]Idx] - 48  ''If the Idx of TempVar = 48..57 the subtract 48
    
          65..70 : EL_CalcVar[noparse][[/noparse]Idx] := EL_TempVar[noparse][[/noparse]Idx] - 55  ''If the Idx of TempVar = 65..70 the subtract 55
    
        Idx++                                               ''Increment Idx by 1
    
      EL_ResultVar := ((((EL_CalcVar[noparse][[/noparse]0]*16)+EL_CalcVar)*100)/255) ''Calculate and display
    
      LCD.dec(EL_ResultVar)
    
    



    As stated, there are several different parameters that need to be gathered, compared to the error array and calculations made. I wanted to sum all of these methods into one method using the following code, starting at the StrComp IF Loop:

    if variable == @EL_DatStr2
          Calc (EL_TempVar, EL_CalcVar, EL_ResultVar, VARIABLE, 1, 3, 2, 1)
    



    This would call this method:

    PUB CALC (TempVar, CalcVar, ResultVar, AAdd, LCDx, LCDy, Bytes, CNum) | Idx
    
      LCD.gotoxy(LCDx, LCDy)                                ''Sets up cursor to proper location on LCD
    
      Idx := 0                                              ''Initalizes the Idx counter
                
      repeat BYTES                                          ''Repeats the loop for the number that Bytes is set as
        TempVar[noparse][[/noparse]Idx] := BYTE[noparse][[/noparse]AAdd][noparse][[/noparse]Idx + 4]                 ''Reads the byte value of AAdd at the Idx+4 location and stores
                                                            ''it in the Idx byte location of TempVar
    
        case TempVar[noparse][[/noparse]Idx]                                   ''Due to the byte received from the ELM chip is actually given as
                                                            ''an ASCII symbol, a conversion must take place. eg."FF" is not
                                                            ''the hex FF but the letters FF, thus in Dec, they equal "7070"
          48..57 : CalcVar[noparse][[/noparse]Idx] := TempVar[noparse][[/noparse]Idx] - 48        ''If the Idx of TempVar = 48..57 the subtract 48 
    
          65..70 : CalcVar[noparse][[/noparse]Idx] := TempVar[noparse][[/noparse]Idx] - 55        ''If the Idx of TempVar = 65..70 the subtract 55 
    
        Idx++                                               ''Increment Idx by 1
         
      case CNum                                                             ''For each parameter different calculations are made
        1 : ResultVar := ((((CalcVar[noparse][[/noparse]0] * 16) + CalcVar) * 100) / 255)      ''and displayed.                   
            lcd.dec(ResultVar)
            lcd.str(string("%"))
            
        2 : ResultVar := (((CalcVar[noparse][[/noparse]0] * 16) + CalcVar) - 40)
            lcd.dec(ResultVar)  
    
        3 : ResultVar := ((CalcVar[noparse][[/noparse]0] * 16) + CalcVar)
            lcd.decf((((ResultVar - 128) * 7812) / 10000), 4)
            lcd.str(string("%"))
    
        4 : ResultVar := ((CalcVar[noparse][[/noparse]0] * 16) + CalcVar)
            lcd.dec((((ResultVar * 1450377) - 147000000) / 10000000))
            lcd.str(string("."))
            lcd.dec((FM.FABS((ResultVar) - 147)) // 10)
                                       
        5 : ResultVar := (((((((CalcVar[noparse][[/noparse]0] * 16) + CalcVar) * 256))) + ((CalcVar * 16) + CalcVar)) / 4)
            lcd.dec(ResultVar)
                             
        6 : lcd.decf(((((CalcVar[noparse][[/noparse]0] * 16) + CalcVar)-128)/2),3)
    
    
    



    Finally, I added subbed in a dummy array value of "FF" to test the code. On the LCD, I get 445% instead of 100%.

    I added some code to display the variables after the calculation loop:

    lcd.gotoxy(0,0)
      lcd.dec(TempVar[noparse][[/noparse]0])
      lcd.gotoxy(0,1)
      lcd.dec(TempVar[noparse][[/noparse](1)])*** For mcode reasons, I have to write the second byte as [noparse][[/noparse](1)] here,
      lcd.gotoxy(2,0)
      lcd.dec(CalcVar[noparse][[/noparse]0])
      lcd.gotoxy(2,1)
      lcd.dec(CalcVar[noparse][[/noparse](1)]) ***and here
      lcd.gotoxy(1,3)
    



    My problem is that for some reason, even though the first byte and second bytes of TempVar are valued at FF, (dec 7070), CalcVar is equated to decimal 15 but CalcVar[noparse][[/noparse]0] stays at F, (dec 70)??

    I have tried to take out certain aspects of the code, eg., separating the gathering loop from the conversion loop, etc. but to no avail.

    You can see that having several methods to calculate, etc. would be a waste of code, thus, you would understand my determination with getting this to work.

    Any help, is greatly appreciated.

    TDII

    Post Edited (tdeyle) : 7/6/2007 7:32:33 PM GMT

  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-06 19:50
    1) The "rxstr" routine will mark the end of the string with a zero byte which it substitutes for the return.

    2) You've presented a lot of code fragments and it's not clear to me what you're asking. Start with the format of the responses from the OBDII. What are the different formats that you need to process? Can you list what the different responses are. Are all the numbers hex values? Are some of them decimal? Is there a delimiter like a comma or space used? Are the responses fixed format (like 4 hex digits)?
  • tdeyletdeyle Posts: 85
    edited 2007-07-06 21:19
    My apologies, I hope I don't complicate the question even more...
    Mike Green said...
    Start with the format of the responses from the OBDII. What are the different formats that you need to process? Can you list what the different responses are.
    The responses of the ELM chip are in a "pseudo hex" format, they look like Hex characters but are in fact ASCII symbols.

    For example if you transmit:

    "0103",13
    



    to the ELM chip, you will receive the status of the Engine Load from the ELM:

    In this example, I will use:

    "4104FF",0
    



    The first four bytes are replies from the ELM giving:
    "4" - Indicates an ELM Response, "1" - OBDII Mode, "04" - PID, "FF" - PID Data

    I only process the last two bytes of data in this example, but there are others that have 4 bytes, (ex. RPM).

    Since these are ASCII Characters, not Hex, I need to convert them to the proper values. The case loop in the CALC method, converts the values received from the ELM.
    In this example, "FF" or "7070" would be converted into "1515".

    This is where the problem lies since, using this method, the result after the conversion is "7015". This value gets carried further into the method and is output as 445% instead of 100%.
    Mike Green said...
    Is there a delimiter like a comma or space used?
    The only delimiter that is present is the Carriage Return (13), on the Tx string to the ELM chip. I have removed the default "," declaration from Extended_FDSerial to ensure this.



    I have posted the code, less fragmented, to clarify the process.

    The first method performed after the LCD setup is:
    pub Gather
    
    ''This method transmits pseudo-hex commands and receives data from the ELM322
    
      serial.rxflush                                        ''Flush the serial receive buffer
    
      repeat                                                ''Repeat
    
        serial.str(string("0103",13))                       ''Transmit 0103 to the ELM322
        ELM_RX (@FS_DatStr2)                                ''Capture "Fuel System Status" Data
         
        serial.str(string("0104",13))                       ''Transmit 0104 to the ELM322                        
        ELM_RX (@EL_DatStr2)                                ''Capture "Engine Load" Data
        
        serial.str(string("0105",13))                       ''Transmit 0105 to the ELM322
        ELM_RX (@CT_DatStr2)                                ''Capture "Coolant Temperature" Data
    
        serial.str(string("0106",13))                       ''Transmit 0108 to the ELM322
        ELM_RX (@STFT_DatStr2)                              ''Capture "Short Term Fuel Trim" Data                        
    
        serial.str(string("0107",13))                       ''Transmit 0107 to the ELM322                         
        ELM_RX (@LTFT_DatStr2)                              ''Capture "Long Term Fuel Trim" Data
    
        serial.str(string("010B",13))                       ''Transmit 010B to the ELM322                        
        ELM_RX (@MAP_DatStr2)                               ''Capture "MAP" Data
    
        serial.str(string("010C",13))                       ''Transmit 010C to the ELM322
        ELM_RX (@RPM_DatStr2)                               ''Capture "Engine RPM" Data
    
        serial.str(string("010E",13))                       ''Transmit 010E to the ELM322
        ELM_RX (@TIM_DatStr2)                               ''Capture "Ignition Timing" Data
    
        serial.str(string("010F",13))                       ''Transmit 010F to the ELM322
        ELM_RX (@IAT_DatStr2)                               ''Capture "Intake Air Temperature" Data
    
        serial.str(string("0111",13))                       ''Transmit 0111 to the ELM322
        ELM_RX (@TPS_DatStr2)                               ''Capture "Throttle Position Sensor" Data
    
    



    Which calls the ELM_Rx method:

    pub ELM_Rx (variable)
    
    ''Method used to collect and compare the data received from the ELM322
    
      serial.rxstr(variable)                                ''Receive the data from the ELM322 using the variable given
    
      if strcomp(@error, VARIABLE)                          ''Compare the ERROR array and the array given with VARIABLE
        LCD.str(string("N/A"))                              ''If the arrays match, then display "N/A"
    
      else
    
        if variable == @EL_DatStr2
          Calc (EL_TempVar, EL_CalcVar, EL_ResultVar, VARIABLE, 1, 3, 2, 1)   
    
        elseif variable == @EL_DatStr2
          Calc (EL_TempVar, EL_CalcVar, EL_ResultVar, VARIABLE, 1, 3, 2, 1)    
    
        elseif variable == @CT_DatStr2
          Calc (CT_TempVar, CT_CalcVar, CT_ResultVar, @CT_DatStr2, 17, 3, 2, 2)
    
        elseif variable == @STFT_DatStr2
          Calc (STFT_TempVar, STFT_CalcVar, STFT_ResultVar, @STFT_DatStr2, 1, 1, 2, 3)
    
        elseif variable == @LTFT_DatStr2
          Calc (LTFT_TempVar, LTFT_CalcVar, LTFT_ResultVar, @LTFT_DatStr2, 10, 1, 2, 3)
    
        elseif variable == @MAP_DatStr2
          Calc (MAP_TempVar, MAP_CalcVar, MAP_ResultVar, @MAP_DatStr2, 7, 3, 2, 4)
    
        elseif variable == @RPM_DatStr2
          Calc (RPM_TempVar, RPM_CalcVar, RPM_ResultVar, @RPM_DatStr2, 1, 2, 4, 5)
    
        elseif variable == @TIM_DatStr2
          Calc (TIM_TempVar, TIM_CalcVar, TIM_ResultVar, @TIM_DatStr2, 13, 2, 2, 6)
    
        elseif variable == @IAT_DatStr2
          Calc (IAT_TempVar, IAT_CalcVar, IAT_ResultVar, @IAT_DatStr2, 13, 3, 2, 2)
    
        elseif variable == @TPS_DatStr2
          Calc (TPS_TempVar, TPS_CalcVar, TPS_ResultVar, @TPS_DatStr2, 7, 2, 2, 1) 
                                
      serial.rxflush
    



    This calls the Calc method with various parameters, shown below:

    PUB CALC (TempVar, CalcVar, ResultVar, AAdd, LCDx, LCDy, Bytes, CNum) | Idx
    
      LCD.gotoxy(LCDx, LCDy)                                ''Sets up cursor to proper location on LCD
    
      Idx := 0                                              ''Initalizes the Idx counter
                
      repeat BYTES                                          ''Repeats the loop for the number that Bytes is set as
        TempVar[noparse][[/noparse]Idx] := BYTE[noparse][[/noparse]AAdd][noparse][[/noparse]Idx + 4]                 ''Reads the byte value of AAdd at the Idx+4 location and stores
                                                            ''it in the Idx byte location of TempVar
    
        case TempVar[noparse][[/noparse]Idx]                                   ''Due to the byte received from the ELM chip is actually given as
                                                            ''an ASCII symbol, a conversion must take place. eg."FF" is not
                                                            ''the hex FF but the letters FF, thus in Dec, they equal "7070"
          48..57 : CalcVar[noparse][[/noparse]Idx] := TempVar[noparse][[/noparse]Idx] - 48        ''If the Idx of TempVar = 48..57 then subtract 48 from TempVar[noparse][[/noparse]Idx] and store as CalcVar[noparse][[/noparse]Idx]
    
          65..70 : CalcVar[noparse][[/noparse]Idx] := TempVar[noparse][[/noparse]Idx] - 55        ''If the Idx of TempVar = 65..70 then subtract 55 from TempVar[noparse][[/noparse]Idx] and store as CalcVar[noparse][[/noparse]Idx]
    
        Idx++                                               ''Increment Idx by 1
    



    After this, I placed some debug code to show me what the values of some of the variables are:
      lcd.gotoxy(0,0)
      lcd.dec(TempVar[noparse][[/noparse]0])
      lcd.gotoxy(0,1)
      lcd.dec(TempVar)
      lcd.gotoxy(2,0)
      lcd.dec(CalcVar[noparse][[/noparse]0])
      lcd.gotoxy(2,1)
      lcd.dec(CalcVar)
      lcd.gotoxy(1,3)
    
    



    The method continues and assigns a calculation, based on the value of CNum, that it needs to perform on the variables.

      case CNum                                                             ''For each parameter different calculations are made
        1 : ResultVar := ((((CalcVar[noparse][[/noparse]0] * 16) + CalcVar) * 100) / 255)   ''and displayed.                   
            lcd.dec(ResultVar)
            lcd.str(string("%"))
            
        2 : ResultVar := (((CalcVar[noparse][[/noparse]0] * 16) + CalcVar) - 40)
            lcd.dec(ResultVar)  
    
        3 : ResultVar := ((CalcVar[noparse][[/noparse]0] * 16) + CalcVar)
            lcd.decf((((ResultVar - 128) * 7812) / 10000), 4)
            lcd.str(string("%"))
    
        4 : ResultVar := ((CalcVar[noparse][[/noparse]0] * 16) + CalcVar)
            lcd.dec((((ResultVar * 1450377) - 147000000) / 10000000))
            lcd.str(string("."))
            lcd.dec((FM.FABS((ResultVar) - 147)) // 10)
                                       
        5 : ResultVar := (((((((CalcVar[noparse][[/noparse]0] * 16) + CalcVar) * 256))) + ((CalcVar * 16) + CalcVar)) / 4)
            lcd.dec(ResultVar)
                             
        6 : lcd.decf(((((CalcVar[noparse][[/noparse]0] * 16) + CalcVar)-128)/2),3)
    
    



    TDII
  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-06 22:07
    It sounds like you need a simple hexadecimal to binary conversion routine like:
    pri HexToBin(strAddr, strLen) | char
    repeat while --strLen > 0
       char := byte[noparse][[/noparse]strAddr++]
       if (char => "0") and (char =< "9")
          result := (result << 4) | (char - "0")
       elseif (char => "A") and (char =< "F")
          result := (result << 4) | (char - "A" + $A)
       else
          abort ' Invalid character (like early end of line)
    


    and you'd do
       if HexToBin(variable,1) <> 4
          abort ' Not ELM response
       if HexToBin(variable+1,1) <> 1
          abort ' Not expected OBDII mode
       if HexToBin(variable+2,2) <> 4
          abort ' Not expected PID value
       PidData := HexToBin(variable+4,2)
       if byte[noparse][[/noparse]variable+6] <> 0
          abort ' Missing end of line
    
    

    Post Edited (Mike Green) : 7/6/2007 10:45:23 PM GMT
  • tdeyletdeyle Posts: 85
    edited 2007-07-06 22:33
    What is "Char"? Variable?

    When I express it as a byte variable, I do not get a reading, I believe it is aborting on the first "if" statement.

    TDII
  • Mike GreenMike Green Posts: 23,101
    edited 2007-07-06 22:46
    I'm sorry. I was making some corrections before posting the code and I forgot to put back the declaration and the assignment for char. I edited the original message with the correction.
  • tdeyletdeyle Posts: 85
    edited 2007-07-06 23:00
    Thanks, I'll try it out.

    TDII
  • mirrormirror Posts: 322
    edited 2007-07-06 23:17
    Mike Green said...
    pri HexToBin(strAddr, strLen) | char
    repeat while --strLen > 0
       char := byte[noparse][[/noparse]strAddr++]
       if (char => "0") and (char =< "9")
          result := (result << 4) | (char - "0")
       elseif (char => "A") and (char =< "F")
          result := (result << 4) | (char - "A" + $A)
       else
          abort ' Invalid character (like early end of line)
    

    HexToBin could also be declared as: (Untested exactly as shown, but will handle either
    upper or lower case letters)
    pri HexToBin(strAddr, strLen) | digit
    
    repeat while --strLen > 0
      if (digit := lookdown(byte[noparse][[/noparse]strAddr++] : "0".."9", "A".."F", "a".."f") - 1) > 16
        digit -= 6
      if digit < 0
        abort   'Invalid character
      result := (result << 4) | digit
    
    

    To be quite honest, I'm not sure how this and Mike's code would compare for speed and size,
    but my feelings are this would be a bit quicker because·there are·less spin functions, but
    larger because of the lookup (lookdown) table.

    My C background would also tend to cause me to write the repeat as:
    repeat while strlen-- > 0


    ·
  • tdeyletdeyle Posts: 85
    edited 2007-07-08 03:55
    Well, I tried the program in the car, to unsatisfying results.

    There was initially no action on the LCD screen so I coded a program that would display the raw strings straight from the ELM chip with no formatting.
    serial.rxflush                                    ''Flush Receiving Buffer                        
          serial.str(string("0104",13))                     ''Send 0104 string with CR to ELM
          serial.rxstr(@EL_DatStr)                          ''Result is received and stored
    
          if strcomp(@EL_DatStr,@error)                     ''Compare the result to see
        
            timing.pause1ms(100)
            
          else
            lcd.gotoxy(0,0)  
            lcd.str(@EL_DatStr)
            lcd.str(string("."))
    
            timing.pause1ms(100)
    



    The results I get on the LCD are:
    41 04 43 .
    



    I tweaked the lcd.str(@EL_DatStr), adding [noparse][[/noparse]1, 2 and 3] to the Array to see what each one contained. This is what I got, shown as [noparse][[/noparse]1, 2 an 3], repsectively:
    41 04 43 .
    


    04 43 .
    


    43 .
    



    Seeing this, I rewrote lcd.str(@EL_DatStr) to read lcd.str(@EL_DatStr[noparse][[/noparse] 3]) and grouped everything in a Repeat loop.
    repeat
          serial.rxflush                                    ''Flush Receiving Buffer                        
          serial.str(string("0104",13))                     ''Send 0104 string with CR to ELM
          serial.rxstr(@EL_DatStr)                          ''Result is received and stored
    
          if strcomp(@EL_DatStr,@error)                     ''Compare the result to see
        
            timing.pause1ms(100)
            
          else
            lcd.gotoxy(0,0)  
            lcd.str(@EL_DatStr[noparse][[/noparse] 3])
            lcd.str(string("."))
    
            timing.pause1ms(100)
    



    After this change, I get looping data, (43 ., 42 ., 45 ., etc.) as well as some other strings: (DATA .). Which, if you reveal the whole string, reads: "NO DATA ." Now, that is why I have the STRCOMP, to compare the incoming strings with the @Error array, which reads, "NO DATA ",0 but it seems that it is not working.

    I increased the pause from 100ms to 1000ms, hoping that it would allow the chips to communicate better. However, it didn't work, so I am led to believe it is due to the ELM chip communicating with the OBDII network.

    My questions, is there something wrong with the STRCOMP section?

    Is there any other way to differentiate between real data and NO DATA?
    I am guessing that the reason why the HexToBin method did not work was due to the fact that the string will never equal to four, thus aborting the routine after the first question.

    TDII
Sign In or Register to comment.