Problems whit Carloop, How to start Read Cam bus!

Hi, i programming my carloop whit electron Particle, i have many problems. firts, i used that example! Visualize Car Data With Carloop And Blynk - Hackster.io and i connect my carloop and read the sensor in my car! but i can’t read the FUEL_TANK_LEVEL_INPUT and really need read the tank.
that’s the list of PID’s
Printing PIDs 0-20 (HEXIDECIMAL)

Monitor status since DTCs cleared
Fuel system status
Calculated engine load
Engine coolant temperature
Short term fuel trim Bank 1
Long term fuel trim Bank 1
Intake manifold absolute pressure
Engine RPM
Vehicle speed
Timing advance
Intake air temperature
Throttle position
Oxygen sensors present (in 2 banks)
Oxygen Sensor 1 A:Voltage B:Short term fuel trim
Oxygen Sensor 2 A:Voltage B:Short term fuel trim
OBD standards this vehicle conforms to
Run time since engine start

PIDs supported [21 - 40]
Printing PIDs 21-40 (HEXIDECIMAL)

Distance traveled with malfunction indicator lamp (MIL) on
Commanded evaporative purge
Warm-ups since codes cleared
Distance traveled since codes cleared
Absolute Barometric Pressure

PIDs supported [41 - 60]

Printing PIDs 41-60 (HEXIDECIMAL)

Control module voltage
Absolute load value
Relative throttle position
Absolute throttle position B
Accelerator pedal position D
Accelerator pedal position E
Commanded throttle actuator


how can read the fuel level input tank?? my car is Suzuki Swift 2018,

Help me please …

@samueldavid,

You have a good start now that you have the list of PIDs.
The next step is to modify the example code following Emerson’s instructions in this step:

When you have done that step, you can use the share your app in Particle Build to share the code here so we can check it over. The instructions to share it are here:
https://docs.particle.io/guide/getting-started/build/photon/#sharing-your-app

Once those steps are working, then maybe @egarl004 can help out with the Blynk aspect.

Hi Cyclin, nice to meet you! yes, i utilize that example and is great! but my question is how can read the Fuell tank level?
In that example and according to my pid list, my car don’t see me the level tank. I try to raed the OBD port but i can’t, sorry but i really new whit that.
How i can read all the port and see in my serial port?

i try this!

but i see nothing.

@samueldavid,

I forgot to provide one other link. This one has lots of information on the OBD2 CAN messages and how to interpret them:

However, I just realized that the PID you are looking for is not on your list.
I would suggest getting hold of a diagnostic scan tool and see if the tool can show the fuel level.
If the tool can do it, then there might be an issue with your code to read the list of PIDs (such as needing Extended CAN).

Also, note the link above has a section on Non-Standard PIDs and exceptions to ETI membership. Suzuki is on that list, which might be related to this puzzle.

I was not able to review your code. A screen shot of a small snippet of code will not help. It is necessary to see the full code, especially the code where you make the request message,

Hi, Cyclin well i reed my OBD port and thats is the response

CAR ON

): : [[code = Finished
114;1af;1b8;124;120;122;129;116;130;131;Done

CAR OFF

): : [[code = Finished
3d1;3d5;3d0;3d4;3d9;3e8;3d1;3d5;3d0;3d4;Done

But I do not know what that means, LOL… :confused:

that is the code what used.

You can help me whit my doubt?

Thanks

@samueldavid,

Sorry, I can not read your code like that. Maybe try copy and pasting your code into the forum here.

Sorry!!! thats is the code…

I read the port OBD2, but i don’t understand what means the PID, the PIDs that I receive…

i receive that
CAR ON


CAR ON

): : [[code = Finished
114;1af;1b8;124;120;122;129;116;130;131;Done

CAR OFF

): : [[code = Finished
3d1;3d5;3d0;3d4;3d9;3e8;3d1;3d5;3d0;3d4;Done


this is the code!




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


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 printValues();
void printValuesAtInterval();
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");
}
void loop() {
    printValuesAtInterval();
}
void printValuesAtInterval() {
    static const unsigned long interval = 1000;

    static unsigned long lastDisplay = 0;
    if(millis() - lastDisplay < 1000)
    {
        return;
    }
    lastDisplay = millis();
    printValues();
}
void printValues(){
    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");   
}

@samueldavid,

I can see what is going on now.
Essentially, your code is dumping the message ID to a String (but even that is not quite what you would expect) and then sending the String to Serial.

What you want to do is check the message ID to see if it is the message you want.
Once you find the correct message, you want to extract the message data.

You might be better off with the VIN reader sample as a starting point. This example reads messages until it gets the VIN data, puts it into a String and sends it to Serial:

You could modify the example to go through a list of PIDs (not just the VIN) and print out each PID. That would be a nice first stage to get working. Edgar’s Hackster project will help out a lot at this stage to get this list.

However, that would be the raw data at that stage. The next step would be to decode the raw data. This Wikipedia page gives you some of the math to decode it:

Hi Cyclin, I solved the read data well i used this code,
// This #include statement was automatically added by the Particle IDE.
#include <carloop.h>
// Set up the Carloop hardware
Carloop carloop;

int canMessageCount = 0;

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

void loop() {

carloop.update();
updateCanMessageCount();

}

void updateCanMessageCount()
{
CANMessage message;
while(carloop.can().receive(message))
{
Serial.printf(“ID:\tBit 0\tBit 1\t Bit 2\tBit 3\tBit 4\tBit 5\tBit 6\tBit 7\tBit 8”);
Serial.println(“”);
Serial.print(message.id, HEX);
Serial.print(“\t”);
Serial.print(message.data[0], HEX);
Serial.print(“\t”);
Serial.print(message.data[1], HEX);
Serial.print(“\t”);
Serial.print(message.data[2], HEX);
Serial.print(“\t”);
Serial.print(message.data[3], HEX);
Serial.print(“\t”);
Serial.print(message.data[4], HEX);
Serial.print(“\t”);
Serial.print(message.data[5], HEX);
Serial.print(“\t”);
Serial.print(message.data[6], HEX);
Serial.print(“\t”);
Serial.print(message.data[7], HEX);
Serial.print(“\t”);
Serial.print(message.data[8], HEX);
Serial.println(“\tEND”);
canMessageCount++;
}
}

and that’s the response

ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
122 0 0 0 2 11 0 0 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
124 0 13 B2 24 B8 11 26 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
130 7 8F 3 2F 0 3 35 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
116 0 F FF F FF 0 0 33 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
180 0 12 D4 0 0 0 0 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
1AD 10 0 50 0 C3 CD 2 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
114 0 1F FF F FF 1 40 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
1AF 0 0 17 0 80 0 0 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
1B8 0 0 0 0 0 0 0 0 0 E ND
ID: Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Bit 8
1EF 0 80 0 80 0 46 81 1A 0 E

But went i don’t understand what means, i read the wiki documenatation and and i don’t know how read the the bit,

or what means

I used the code you gave me, but it did not work out I never found a message, I mean poor with several PID according to the wikipedia documentation but I never found the PID.

The first thing you have to do is filter or validate the message.data[2] , which contains the PID that the car send you (RPM, Speed, and so on …) . Depending on which PID you have, you have apply a specific formula according the wikipedia’s article you had read; by example :

you have to read A = message.data[3] and B = message.data[4] and apply that formula to obtain the RPMs. You have to do the same thing with all the data you want to read.

Hi Maleficarum, Great News for your help, I managed to read the data of the cam and select the one I want. but I’m not sure if the data is correct, but i have dome doubt, if message.data[2] it’s the PID and message.data[3] it’s data A and message.data[4] it’s B, what means message.data[1]?

and how i know if data is correct well, in my case I take the data 2f to know the value of gasoline but it does not give me exact always changes. that is my code

#include <carloop.h>
// Set up the Carloop hardware
Carloop carloop;

int canMessageCount = 0;

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

void loop() {

carloop.update();
updateCanMessageCount();

}

void updateCanMessageCount()
{
CANMessage message;
while(carloop.can().receive(message))
{
if(message.data[2] == 0x2F){
Serial.printf(“Bencina:”);
Serial.println(“”);
Serial.print(“PID\tA\tB\tC\tD”);
Serial.println(“”);
Serial.print(message.data[2], HEX); //PID
Serial.print(“\t”);
Serial.print(message.data[3], HEX); //A
Serial.print(“\t”);
Serial.print(message.data[4], HEX); //B
Serial.print(“\t”);
Serial.print(message.data[5], HEX); //C
Serial.print(“\t”);
Serial.print(message.data[6], HEX);
Serial.println(“\t”);
//Serial.println(“\tEND”);
canMessageCount++;
}else if(message.data[2] == 0x31){
Serial.printf(“Revoluciones:”);
Serial.println(“”);
Serial.print(“PID\tA\tB\tC\tD”);
Serial.println(“”);
Serial.print(message.data[2], HEX); //PID
Serial.print(“\t”);
Serial.print(message.data[3], HEX); //A
Serial.print(“\t”);
Serial.print(message.data[4], HEX); //B
Serial.print(“\t”);
Serial.print(message.data[5], HEX); //C
Serial.print(“\t”);
Serial.print(message.data[6], HEX);
Serial.println(“\t”);
//Serial.println(“\tEND”);
canMessageCount++;
}else if(message.data[2] == 0x0C){
Serial.printf(“Distancia:”);
Serial.println(“”);
Serial.print(“PID\tA\tB\tC\tD”);
Serial.println(“”);
Serial.print(message.data[2], HEX); //PID
Serial.print(“\t”);
Serial.print(message.data[3], HEX); //A
Serial.print(“\t”);
Serial.print(message.data[4], HEX); //B
Serial.print(“\t”);
Serial.print(message.data[5], HEX); //C
Serial.print(“\t”);
Serial.print(message.data[6], HEX);
Serial.println(“\t”);
//Serial.println(“\tEND”);
canMessageCount++;
}else if(message.data[2] == 0x0D){
Serial.printf(“Velocidad:”);
Serial.println(“”);
Serial.print(“PID\tA\tB\tC\tD”);
Serial.println(“”);
Serial.print(message.data[2], HEX); //PID
Serial.print(“\t”);
Serial.print(message.data[3], HEX); //A
Serial.print(“\t”);
Serial.print(message.data[4], HEX); //B
Serial.print(“\t”);
Serial.print(message.data[5], HEX); //C
Serial.print(“\t”);
Serial.print(message.data[6], HEX);
Serial.println(“\t”);
//Serial.println(“\tEND”);
canMessageCount++;
}
}

}

and my response is that

Revolution:
PID A B C D
31 30 30 36 37
Speed:
PID A B C D
D 0 0 0 0
Revolution:
PID A B C D
31 30 30 36 37
Revolution:
PID A B C D
31 FE 2 C9 0
Revolution:
PID A B C D
31 DF 3 D 0
Revolution:
PID A B C D
31 B4 3 20 0
Fuell tank:
PID A B C D
2F 0 80 20 0
Fuell tank:
PID A B C D
2F 20 D8 20 DC
Bencina:
PID A B C D
2F 3 2C 1 0

thanks for support me!

The important data in the message start from byte 3 (message.data[2]) ; to know how is the can message structured see this article.

In your case, if you are lookin to parse the fuel level input (0x2f), you have to apply the formula over the byte 4 (message.data[3]) as follows:

data[3] / 2.55;

be sure tu read all the formulas you can need from the wikipedia article. I noticed that the fuel level input can be changing … but the variation is not notorious for me.

@samueldavid & @maleficarum,

With the latest code you posted and the raw responses in hex format, I can now see what is actually going on. The important information you are missing is in byte[1]. Byte[1] contains the Mode data. When you send a CAN message with the request for these PIDs, you have to use Mode 1 or Mode 2. The other modes are used for other kinds of data. So, you have to look for responses with Mode 0x41 (the response to Mode 1) or Mode 0x42 (the response to Mode 2). This is described in the Wikipedia article.

For example, if you receive a response to Mode 3, the data is a Diagnostic Trouble Code, which will not include the engine RPM. The data bytes will mean something totally different, which appears like garbage when you are looking for the engine RPM.

The code you posted is not complete, so I have no idea if your request is using Mode 1 or Mode 2. Therefore, I can tell that you are interested in either the Mode 0x41 or 0x42 responses, but I can not tell which one.

My bad about that important detail.

Hi Cyclin, Thanks for support me! this is the information frame that I have from the can bus,

D: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
122 0 0 0 2 11 0 0 0 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
124 0 13 B2 24 B8 11 26 0 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
130 7 8F 3 2F 0 3 35 0 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
116 0 F FF F FF 0 0 33 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
180 0 12 D4 0 0 0 0 0 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
1AD 10 0 50 0 C3 CD 2 0 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
114 0 1F FF F FF 1 40 0 0 END

ID: HEX 0 BYTE 1 PID 2 A B C D Bit 7 Bit 8
1AF 0 0 17 0 80 0 0 0 0 END

Is the data I need to take data 1? to be able to know in what way the plot comes? It always changes me, it’s never the same. :confused:

i try this. for convert the full tank. But i don’t sure is that correct.!



void updateCanMessageCount()
{
CANMessage message;
while(carloop.can().receive(message))
{

    if(message.data[2] == 0x2F){
          Serial.printf("Bencina:");
          Serial.println("");
          Serial.print("PID\tA\tB\tC\tD");
          Serial.println("");
          Serial.print(message.data[2], HEX); //PID
          Serial.print("\t");
          Serial.print(message.data[3], DEC); //A
          Serial.print("\t");
         // Serial.print(message.data[4], DEC); //B
          //Serial.print("\t");
          //Serial.print(message.data[5], HEX);   //C
          //Serial.print("\t");
         // Serial.print(message.data[6], HEX);
          //Serial.println("\t");
          bencina = ((100/255) * message.data[3],DEC);
          Serial.print( bencina);
          Serial.println("\t");
          //Serial.println("\tEND");
          canMessageCount++;
          
          
          
          
    }
}

}



according @cyclin_al1 , you have to validate byte 2 (message.data[1]) against 0x41 which your code isn’t doing. The changing data is cause the same received code (lets say 0x2F) would be a response from other modes as well and you have to add something like :

if(message.data[2] == 0x2F && message.data[1] == 0x41){ }