HELP with CAN BUS Receive Data

Hello everyone,

I'm trying to test receiving a signal using the Sparkfun CANbus and the arduino Mega 2560, the send signal is working fine currently. But I have a problem with the receive data:

I realized the following code that we will call *1 and I observe in the arduino console that I block at "CAN init OK" so my void loop is not carried out...
(this code is made in the Seeed library)

By chance I launched the following code *0 from coryjfowler's MCP2515 library which is called Loopback , everything works and moreover if I launch this code *0 then my code *1 then everything works ...

Questions :

Is there a way to check/solve this or do I need to add something in the code.

Maybe change library and code all my code in coryjfowler's MCP2515 library?

I hope my attached code and pictures will lead you to find the problem.

Thanks
Remay

*1 My code

#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
#include "mcp2515_can.h"

//*********************CAN Sheild declarations*********************

const int SPI_CS_PIN = 10;
const int CAN_INT_PIN = 2;
mcp2515_can CAN(SPI_CS_PIN);

//*********************SD Sheild declarations**********************

File myFile;
const int SD_CS_PIN = 9;

//*********************Record Excel declarations*******************

char filename[16];
unsigned long reads_recorded = 0;
uint16_t i = 0;

//*********************Switch and Led declarations*****************

const int buttonPin = 40;     // the number of the pushbutton pin
const int ledPin =  41;      // the number of the LED pin

//********************* Program SETUP *****************************

void setup() {

  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(CAN_INT_PIN, INPUT); 
  
  SERIAL_PORT_MONITOR.begin(115200);

  while (CAN_OK != CAN.begin(CAN_500KBPS, MCP_16MHz)) { // init can bus : baudrate = 500k
    SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
    while (1); //wait here forever
  }
  SERIAL_PORT_MONITOR.println("CAN init ok!");

  if (SD.begin(SD_CS_PIN))
  {
    SERIAL_PORT_MONITOR.println("SD card is present & ready");

    //initialise filename
    sprintf(filename, "can_%.03d.csv", i);
    
    myFile = SD.open(filename, FILE_WRITE);
    if (myFile) // it opened OK
    {
      //add header to file
      myFile.println("Time,Pression,Temperature,co2_hydrogen,humidity");
      myFile.close();
      SERIAL_PORT_MONITOR.println("File created!");
    }
    else
      SERIAL_PORT_MONITOR.println("Error opening file");
  }
  else
  {
    SERIAL_PORT_MONITOR.println("SD card missing or failure");
    while (1); //wait here forever
  }
 }
//********************* Fonction ecrire dans Excel ***********************

void writeToFile(float press_pascal, float temp_degC, float co2_true, float humi_pourcent)
{
  myFile = SD.open(filename, FILE_WRITE);
  if (myFile) // it opened OK
  {
    myFile.print(String(minute()));
    myFile.print(":");
    myFile.print(String(second()));
    myFile.print(";");
    myFile.print(String(press_pascal, 2));
    myFile.print(";");
    myFile.print(String(temp_degC, 2));
    myFile.print(";");
    myFile.print(String(co2_true, 2));
    myFile.print(";");
    myFile.println(String(humi_pourcent, 2));
    myFile.close();
  }
  else
    SERIAL_PORT_MONITOR.println("Error opening file");
}

//********************* Program LOOP ************************

void loop() {
  
  unsigned char len = 0;
  unsigned char buf[8];
  unsigned long canId = CAN.getCanId();

 if (digitalRead(buttonPin)== HIGH) 
    {
    digitalWrite(ledPin, HIGH);  // turn LED on
    
    CAN_MSGAVAIL != CAN.checkReceive();
    CAN.readMsgBuf(&len, buf); // read data,  len: data length, buf: data buf
    
    SERIAL_PORT_MONITOR.println("_____Pression_____");
    uint16_t press_raw;
    memcpy(&press_raw, &buf[0], 2); //buf[0] is the first byte in buf, 2 because you want 2 bytes
    float press_pascal = ((press_raw * 0.0078125) - 250);
    SERIAL_PORT_MONITOR.println(press_pascal, 2);  // value to copy on excel

    SERIAL_PORT_MONITOR.println("_____Temperature_____");
    uint16_t temp_raw;
    memcpy(&temp_raw, &buf[2], 2); //buf[2] is the third byte in buf, 2 because you want 2 bytes
    float temp_degC = ((temp_raw * 0.3125) - 273) / 100;
    SERIAL_PORT_MONITOR.println(temp_degC, 2);

    SERIAL_PORT_MONITOR.println("_____CO2_Hydrogen_____");
    uint16_t co2_raw;
    memcpy(&co2_raw, &buf[4], 2); //buf[4] is the fifth byte in buf, 2 because you want 2 bytes
    float co2_true = ((co2_raw * 1) - 0) / 100;
    SERIAL_PORT_MONITOR.println(co2_true, 2);

    SERIAL_PORT_MONITOR.println("_____Humidity_%_____");
    uint16_t humi_raw;
    memcpy(&humi_raw, &buf[6], 2); //buf[6] is the six byte in buf, 1 because you want 1 bytes
    float humi_pourcent = ((humi_raw * 0.4) - 0);
    SERIAL_PORT_MONITOR.println(humi_pourcent, 2);

    writeToFile(press_pascal, temp_degC, co2_true, humi_pourcent);
    ++reads_recorded;

    }
    else 
    {
    digitalWrite(ledPin, LOW); // turn LED off
    Serial.println("off");
    }; 
  
//********************* Creation new files excel ***********************
  
  //create new filenames for every 1800 lines written to file
  if(reads_recorded == 1800) {  //reset counter
    reads_recorded = 0;

    //increment file counter
    ++i;
    
    //update finename
    sprintf(filename, "can_%.03d.csv", i);

    myFile = SD.open(filename, FILE_WRITE);
    if (myFile) // it opened OK
    {
      //add header to new file
      myFile.println("Time,Pression,Temperature,co2_hydrogen,humidity");
      myFile.close();
      SERIAL_PORT_MONITOR.println("New File created!");
    }
    else
      SERIAL_PORT_MONITOR.println("Error opening file");
  }
}

*0 The code in coryjfowler's MCP2515 library

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

// CAN TX Variables
unsigned long prevTX = 0;                                        // Variable to store last execution time
const unsigned int invlTX = 1000;                                // One second interval constant
byte data[] = {0xAA, 0x55, 0x01, 0x10, 0xFF, 0x12, 0x34, 0x56};  // Generic CAN data to send

// CAN RX Variables
long unsigned int rxId;
unsigned char len;
unsigned char rxBuf[8];

// Serial Output String Buffer
char msgString[128];

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


void setup()
{
  Serial.begin(115200);  // CAN is running at 500,000BPS; 115,200BPS is SLOW, not FAST, thus 9600 is crippling.
  
  // 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...");
  
  // Since we do not set NORMAL mode, we are in loopback mode by default.
  //CAN0.setMode(MCP_NORMAL);

  pinMode(CAN0_INT, INPUT);                           // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Loopback 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();
  }
  
  if(millis() - prevTX >= invlTX){                    // Send this at a one second interval. 
    prevTX = millis();
    byte sndStat = CAN0.sendMsgBuf(0x100, 8, data);
    
    if(sndStat == CAN_OK)
      Serial.println("Message Sent Successfully!");
    else
      Serial.println("Error Sending Message...");

  }
}

Nice pictures but they do not show much example: the lettering etc is fuzzy, no termination indicated etc. Posting a real schematic instead of a frizzy wiring diagram will help us help you a lot better. What is a capture TR? Cory has a great library, I use it all the time. Loopback shows that you are talking to the MPC2515, not communicating on the bus. In that library there is a send and receive, I suggest you build one of each and get that working first. Be sure to include termination resistors on each end of the bus. I do not have any experience using that shield as I use the little modules from china and they work great with Nano, UNO, etc. Check the MPC2515 crystal and set your init code accordingly, I have seen them with three different values. They can be different, the init portion of the code corrects that. The reason to get those two modules working is to eliminate as many variables as possible. CAN as part of the message is expecting a remote unit to generate an ACK by driving the bus dominate for one clock cycle. A CAN module cannot do that externally or error detection etc of the bus fails. It can do it internally for testing.

2 Likes

The first thing I see is you are using two different CAN libraries. You #include "mcp2515_can.h" in *1 and #include <mcp_can.h> in *0. If *1 is using Seeed's library, it looks like it may have issues again. I would follow @gilshultz's suggestions and advice.

2 Likes

Yes I coded the *1 in the Seeed library my project.

After doing some research I saw people talking about your library and it's the only one to give me correct values *0.

I don't know if I should take my code and write it again under your library or if I can fix the problem in Seeed but I don't know where the problem is...

I have error like that i dont know if you know ?

C:\Users\RORE169\Desktop\A\MCP_CAN_lib-master\examples\CAN_receive\CAN_receive.ino: In function 'void loop()':
C:\Users\RORE169\Desktop\A\MCP_CAN_lib-master\examples\CAN_receive\CAN_receive.ino:96:30: warning: invalid conversion from 'unsigned char' to 'const void*' [-fpermissive]
     memcpy(&temp_raw, rxBuf[2], 2); //buf[2] is the third byte in buf, 2 because you want 2 bytes
                       ~~~~~~~^
In file included from C:\Users\RORE169\Desktop\A\arduino-1.8.19\hardware\arduino\avr\cores\arduino/Arduino.h:25:0,
                 from sketch\CAN_receive.ino.cpp:1:
c:\users\rore169\desktop\a\arduino-1.8.19\hardware\tools\avr\avr\include\string.h:191:14: note:   initializing argument 2 of 'void* memcpy(void*, const void*, size_t)'
 extern void *memcpy(void *, const void *, size_t);
              ^~~~~~

It works because my library is apparently configuring a register on the MCP2515 that Seeed has messed up. I'd suggest using my library, especially if you want further help. If you want to get Seeed to fix their library, you would likely have to get on their forum.

1 Like

Yes, I am working on your library, now for my project because it is more convenient with the MCP2515 but I have a code problem with the `memcpy(&temp_raw, rxBuf[2], 2) ;

The error is `invalid conversion from 'unsigned char' to 'const void*' [-fpermissive].

initialize argument 2 of 'void* memcpy(void*, const void*, size_t)'
extern void *memcpy(void *, const void *, size_t) ;
`

I use memcpy to select the byte and the number of bytes in the rxBuf, I don't know if you have a better way to code this.

I use your code Can receive of your library (the code runs but I get error messages and the temperature reading is wrong ) :

// CAN Receive

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

//*********************CAN Sheild declarations********************

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 
MCP_CAN CAN0(53);    // Set CS 

//*********************SD Sheild declarations**********************

File myFile;
const int SD_CS_PIN = 9;

//*********************Record Excel declarations*******************

char filename[16];
unsigned long reads_recorded = 0;
uint16_t i = 0;

//*********************Switch and Led declarations*****************

const int buttonPin = 40;     // the number of the pushbutton pin
const int ledPin =  41;      // the number of the LED pin

//********************* Program SETUP *****************************

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_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
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  Serial.println("MCP2515 Library Receive Example...");

}
//********************* Program LOOP ***************************

void loop()
{

  if (digitalRead(buttonPin)== HIGH) 
    {
    digitalWrite(ledPin, HIGH);  // turn LED on
    
  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();

    Serial.println("_____Pression_____");
    uint16_t press_raw;
    memcpy(&press_raw, &rxBuf[0], 2); //buf[0] is the first byte in buf, 2 because you want 2 bytes
    float press_pascal = ((press_raw * 0.0078125) - 250);
    Serial.println(press_pascal, 2);  // value to copy on excel

    Serial.println("_____Temperature_____");
    uint16_t temp_raw;
    memcpy(&temp_raw, rxBuf[2], 2); //buf[2] is the third byte in buf, 2 because you want 2 bytes
    float temp_degC = ((temp_raw * 0.03125) -273) ;
    Serial.println(temp_degC, 2);

    Serial.println("_____CO2_Hydrogen_____");
    uint16_t co2_raw;
    memcpy(&co2_raw, &rxBuf[4], 2); //buf[4] is the fifth byte in buf, 2 because you want 2 bytes
    float co2_true = ((co2_raw * 1) - 0) / 100;
    Serial.println(co2_true, 2);

    Serial.println("_____Humidity_%_____");
    uint16_t humi_raw;
    memcpy(&humi_raw, &rxBuf[6], 2); //buf[6] is the six byte in buf, 1 because you want 1 bytes
    float humi_pourcent = ((humi_raw * 0.4) - 0);
    Serial.println(humi_pourcent, 2);
  }
}
  else 
      {
         digitalWrite(ledPin, LOW); // turn LED off
         Serial.println("off");
      }
} 

My first suggestion is to avoid using memcpy().

Something like this

Becomes this

    uint16_t press_raw = (rxBuf[0] << 8) & rxBuf[1];  /* adjust order for endianness */
    float press_pascal = ((press_raw * 0.0078125) - 250);
    Serial.println(press_pascal, 2);  // value to copy on excel

A single byte would just be

uint8_t single_byte = rxBuf[n];

1 Like

hello , everythings works but only when i do a reset or if a on/off the alimentation of my project.
I know that beacause the Led doesnt work before i do the reset...

Do you thinks is a error in my code ?
Thx you to help me to solve that

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

//*********************CAN Sheild declarations********************

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 
MCP_CAN CAN0(53);    // Set CS 

//*********************SD Sheild declarations**********************

File myFile;
const int SD_CS_PIN = 9;

//*********************Record Excel declarations*******************

char filename[16];
unsigned long reads_recorded = 0;
uint16_t i = 0;

//*********************Switch and Led declarations*****************

const int buttonPin = 40;     // the number of the pushbutton pin
const int ledPin =  41;      // the number of the LED pin

//********************* Program SETUP *****************************

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_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
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  Serial.println("MCP2515 Library Receive Example...");

  if (SD.begin(SD_CS_PIN))
  {
    SERIAL_PORT_MONITOR.println("SD card is present & ready");
    sprintf(filename, "can_%.03d.csv", i);  //initialise filename
    
    myFile = SD.open(filename, FILE_WRITE);
    if (myFile) // it opened OK
    {
      myFile.println("Time,Pression,Temperature,co2_hydrogen,humidity"); //add header to file
      myFile.close();
      SERIAL_PORT_MONITOR.println("File created!");
    }
    else
      SERIAL_PORT_MONITOR.println("Error opening file");
  }
  else
  {
    SERIAL_PORT_MONITOR.println("SD card missing or failure");
    while (1); //wait here forever
  }
}

//********************* Fonction ecrire dans Excel ***********************

void writeToFile(float press_pascal, float temp_degC, float co2_true, float humi_pourcent)
{
  myFile = SD.open(filename, FILE_WRITE);
  if (myFile) // it opened OK
  {
    myFile.print(String(minute()));
    myFile.print(":");
    myFile.print(String(second()));
    myFile.print(";");
    myFile.print(String(press_pascal, 2));
    myFile.print(";");
    myFile.print(String(temp_degC, 2));
    myFile.print(";");
    myFile.print(String(co2_true, 2));
    myFile.print(";");
    myFile.println(String(humi_pourcent, 2));
    myFile.close();
  }
  else
    SERIAL_PORT_MONITOR.println("Error opening file");
}

//********************* Program LOOP ***************************

void loop()
{

  if (digitalRead(buttonPin)== HIGH) 
    {
    digitalWrite(ledPin, HIGH);  // turn LED on
    
  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();

    Serial.println("_____Pression_Kpa_____");
    uint16_t press_raw;
    memcpy(&press_raw, &rxBuf[0], 2); //buf[0] is the first byte in buf, 2 because you want 2 bytes
    float press_pascal = ((press_raw * 0.0078125) - 250);
    Serial.println(press_pascal, 2);  // value to copy on excel

    Serial.println("_____Temperature_____");
    uint16_t temp_raw;
    memcpy(&temp_raw, &rxBuf[2], 2); //buf[2] is the third byte in buf, 2 because you want 2 bytes
    float temp_degC = (((temp_raw * 0.03125)-273)-3) ;
    Serial.println(temp_degC, 2);

    Serial.println("_____CO2_Hydrogen_____");
    uint16_t co2_raw;
    memcpy(&co2_raw, &rxBuf[4], 2); //buf[4] is the fifth byte in buf, 2 because you want 2 bytes
    float co2_true = ((co2_raw * 1) - 0);
    Serial.println(co2_true, 2);

    Serial.println("_____Humidity_%_____");
    uint16_t humi_raw;
    memcpy(&humi_raw, &rxBuf[6], 2); //buf[6] is the six byte in buf, 1 because you want 1 bytes
    float humi_pourcent = ((humi_raw * 0.4) - 0);
    Serial.println(humi_pourcent, 2);

    writeToFile(press_pascal, temp_degC, co2_true, humi_pourcent);
    ++reads_recorded;
  }
}
  else 
      {
         digitalWrite(ledPin, LOW); // turn LED off
         Serial.println("off");
      }
      
//********************* Creation new files excel ***********************
  
  //create new filenames for every 1800 lines written to file
  if(reads_recorded == 1800) {  //reset counter
    reads_recorded = 0;

    //increment file counter
    ++i;
    
    //update finename
    sprintf(filename, "can_%.03d.csv", i);

    myFile = SD.open(filename, FILE_WRITE);
    if (myFile) // it opened OK
    {
      //add header to new file
      myFile.println("  Time,  Pression  ,  Temperature  ,  co2_hydrogen  ,humidity");
      myFile.close();
      SERIAL_PORT_MONITOR.println("New File created!");
    }
    else
      SERIAL_PORT_MONITOR.println("Error opening file");
  }
} 

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