How do I read messages?

Sorry, I’m new here. I just got my carloop a few months ago. I just got time to try to make it work this past week.
I figured out that I have no idea what to do.
I got a sample code running and showing me batt voltage.
I got it to tell me that it received messages.
What do I need to do/study to figure out out to read the messages?
I would like to read the PIDs such as intake temp or etc, but I can’t get anywhere.
I guess I just need some guidance. Hopefully it is something I can figure out because I’m really excited.

if it matters, my cars are 05 Corvette and 98 Camaro

1 Like

This community project appears to do what you want. Perhaps you can adapt what he has written? If you run into trouble give us an update (with error messages!) so we can help.

Definitely glad to help. Also check out the visualize data with blynk project here

That should be a good start. If you simply want to read values across the console on your machine, just add some print lines for whatever sensors you have available. Math has already been created(though I haven’t qa’d everything yet) remember to look at the connection details and have your drivers installed.

As a newbie, I thought I would share my first few experiences (I am not an expert by any means).

I bought a particle photon and the carloop ODB-II adapter. I wanted to read from serial, so I also picked up a USB cable. Note that the photon gets power from the ODB port even when the car is off.

I had difficulty using the OSX dev, because of compilation issues. Other folks indicated that an “ignore” file is needed, but I went with the online build platform and that worked best.

On the build site, I created a new project and created two new files: carloop.cpp and TinyGPS.cpp, along with the corresponding headers. Note that the online build would not allow me to use “+” characters after GPS. I then copied the contents of the carloop.cpp/.h and TinyGPS++.cpp/.h from the carloop GitHub.

The main program goes into the “.ino” file (auto-generated with a new project). I used:

// This #include statement was automatically added by the Particle IDE.
#include "TinyGPS.h"

// This #include statement was automatically added by the Particle IDE.
#include "carloop.h"

Carloop<CarloopRevision2> carloop;

void setup() {
    carloop.begin();
    Serial.begin(9600);
}

void loop() {
    //Serial.println("Beginning loop before message read");
    carloop.update();
    CANMessage message;
    while(carloop.can().receive(message))
    {
        Serial.printf("ID %03x len %d", message.id, message.len);
        for(int i = 0; i < message.len; i++) {
            Serial.printf("%02x ", message.data[i]);
        }
        Serial.print("\n");
    }
}

Note that “message.length” in the initial carloop example is now “message.len”, according to the particle CANMessage documentation.

After flashing the program onto the photon and plugging into my car, I opened terminal and listened to the USB port at 9600 baud using this command:

$ screen /dev/tty.usbmodem1421 9600

Note that the usb modem number does not stay always consistent across flashes/disconnects.

Every couple of seconds, I received messages like:

ID 17f00010 len 820 10 00 00 00 00 00 00

It does not look like the data payload is printed, which is what I am investigating now!

For sure your data payload is being printed:

In your output, the 820 is the length 8 and the first byte 0x20 of the payload with no space in between. You might want to adjust your code to add a space to make the output easier to read.

In some cars, listening on the OBD port CANbus does not get a lot of activity.
Once you send a request onto the CANbus, then the responses coming back is where things start to get interesting!

Good luck; let us know if you need more details!

1 Like

Alan – many thanks for the very speedy reply. I adjusted my code to mimic the VIN reading in How to Request VIN - Software - Carloop Community. When I send my request, however, I still receive
ID 17f00010 len 8 20 10 00 00 00 00 00 00
instead of an initial reply with ID=7E8, as listed by Julien. Is the ECU required to reply? There may be a mistake on my end (code below). I will try Julien’s VIN app also.

#include "TinyGPS.h" // Tiny GPS Header (Currently Unused)
#include "carloop.h" // Carloop Rev 2

SYSTEM_THREAD(ENABLED); // To not block the main program while searching for WiFi
#define OBD_CAN_BROADCAST_ID 0x7DF

Carloop<CarloopRevision2> carloop; // Instantiate Carloop Object

