Help coding question POST#12

Hello i hope you'r fine :slight_smile:

I am a beginner in programming

I have a question , i want to know if its possible in the " void loop() { " if i can execute one first code like 1 min to verify everithings fine and after that start my principal code and of course make it all loop back when you press reset or when you turn it off/on

if you need to see:

in first i need to execute this code :

void loop()
{

  unsigned char len = 0;
  unsigned char buf[8];
  
  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...");

And just after a tempo like 1 min execute this for all time necessary :

if (CAN_MSGAVAIL == CAN.checkReceive()) {    // check if data coming
    CAN.readMsgBuf(&len, buf);                 // read data,  len: data length, buf: data buf

    unsigned long canId = CAN.getCanId();

    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);

    if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);  // turn LED on
    writeToFile(press_pascal, temp_degC, co2_true, humi_pourcent);
    ++reads_recorded;}
    else {
    digitalWrite(ledPin, LOW); // turn LED off
  }
  }

I hope you can help me to finish my code :confused:
Thanks you

If you have code that is executes only once, even if it is for a period of time, then why not put it in setup() or a function called from setup() ?

It's mean i can simply add the first part of code ( on my post ) in the setup and keep the other code in the loop and everithings works ?

As long as you write it correctly then yes

As currently written it does not loop and in order to

you will need to change it to incorporate a loop for 1 minute. It would also be preferable to put it in its own function and call it from setup()

As an alternative you could put the code in loop() and control whether it or the main code runs using a boolean variable. When true run the initialisation code, when false run the main code. Have the initialisation code change the boolean to false when it has finished doing what you need it to. I would, however, still put the initialisation code in a function with an appropriate name

Ok i understand your logical , but how do you code a function in arduino?

its like i write ?:

Void FirstCode ()
{
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...");
}

and i call it idk how in the setup ?

Hi @remay66,

first a little bit of theory ...

In general - as @UKHeliBob already posted - Arduino code is performed in three parts:

  • initialization
  • setup()
  • loop()

When the controller is powered up (or reset) all functions written or called in setup() will be performed. After this the code usually enters loop() and repeats the functionality of loop until (theoretically) "infinity" ...

But be aware that you as the developer may stop the code in setup() so it never may reach loop() or you can influence the flow also in loop() so that the controller cannot perform all functions or at least not in due time. In certain cases this is on purpose - in others not and then it is usually a result of bad design (e.g. by making extensive use of delay() instead of using the controller time to control tasks).

Regarding your request: You wrote

... execute one first code like 1 min to verify everithings fine and after that start my principal code and of course make it all loop back when you press reset or when you turn it off/on

This can be done by checking the start conditions in setup() as this part will be performed first (after initialization) with every restart.

However you have to decide what do you want the controller to do when the conditions are not "fine". Shall it repeat the check or just send a serial message and stop?

Here is a small demo code:

unsigned long StartCheck;
boolean EverythingIsFine = false;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  StartCheck = millis();
  while (millis()-StartCheck < 2000) {
    EverythingIsFine = IsEverythingFine();
  }
  if (!EverythingIsFine) {
    Serial.println("Conditions not met ...");
    Serial.println("Controller stopped");
    while(true);
  }
  Serial.println("Conditions are met!");
  Serial.println("Goto loop()");
}

void loop() {
  // put your main code here, to run repeatedly:
}

boolean IsEverythingFine(){
   return true;  // Change true to false or vice versa to test the result
}

1 Like

Write your function outside everything then call it wherever you want. Exactly the same as you do with global variables. The syntax is in the arduino reference.

You may benefit from developing a flow diagram in plain words of what you want to achieve.

1 Like

The same way that you call pinMode(), digitalRead(), CANreadMsgBuffer(), sprintf(), Serial.print() etc

Take a look into this tutorial:

Arduino Programming Course

It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.

best regards Stefan

1 Like

Ok, I think it works , i use your while millis , I understand your answers!

But I have bug errors with the library
'mcp2515_can' does not name a type
I think with #include <mcp_can.h> and #include "mcp2515_can.h" because I need it but it's like it can't not work together, i've been working on it for a while now but can't find a solution, idk if anyone can help me :confused:

Here is my final code (a little longer but I structured it well):

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

//*********************CAN Sheild declarations*********************
#define CAN_2515

#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat:
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN  = BCM8;
const int CAN_INT_PIN = BCM25;
#else

// For Arduino MCP2515 Hat:
const int SPI_CS_PIN = 53;
const int CAN_INT_PIN = 2;
#endif

#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif

#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif       
       

//*********************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

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 SETUP ***********************

void setup()
{
  
#define CAN0_INT 2                              
MCP_CAN CAN0(53);                               


  // 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];
char msgString[128];    // Serial Output String Buffer

  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  Serial.begin(115200);  
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
    pinMode(CAN0_INT, INPUT);                           
    Serial.println("MCP2515 Library Loopback Example...");

  unsigned long initial_T = millis();
  while(millis()-initial_T< 60000UL)  //loops for about 1min
  { 

    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
  }

  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...");

  }
 }
}

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

void loop()
{

  unsigned char len = 0;
  unsigned char buf[8];

  if (CAN_MSGAVAIL == CAN.checkReceive()) {    // check if data coming
    CAN.readMsgBuf(&len, buf);                 // read data,  len: data length, buf: data buf

    unsigned long canId = CAN.getCanId();

    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);

    if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);  // turn LED on
    writeToFile(press_pascal, temp_degC, co2_true, humi_pourcent);
    ++reads_recorded;}
    else {
    digitalWrite(ledPin, LOW); // turn LED 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");
  }

}

Assuming that you do not really require all the '"#if defined()" issues I removed them, moved one #include and the declaration for CAN0 from setup() to initialization ...

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

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

// For Arduino MCP2515 Hat:
const int SPI_CS_PIN = 53;
const int CAN_INT_PIN = 2;
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin

// For CAN0       
#define CAN0_INT 2                              
MCP_CAN CAN0(53); 

//*********************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

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 SETUP ***********************

void setup()
{
  // 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];
char msgString[128];    // Serial Output String Buffer

  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  Serial.begin(115200);  
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
    pinMode(CAN0_INT, INPUT);                           
    Serial.println("MCP2515 Library Loopback Example...");

  unsigned long initial_T = millis();
  while(millis()-initial_T< 60000UL)  //loops for about 1min
  { 

    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
  }

  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...");

  }
 }
}

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

void loop()
{

  unsigned char len = 0;
  unsigned char buf[8];

  if (CAN_MSGAVAIL == CAN.checkReceive()) {    // check if data coming
    CAN.readMsgBuf(&len, buf);                 // read data,  len: data length, buf: data buf

    unsigned long canId = CAN.getCanId();

    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);

    if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);  // turn LED on
    writeToFile(press_pascal, temp_degC, co2_true, humi_pourcent);
    ++reads_recorded;}
    else {
    digitalWrite(ledPin, LOW); // turn LED 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");
  }

}

I have not tested/compiled it, just give it a try ...

P.S.: You use the same SPI_CS_PIN for both CAN() and CAN0() ... ?!

This is what I found in an example by Seeed which seems to collide with your SD_CS_PIN = 9.


// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
  const int SPI_CS_PIN = 9;
  const int CAN_INT_PIN = 2;

If you use the TF-Card reader from this shield (Version 2.0) it looks as if the default SD_CS_PIN should be Pin 4 (IO4) if I am not wrong:

image

1 Like

I try it but same error :
CAN_programe:12:1: error: 'mcp2515_can' does not name a type mcp2515_can CAN(SPI_CS_PIN); // Set CS pin

Yeah i use the same SPI_CS_PIN for both CAN() and CAN0()

Because on my project i use a arduino mega with a sparkun CANBUS connect to a sensor. And to resume my main code (1) in Seed_Arduino_CAN-master works only if i lauch before this code call MCP_loopback.ino (0) from library MCP_CAN_lib_master and i dont find why...

For my project I need to implement a single code in the board and no longer use a computer (only +12v power supply of arduino)

So I wanted to put the code 0 in the setup and the main code in the main 1 as we talk about just above :confused:

the two code works great independently :
0

#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(53);                               // 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...");

  }
}

1

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

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

