+ Reply to Thread
Results 1 to 5 of 5

Thread: Elm327 obd

  1. #1
    Join Date
    Apr 2014

    Default Elm327 obd

    I've spent about 2 years familiarizing myself with SAE OBD II communications protocols. I purchased the ELM327 OBD II CAN Interpreter, based on a PIC18F2480. As a test module, I printed a PCB board that uses a PIC18F25K50 for USB communication to my laptop. The initial goal is to send a command from the laptop to the K50 which is then sent serially to the ELM. I rigged an LCD screen to display (from the K50) communications both ways. I have the LCD verifying commands from the PC. However, the ELM327 Data Sheet claims it sends "ELM327 v2.1" when fired up, and when given "ATZ" command. I cannot seem to get the appropriate response from the ELM.

    I rigged a logic analyzer to both Comm pins to see if it at least looked like it should. Sending "ATZ" from the PC is converted to 0x03 for the variable ByteCount (indicating 3 bytes of data to be transmitted; ATZ), 0x41 ("A"), 0x44 ("T), 0x5A ("Z"). The LCD confirms the K50 is receiving this from the PC via USB. From the K50 I send "ATZ" then $0D, which is the Carriage Return value. From the K50, the logic analyzer shows 0xA5, 0x8A, 0x96, 0xAC. Response from ELM is NULL, NULL. I tried MSB & LSB First, I tried Auto Baud Detect on the Logic Analyzer, I triple checked the 8 bits, 1 stop bit, no parity settings...

    Next, the ELM327 has a couple BAUD rate options. Pin 6 tied to Vdd sets the initial baud at 38400, which is the option I chose. The punch line is I am unable to get the K50 talking with the ELM properly. I tried using the HSERIN/OUT commands setting the DEFINEs, but communication couldn't be verified. I then sent & received transmissions directly through the TXREG1 and RCREG1. Still no success. If I manually load values to represent an ELM transmission, the USB properly displays them, so the USB side seems fine. UART is not something I've worked with extensively. My inclinations are I'm not processing the data correctly between the K50 & ELM. Here is the pertinent code:

        CONFIG PLLSEL = PLL3X                 ;3x clock multiplier
        CONFIG CFGPLLEN = ON                 ;PLL Enabled
        CONFIG CPUDIV = NOCLKDIV             ;CPU uses system clock (no divide)
        CONFIG LS48MHZ = SYS48X8             ;System clock at 48 MHz, USB clock divider is set to 8
        CONFIG FOSC = INTOSCIO                 ;Internal oscillator
        CONFIG PCLKEN = OFF                     ;Primary oscillator shutdown firmware controlled
        CONFIG FCMEN = OFF                     ;Fail-Safe Clock Monitor disabled
        CONFIG IESO = OFF                     ;Oscillator Switchover mode disabled
    ;    CONFIG PWRTEN = OFF                 ;Power up timer disabled
        CONFIG BOREN = ON                     ;BOR controlled by firmware (SBOREN is enabled)
        CONFIG BORV = 190                     ;BOR set to 1.9V nominal
    ;    CONFIG LPBOR = OFF                     ;Low-Power Brown-out Reset disabled
        CONFIG WDTEN = ON                     ;WDT enabled in hardware (SWDTEN ignored)
        CONFIG WDTPS = 512                     ;1:512
        CONFIG CCP2MX = RC1                     ;CCP2 input/output is multiplexed with RC1
        CONFIG PBADEN = OFF                     ;PORTB<5:0> pins are configured as digital I/O on Reset
        CONFIG T3CMX = RC0                     ;T3CKI function is on RC0
        CONFIG SDOMX = RB3                     ;SDO function is on RB3
        CONFIG MCLRE = OFF                     ;MCLR pin disabled; RE3 input enabled
        CONFIG STVREN = ON                     ;Stack full/underflow will cause Reset
        CONFIG LVP = OFF                     ;Single-Supply ICSP disabled
    ;    CONFIG XINST = OFF                     ;Instruction set extension and Indexed Addressing mode disabled
    INCLUDE    "descript.bas"    ' Include the USB & HID descriptors
    INCLUDE "DT_INTS-18.bas"
    INCLUDE "ReEnterPBP-18.bas"
    Define  OSC         48
    ;Interrupt Processor:
    INT_LIST  macro    ; IntSource,  Label,         Type, ResetFlag? 
            INT_Handler   RX_INT,    _Get_Elm,      PBP,  yes   ;USART Transmission Received
        INT_CREATE                      ;Creates the interrupt processor
    ; --- *** Oscillator Related SFRs *** ----------------------------------------------------------------------------------
    OSCCON       =    %01110000         ;INTOSC 16 MHz, PLL Defined
    OSCCON2      =    %10010010         ;PLL Enabled, HFINTOSC Running
    OSCTUNE.7    =    1                 ;3X PLL
    ; --- *** USB SFRs *** -------------------------------------------------------------------------------------------------
    UCON         =    %00001110
    UCFG         =    %00010100
    ; --- *** USART SFRs *** -----------------------------------------------------------------------------------------------
    TXSTA1       =    %00100100         ;24h, Yields 38400 Baud
    ;TXSTA1       =    %00100000         ;20h, Yields 9600 Baud
    RCSTA1       =    %10010000         ;90h, .2 = FERR, .1 = OERR
    BAUDCON1     =    %01000000
    SPBRG        =    77                ;38400 Baud @ 48MHz, 0.16%
    PIE1.5       =    1                 ;RCIE
    PIR1.5       =    0                 ;RCIF
    PIE1.4       =    0                 ;TXIE
    INTCON       =    %11000000
    b0          VAR     BYTE BANK0 SYSTEM   ;Used for For/Next Loops
    b1          VAR     BYTE BANK0 SYSTEM   ;Used for For/Next Loops
    CmdCt       VAR     BYTE                ;Similar to ByteCount, for ELM327
    CmdSet      VAR     WORK.1              ;Indicates a Command has been received from the PC
    ElmBuf      VAR     WORK.3              ;ELM Data Received before Init_LCD Completed
    ElmSet      VAR     Work.0              ;End of Transmissions USART RX (Input from ELM), denoted by $D0 (CR)
    Hin0        VAR     BYTE BANK0 SYSTEM   ;USART Input from ELM327, BYTE0
    InBufIndex  VAR     BYTE BANK0 SYSTEM   ;Index used to move BYTES from Hinx to InBuf[InBufIndex]
    Work        VAR     BYTE                ;Working Bits  
    ' Alias for easy access to bit variables: 
    hmRptVarBitArray0     var  byte  
    ' Endpoint 1 IN variables: 
    ' ======================== 
    ElmData   var   byte[23]  
    OER   var   hmRptVarBitArray0.0
    FER   var   hmRptVarBitArray0.1
    ' Endpoint 1 OUT variables: 
    ' ========================= 
    ByteCount   var   byte
    CmdData   var   byte[23]
      Goto start              ' Skip around interrupt handler
    ' ************************************************************************
    ' Subroutines:
    ' ************************************************************************
    ; --- *** RX_INT Interrupt Handler from ELM327 *** ---------------------------------------------------------------------
        Hin0 = RCREG1
    ;    RCSTA1.4 = 0                                    ;CLOERR
    ;    RCSTA1.4 = 1                                    ;CLOERR
        IF (Hin0 <> $0D) AND (Hin0 <> $29) THEN         ;CR or ">"
            ElmData[InBufIndex] = Hin0
            InBufIndex = InBufIndex + 1
            ;EP1XmtDataReady = TRUE
            GOTO Leave
        ELSEIF Hin0 = $0D THEN                          ;Carriage Return
            b1 = InBufIndex - 1
            ElmData[b1] = Hin0
            FOR b0 = InBufIndex TO 22
                ElmData[b0] = 0
            NEXT b0
            EP1XmtDataReady = TRUE
            InBufIndex = 0
            GOTO Leave
    ;    USBService
      USB_Enum_Complete = 0
    ' ************************************************************************
    ' USB Init Code:
    ' ************************************************************************
        gosub InitUSBVars
        RTS = 1                     ;Active Low, ELM Request To Send
        Work = 0                    ;Start all Working Bits at 0
        InBufIndex = 0              ;Clear Input Buffer Index for ELM UART
        USBW_On = 0
        Pause 10
        USBInit                 ' Init USB and wait until configured
        HandleEp1Rcv = FALSE
      USBService  ; Must service USB regularly
      HandleEp1Rcv = FALSE
    ;HIDMaker created USB related code goes here next
      HandleEp1Rcv = TRUE       ' Indicate that we have data to handle
        GOSUB Send_Elm           ;We now have data from the USB to send to ELM
      OER = RCSTA1.1              ;UART Over Run Error
      FER = RCSTA1.2.              ;UART Framing Error
      EP1XmtDataReady = TRUE
    ;More HIDMaker generated USB code
        RTS = 0
            LOOP WHILE PIR1.4 = 0
        TXREG1 = $29
            FOR b0 = 0 TO (ByteCount - 1)
                LOOP WHILE PIR1.4 = 0
                TXREG1 = CmdData[b0]
            NEXT b0
                LOOP WHILE PIR1.4 = 0
            TXREG1 = $0D
            HandleEp1Rcv = FALSE
        RTS = 1
    Last edited by mpgmike; - 4th March 2018 at 18:24.

  2. #2

    Default Re: Elm327 obd

    The PORTC UART pins on the K50 have analog capability, so try turning that off with ANSELC = 0

  3. #3
    Join Date
    Apr 2014

    Default Re: Elm327 obd

    I skipped some of the code for brevity's sake; here is my PORT SFRs:
    ; --- *** PORT Related SFRs *** ----------------------------------------------------------------------------------------
    TRISA        =    %01000000
    TRISB        =    0
    TRISC        =    %11000000
    ANSELA       =    0
    ANSELB       =    0
    ANSELC       =    0

  4. #4

    Default Re: Elm327 obd

    Just to make sure I'm following you...
    From the K50, the logic analyzer shows 0xA5, 0x8A, 0x96, 0xAC
    So the PC->K50 USB is ok... you see "ATZ", but the K50 uart TX is what's wrong? The above should have been "ATZ"?

    I'll look back over the uart setup, but in the meantime try transmitting a "U" (0x55) on the uart and measure the bit times with a scope
     LOOP WHILE PIR1.4 = 0
     TXREG1 = $55
     GOTO txtest
    At 38400 bit times should be ~26us

  5. #5
    Join Date
    Apr 2014

    Default Re: Elm327 obd

    I finally got it working. The big thing was it seems I missed traces on 2 of the ELM327 board that tie pins 5 & 6 to Vdd. Pin 5 holds the memory while pin 6 is the Baud selector. Ran a jumper on the bottom of the board and now it works.

Similar Threads

  1. Replies: 8
    Last Post: - 5th March 2011, 19:31
  2. OBD-2 Question
    By oslinux in forum General
    Replies: 9
    Last Post: - 5th May 2007, 21:34
  3. OBD-2 Input to the PIC
    By oslinux in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 4th April 2007, 14:00
  4. OBD II Protocol
    By L_Gaminde in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 30th July 2005, 06:12

Members who have read this thread : 20

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts