CAN BUS Intel format data

Hi
I am building an electric go-kart for my autistic son. Have built a GPS speedo using Arduino with an OLED display - I want to add the motor RPM to it. The motor controller supports CAN BUS and I have the UNO Can Shield from DF Robot. When I run it all through CANHACKER and switch to Intel format I can see the data I want

image001

The value I want in the final integer value (32000). There is actually an offset of 32000 on this value.

Question - in Arduino IDE how do I return this value from the frame ? I can return the 8 byte values but want this one for the display.

Apologies if this has been asked before - I did a search and there is a lot on CAN BUS but couldnt see this one.

Thanks

sketch?
schematic?
picture?

1 Like

Welcome! What do you mean by "CAN Bus intel format data"? Are you talking about the endian and little-endian? This link may be your answer: What are big-endian and little-endian? Definition from SearchNetworking

Here is the code - it is the standard code in the examples folder

// 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 2                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_250KBPS, 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  Length: %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
*********************************************************************************************************/

According to the document Byte 6 and 7 are the RPM with an offset of 32000

Screenshot 2023-08-13 123829

So when the motor isnt running this value should be 32,000 which is what shows in Can Hacker when I switch it to Intel format

The values provided by the code look like.

12:36:07.670 -> Extended ID: 0x180117EF Length: 8 Data: 0x1F 0x02 0x00 0x7D 0x00 0x7D 0x00 0x7D
12:36:07.675 -> Extended ID: 0x180117EF Length: 8 Data: 0x1F 0x02 0x00 0x7D 0x00 0x7D 0x00 0x7D
12:36:07.701 -> Extended ID: 0x180117EF Length: 8 Data: 0x1F 0x02 0x00 0x7D 0x00 0x7D 0x00 0x7D

I just want the RPM value so I can add it to the screen with the GPS speed.

Thanks !

A single data point makes it difficult to see what is going on.
Are you able to make the motor rotate at a particular speed, for example 6 RPM or 60 RPM?
Can you also make it turn in reverse?

изображение
not the same ID?

Perhaps but it still returns the correct data when displayed in CanHacker.

Thanks

See figure 4, https://www.xanalyser.uk/wp-content/uploads/2020/11/Chapter-2-CAN-Signals-new.pdf

I cannot make sense of the CANHacker 'Integer Value' section of the display. There may be a field missing on the left, then it would make sense as 4 pairs of 16 bit value high/low , low/high values.

Using the data from the Arduino, if you look at the last 2 bytes, multiply the high byte 0x7D by 2^8 then add the low byte 0x0 you get 32000 decimal.

// 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 2                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup() {
  Serial.begin(115200);
  if (CAN0.begin(MCP_ANY, CAN_250KBPS, 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)sprintf(msgString, "Extended ID: 0x%.8lX  Length: %1d  Data:", (rxId & 0x1FFFFFFF), len);
    else sprintf(msgString, "Standard ID: 0x%.3lX       DLC: %1d  Data:", rxId, len);   // Determine if ID is standard (11 bits) or extended (29 bits)

    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();
    }
    Serial.println(rxBuf[len - 1] * 256 + rxBuf[len - 2]);
  }
}

Works perfectly - thanks mate.

Can I ask for my own learning - why did you 'len - 1' and 'len - 2' instead of the byte number rxBuf[7] ?

Thanks again !

today i think that 'len - 1' is not so good idea.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.