const int SPI_CS_PIN = 53;
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


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 SETUP ***********************

void setup() {
  
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  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
  }
}

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

void loop() {
  unsigned char len = 0;
  unsigned char buf[8];

  if (CAN_MSGAVAIL == CAN.checkReceive()) {    // check if data coming
    CAN.readMsgBuf(&len, buf);                 // read data,  len: data length, buf: data buf

    unsigned long canId = CAN.getCanId();

    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);

    if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);  // turn LED on
    writeToFile(press_pascal, temp_degC, co2_true, humi_pourcent);
    ++reads_recorded;}
    else {
    digitalWrite(ledPin, LOW); // turn LED 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");
  }

}

it's very frustrating because everything is working fine but divided into two programs and I can't figure out how to do it if anyone can help me :slight_smile:

Check the libraries for the following lines:

#ifndef _MCP2515_H_
#define _MCP2515_H_

I reckon you will find the same lines in both libs to prevent that each lib is included several times ...

You can change one of the libs or just put the following #undef before you call the second lib:

#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
#include <mcp_can.h>
#undef _MCP2515_H_       
#include "mcp2515_can.h"

However there is a certain danger that the two libs may collide ...

1 Like

Yeah true when i compile with modification i have :

Several libraries found for "mcp_can.h"
Used : C:\Users\RORE169\Documents\Arduino\libraries\MCP_CAN_lib-master
Not used : C:\Users\RORE169\Documents\Arduino\libraries\Seeed_Arduino_CAN-master
output status 1
Compilation error for the Arduino Mega or Mega 2560 board

So now you know the reason for the error "'mcp2515_can' does not name a type": If one or the other lib is included first it restricts the inclusion of the second.

As we are chasing followup problems coming from your "workaround" you should focus on your initial problem instead:

Because on my project i use a arduino mega with a sparkun CANBUS connect to a sensor. And to resume my main code (1) in Seed_Arduino_CAN-master works only if i lauch before this code call MCP_loopback.ino (0) from library MCP_CAN_lib_master and i dont find why...

There must be an issue for this and that has to be solved ...

P.S.: On a first glance it looks as if at least this line is missing in the second sketch in setup()

  pinMode(CAN_INT_PIN , INPUT);                           // Configuring pin for /INT input
1 Like

Ok fine , Thank you for helping me to understand how to find a solution

Tomorrow I will find out why the program 0 allows me to start my project

Because to explain with a spy i can see on my Sparkun bus can my signal on pin In/Out.

I have MISO MOSI CLOCK ShipSelect INT and when i use my program i have just MOSI with signal and the rest with one pick of rising edge nothings works on the arduino screen.

And when i use the program Loopback its like the card wakes up all signal are ok and works on my oscillo arduino screen.

So i need to find why ...

I had a deeper look into the Seed_Arduino_CAN library. Actually it also includes a file mcp_can.h which is used during the compilation. The pinmode() of the CAN_INT_PIN does not have to be set in the Seeed-Studio examples.

If you have not done it you might try the Seeed examples:

https://github.com/Seeed-Studio/Seeed_Arduino_CAN/tree/master/examples

This one may be the best to start with:

https://github.com/Seeed-Studio/Seeed_Arduino_CAN/blob/master/examples/send/send.ino

Good luck ...

1 Like

Hello again!

The whole project works but there is something I don't understand.

I made a box to store the arduino board and the Sparkfun CANbus with my led switches etc. in front.

The +12v supplies my arduino board as well as my sensor. I have a 230/12v transformer that supplies my two components at the same time.

But when I connect the current nothing happens, I have to manually disconnect and reconnect the +12v on my Arduino board for the code to work ... ( I could check it because the switch lights the registration LED after this maniupulation )

Do you think I have to add an ON/OFF switch to control the power supply of my Arduino board, otherwise I don't understand ?

Great that your project is working now.

As other members might look up this thread because they have similar problems, it would be helpful if you could post the solution with some explanations ...

Regarding your last request it would be of assistance if you would elaborate on your hardware setup (e.g. a sketch how the components are wired and what types you use).

There are highly experienced members in the forum but they believe in information based analysis rather than professional guesswork :wink:

1 Like

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