I have tried for hours to figure out how I can speed limit reading specific messages from a CAN bus data stream. ![]()
I can read the messages I am after; they come at a rate for 4 Hz and Serial.print() these in the monitor.
However, I need to pass the messages on to another system and want to limit the flow of information.
I can limit querying the bus to any time I want (here 10 seconds), but, I always end up getting the same message Id (301), and not the other five Ids I am after.
I thought about state machines, then a "do until" would be nice, but this does not translate to C. E.g. loop until id = 301.
So the question is: How can read the bus to get all IDs {301,302,303,304,30,40}, then wait some time, say 10 sec, then do it again.
Actually more precise, the IDs come in succession, but I want to read ID 301, then convert, send it off, then move to the next ID (302)... 303, etc. then wait 10 sec, and do it again.
Hope this makes sense.
void loop() {
every ten seconds, do {
read ID 301
convert
send
read 302
...
}
}
The problem seems to be the 10 second timer; as it is written it read one ID, waits 10 sec and then reads 301 again, but not the others.
Here the code dummied up that reads 301 only.:
#include <Arduino.h>
#include <mcp_can.h>
#include <SPI.h>
const unsigned long BAUD_RATE_HW = 115200; // baud rate for hardware serial port
const unsigned long CAN_READ_INTERVAL = 10000; // [ms]
const byte PIN_CAN_SPI_CS = 9; // CS (Chip Select) pin
unsigned long receiveTime = 0;
unsigned char dataLength = 0;
unsigned char receiveBuffer[8];
long unsigned int packetId;
MCP_CAN CAN(PIN_CAN_SPI_CS); // Construct a MCP_CAN Object and set Chip Select to 10.
// Prototypes
void readCAN();
void operatingStatus();
void batteryCurrent();
void getCellVoltages();
void setup() {
Serial.begin(BAUD_RATE_HW); // start hardware serial port with 9600 bps
while (CAN_OK != CAN.begin(CAN_250KBPS,MCP_8MHz)) { // init can bus : baudrate = 250K
Serial.println(F("CAN BUS Module: failed to initialise; retrying..."));
delay(500);
}
}
void loop() {
static unsigned long lastCanRead = 0;
unsigned long timeStamp = millis(); // memorise current time
if (timeStamp - lastCanRead > CAN_READ_INTERVAL) {
lastCanRead = timeStamp;
Serial.println(F("readCAN"));
readCAN();
}
}
void readCAN() {
if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming
receiveTime = millis();
CAN.readMsgBuf(&dataLength, receiveBuffer); // read data, len: data length, buf: data buf
packetId = CAN.getCanId();
switch (packetId) {
case 301: // cell voltages 1 to 4
case 302: // cell voltages 5 to 8
case 311: // cell voltages 9 to 12
case 312: // cell voltages 13 to 16
getCellVoltages();
break;
case 30: // Broadcast Status
operatingStatus();
break;
case 40: // Battery Current
batteryCurrent();
break;
default: // anything else
break;
}
}
}
void getCellVoltages() {
Serial.println("getCellVoltages");
}
void operatingStatus() {
Serial.println("operatingStatus");
}
void batteryCurrent() {
Serial.println("batteryCurrent");
}