Teensy 3.2 and canbus connections

Status
Not open for further replies.

SteveSFX

Well-known member
Hello all

Been playing around with my new Teensy 3.2 (had it a while.... never used it).
Was planning to add a MCP2515 Can-bus breakout board to it, so that I could decode the Can-bus signals from my truck (only want to read them).
Then.... I notice the Can-bus pins on the Teensy itself....

Can I connect these directly to the trucks Can-bus? I cannot find connections for this anywhere on the net, but in theory it would work.... right?
I imagine I may need a termination resistor or something (120R)?

Looking at the Can-bus plug in the truck, I can see Can-bus High and Can-bus low, but how do they relate to Canbus RX/TX on the Teensy?

Any help would be gratefully received.... been Googling for hours!
 
OK... We are up and running.....

Biblical amount of data..... how the heck do you extract RPM, Speed etc
Clearly it need filtering..... hmm

Code:
// CAN Receive Example
//

#include <mcp_can.h>
#include <SPI.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128];                        // Array to store serial string

#define CAN0_INT 3                              // Set INT to pin 2
MCP_CAN CAN0(14);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);

  delay(3000);

  Serial.println("System starting....");
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.

  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
  
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, rxBuf);      // Read data: len = data length, buf = data byte(s)
    
    if((rxId & 0x80000000) == 0x80000000)     // Determine if ID is standard (11 bits) or extended (29 bits)
      sprintf(msgString, "Extended ID: 0x%.8lX  DLC: %1d  Data:", (rxId & 0x1FFFFFFF), len);
    else
      sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);
  
    Serial.print(msgString);
  
    if((rxId & 0x40000000) == 0x40000000){    // Determine if message is a remote request frame.
      sprintf(msgString, " REMOTE REQUEST FRAME");
      Serial.print(msgString);
    } else {
      for(byte i = 0; i<len; i++){
        sprintf(msgString, " 0x%.2X", rxBuf[i]);
        Serial.print(msgString);
      }
    }
        
    Serial.println();
  }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/
 
I think I need to find a better library that I can understand....

The line: CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s) is retrieving the data.... But I don't understand how to change that to obtain what I want.
Do I need filtering, if I am only requesting a single item anyway?

From what I understand, the first part of that request is the id of what I require, which I believe is 01 for Mode 1 (which is current data), and then 0c for example, which should be RPM.
But, entering those values in any format fails.

I clearly don't quite get it.
 
I think I need to find a better library that I can understand....

The line: CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s) is retrieving the data.... But I don't understand how to change that to obtain what I want.
Do I need filtering, if I am only requesting a single item anyway?

From what I understand, the first part of that request is the id of what I require, which I believe is 01 for Mode 1 (which is current data), and then 0c for example, which should be RPM.
But, entering those values in any format fails.

I clearly don't quite get it.

If you are connecting to a vehicle that supports OBD2 (IIRC anything manufacured after 2004), you need to request the data with the corresponding PID (https://en.wikipedia.org/wiki/OBD-II_PIDs - service 01).
For this, you need to filter any messages with a response header of 0x7E8 (need to check if this is for trucks too), verify your response PID has a value of 0x40 added to it (sucessful response indicator eg if you requested PID 0x01, you'll get 0x41 in response from the ECU) and then extract the response data from the payload.

To do this, you need to understand the request and response structure of the OBD protocol over Can bus.
Start with this video (it explains UDS - the underlying application layer within car can networks, but covers the request-response structure) - https://www.youtube.com/watch?v=lY585Yp7zeY

You can see an example of simple PID's in SK Pang's sketch
https://github.com/skpang/Teensy_CAN-Bus_ECU_reader
 
Another sughestion is to export the data to something like excel and try understand what can codes relate to which module. Turning the wipers on and off for example should be the body control module
 
Check out the examples from IFCT Library for teensy, should get you up and running. As for the truck you seem to be getting frames however, on some vehicles OBD is accessed over CAN as extended rather than standard. Granted if the EACEN bit is not set in the MCR register, a mailbox can pull both extended and standard frames from the same mailbox, otherwise each mailbox bit needs to be set to specify it to be explicitly only one type. I would suggest to try the fifo example with interrupts or polling, depending on your preference. If you want to get the correct ECU address over CAN I also suggest you hook up an OBD reader to the truck to read the ECU while logging on teensy, teensy will show you the correct addrese you SHOULD use when addressing commands to the ECU
 
Status
Not open for further replies.
Back
Top