void setup() {
    carloop.begin(); // Creates the appropriate CANChannel (https://docs.particle.io/reference/firmware/photon/#can-canbus-)
    Serial.begin(9600); // Open serial connection at 9600 baud, bits per second (https://docs.particle.io/reference/firmware/photon/#serial)
    
    delay(45000); // After Booting, Delay 45 seconds
    
    Serial.print("SENDING MESSAGE! \n");
    // Message to transmit
    CANMessage message;
    message.id = OBD_CAN_BROADCAST_ID;
    message.len = 8;
    message.data[0] = 0x02; // Data Length Code (DLC)
    message.data[1] = 0x09; // Mode 09 (https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_09)
    message.data[2] = 0x02; // PID 02 Vehicle Identification Number (VIN): 17-char ASCII-encoded, left-padded with 0x00
    carloop.can().transmit(message);
    Serial.print("MESSAGE SENT! \n");
}

void loop() {
    carloop.update(); // Is this needed?
    CANMessage message; 
    while(carloop.can().receive(message))   // Uses the CANChannel.receive() to query if message is received.
    {                                       // Returns true/false, and stores message in given parameter (message object)
        // CANMessage contains:
        //      uint32_t id;
        //      bool extended;
        //      bool rtr;
        //      uint8_t len;
        //      uint8_t data[8]
        Serial.printf("ID %03x len %d ", message.id, message.len); 
        for(int i = 0; i < message.len; i++) {
            Serial.printf("%02x ", message.data[i]);
        }
        Serial.print("\n");
    }
}

@almlof, Did you get a chance to try Julien’s VIN app exactly? In theory, you can flash the firmware to your photon directly from the carloop.io examples pages.

If Julien’s example works, then we should look at your code, and how it is different from his example.

Getting to the protocol, there can be traffic on the CANbus from various modules.
However, when you send a request from ID 0x7DF, there should be a response from an address between 0x7E8 to 0x7EF. An ID 0x17F is not finding any matches when I google it, so that might be a clue.

I wonder if using the Serial interface to copy out every single message is messing up your code? If there is a lot of traffic on the CANbus, you might be missing messages during the time the code is sending data to Serial.

Good news. Once I stopped printing all of the messages, and instead focused on replies with 0x7E8, I was able to query a number of PIDs for useful information. Thanks again for the help!!

Whew, lucky guess. Glad to hear you got it working @almlof!

For the sake of experimenting, have you ever tried counting all the messages on the CANbus? It would be interesting to know, but it would be important to list the car make, model & year to provide context.

That is a great suggestion; I want to try that next and find any manufacturer-specific information. I will report back.

Alan, I looked into the can-utils, first in hopes that I could execute it on my Mac (does not appear possible, as you also discovered), and second to run the CAN functions from an old (circa 2011) raspberry pi, which failed possibly due to power draw (the CAN0 interface appeared only for an instant).

My question is, if I store the CAN messages in a data structure, shouldn’t I get the same result as if I run a CAN dump? i.e.:

#include "TinyGPS.h" // Tiny GPS Header (Currently Unused)
#include "carloop.h" // Carloop Rev 2

SYSTEM_THREAD(ENABLED); // To not block the main program while searching for WiFi
Carloop<CarloopRevision2> carloop; // Instantiate Carloop Object

const int len = 10; // Length of data to hold in array
String data[len]; // Array to hold data

void setup() {
    carloop.begin(); // Creates the appropriate CANChannel
    Serial.begin(9600); // Open serial connection at 9600 baud, bits per second
    Serial.print("Starting Up \n");
    for (int i=0; i<11; i++) {
        Serial.print(i+" ");
        delay(1000); // Delay 1 second
    }
    carloop.update();
    int i = 0;
    CANMessage message;
    while (i < len) {
        if(carloop.can().receive(message)) {
            data[i] = String::format("%02x", message.id);
            i++;
        }
    }
    Serial.println("Finished");
    for (int i = 0; i < len; i++) {
        Serial.print(data[i]+";");
    }
    Serial.println("Done \n");
}
void loop() {
}

Is there something that CANutils does differently? Or, can it simply display more data? Thanks again for your continued help!

Post removed as it is a double-post. It will be clearer to others in its own thread.