I have written a library to interpret CAN messages, and I'm struggling with one small part of its intended functionality. There are a few hundred possible variables that could be sent on this network, with a few packed arbitrarily into each 8-byte message, with several dozen message IDs. The sending system has a configurable base ID, with subsequent messages offsetting the ID by increments of 1. For example, if the system is set up with a base ID of 1512, then var0 - var3 might live at the base ID of 1512, var4 to var7 at ID 1513, etc.
I would like a library user to be able to define the base ID in an .ino file without having to modify the library files, if possible. I thought that a simple way to do it would be to declare a 'const uint32_t' before setup() and use it as an argument to a library function call as the switch case variable, something like this:
/*~~~~~ 'can_test.ino' ~~~~*/
#include <CAN.h> //could be any of many CAN libraries, as long as it creates accurate msg.id and msg.buf[]
#include <myCANLibrary.h>
CAN Can0; //for communications
myCANLibrary myCAN; //for unpacking and storing data from Can0
CAN_message_t msg; //from generic 'CAN.h' or similar library
myCAN_message_t myCANMsg; //from my own library, used for unpacking the CAN messages, e.g. holds var0, var1, etc
const uint32_t baseID = 1512;
void setup() {
// start the CAN bus, etc.
}
void loop() {
if(Can0.messageAvailable()) { //unpack the data once a new message is available, into msg.id and msg.buf[]
myCAN.getData(baseID, msg.id, msg.buf, myCANMsg);
Serial.print("Any variable in myCANMsg: "); Serial.println(myCanMsg.someVariable);
}
}
/*~~~~ end of 'can_test.ino' ~~~~*/
/*~~~~ 'myCANLibrary.h' ~~~~*/
#ifndef myCANLibrary_h
#define myCANLibrary_h
#include "Arduino.h"
typedef struct myCAN_message_t {
float someVariable = 0;
uint16_t someOtherVariable = 0;
} myCAN_message_t;
class myCANLibrary {
public:
myCANLibrary();
void getData(const uint32_t baseID, uint32_t id, const uint8_t data[8], myCAN_message_t &msg);
}
#endif
/*~~~~ end of 'myCANLibrary.h' ~~~~*/
/*~~~~ 'myCANLibrary.cpp' ~~~~*/
#include <myCANLibrary.h>
#include "Arduino.h"
myCANLibrary::myCANLibrary() {}
void myCANLibrary::getData(const uint32_t baseID, uint32_t id, const uint8_t data[8], myCAN_message_t &msg) {
switch(id) {
case baseID:
msg.someVariable = ((data[0] << 8) | data[1]) / (float)1000;
//some other variables
break;
case baseID + 1:
msg.someOtherVariable = (data[0] << 8) | data[1];
break;
//many other cases, as 'baseID + n'
}
}
/*~~~~ end of 'myCANLibrary.h' ~~~~*/
I get a long string of the following errors for each case in the switch:
C:\Users\Mike\Documents\Arduino\libraries\myCANLibrary\myCANLibrary.cpp: In member function 'void myCANLibrary::getData(uint32_t, uint32_t, const uint8_t*, myCAN_message_t&)':
C:\Users\Mike\Documents\Arduino\libraries\myCANLibrary\myCANLibrary.cpp:8:8: error: 'baseID' is not a constant expression
case baseID:
^
C:\Users\Mike\Documents\Arduino\libraries\myCANLibrary\myCANLibrary.cpp:12:17: error: 'baseID' is not a constant expression
case baseID + 1:
^
So... what am I doing wrong? Or how can I set a baseID in the .ino file for use in the library function? I did quite a bit of searching, tried several things, but the above method was the closest to the non-library version of this, which worked (the switch was in a function in the .ino file, I believe I used 'const uint32_t' for the baseID).
