Hi all,
I’m attempting to use 2 CAN-BUS Shield V2.0 with Arduino Uno R3 “Systems” as a test bench for a power supply I’m working with. These systems are meant to mimic a real controller that will send out different CAN commands to the bus (System 1), and a Power Supply (The real Power Supply will be referred to as “PS”. PS will consist of multiple power supplies that are strung together) that will respond to requests (System 2).
TLDR: Is there a way to receive all messages at this rate and process them?
System 1 is going to send out an extended ID message with last 3 digits as 0x202. System 1 will respond to this message (and only messages with these last 3 digits, otherwise it will ignore the message) by sending 30 messages with extended ID back on the bus. System 1 is meant to read these messages so that there are no errors on System 1. I’m also looking into the storage/processing of these 39 messages each with extended ID and 8 data bytes, but I’m checking to see if this is possible first. I believe the real System 2 (PS) sends each of these 39 messages at a rate of about 2ms/message. This was seen with a down-sized version of PS that only sends out 12 messages, but the concept shall remain the same for the real PS.
System 2 currently sends out messages at a rate of ~1-3ms. This was tracked with a data logger with only 1ms resolution. When using micros()
to time the amount of time in my loop for sending messages, I come up with 83492 = 83ms = ~2ms/msg. System 1 currently has a delay(1)
, then checks the buffer for received messages. This takes 88862 (measured by micros()
again) but I only receive 31 of the 39 messages. When I used a different method of sending messages out on System 2 that took ~4ms/msg, all 39 messages were received. I also note that when I take out some of my debugging messages in System 1’s loop for checking the message buffer, I read less messages (between 20-30 sometimes). However, if I take almost all of my debugging messages out, I receive even less messages (2-3 only, loop takes ~308 micros = 308ms).
Is there a way to receive all messages at this rate and process them?
System 1 code:
//Send data every 5s, check for messages, then wait 15s to start again
#include <SPI.h>
#define CAN_2515
// Set SPI CS Pin according to your hardware
// 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 = 10;
const int CAN_INT_PIN = 2;
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_250KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
unsigned char len = 0;
unsigned char buf[8];
int count = 1;
unsigned long time, times=0;
void loop() {
SERIAL_PORT_MONITOR.println("Starting loop");
delay(5000);
CAN.sendMsgBuf(0x00000202, 1, 8, stmp);
SERIAL_PORT_MONITOR.println("CAN BUS 202 sendMsgBuf ok!");
delay(1);
SERIAL_PORT_MONITOR.println(" checking for checkReceive()");
// time = micros();
while(CAN_MSGAVAIL == CAN.checkReceive()){
SERIAL_PORT_MONITOR.print(" MSG " + String(count) + " Available!");
CAN.readMsgBuf(&len, buf);
unsigned long canId = CAN.getCanId();
SERIAL_PORT_MONITOR.println(" Get data from ID: 0x"+String(canId, HEX));
// SERIAL_PORT_MONITOR.println(canId, HEX);
count++;
}
////This receive code is different from the above loop by only one character, "-" and receives only 38/39 messages.
// while(CAN_MSGAVAIL == CAN.checkReceive()){
// SERIAL_PORT_MONITOR.print(" MSG " + String(count) + " Available!");
// CAN.readMsgBuf(&len, buf);
// unsigned long canId = CAN.getCanId();
// SERIAL_PORT_MONITOR.println("- Get data from ID: 0x"+String(canId, HEX));
// // SERIAL_PORT_MONITOR.println(canId, HEX);
// count++;
// }
// times = micros();
// SERIAL_PORT_MONITOR.println(String(times-time));
SERIAL_PORT_MONITOR.println("Finished this iteration ");
delay(15000);
SERIAL_PORT_MONITOR.println("Done waiting 15 seconds, looping");
count = 1;
}
// END FILE
System 2 Code:
/*
sketch for PS - will await a message on CANBUS for request id, 202
Following this, will send out 39 messages, 3 from each shelf with 13 shelves.
*/
#include <SPI.h>
#define CAN_2515
// 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;
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_250KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
byte stmp[8] = {0,18,95,0,4,0,28,0};
unsigned long cid[39] = {0x11202,0x12202,0x13202,0x21202,0x22202,0x23202,0x31202,0x32202,0x33202,0x41202,0x42202,0x43202,0x51202,0x52202,0x53202,0x61202,0x62202,0x63202,0x71202,0x72202,0x73202,0x81202,0x82202,0x83202,0x91202,0x92202,0x93202,0x101202,0x102202,0x103202,0x111202,0x112202,0x113202,0x121202,0x122202,0x123202,0x131202,0x132202,0x133202};
int count = 0;
unsigned char len = 0;
unsigned char buf[8];
unsigned long tsend, tend = 0;
void loop() {
// delay(10000);
if (CAN_MSGAVAIL == CAN.checkReceive()){
CAN.readMsgBuf(&len, buf);
unsigned long canId = CAN.getCanId();
SERIAL_PORT_MONITOR.println("rec'd from canID: "+String(canId,HEX));
if ((canId&0xfff) == 0x202){ // Mask off last 3 bytes of can ID and compare to 0x202
tsend = micros();
////Current way of sending messages, takes ~2ms/msg
for(unsigned long id : cid){
CAN.sendMsgBuf(id, 1, 8, stmp);
// SERIAL_PORT_MONITOR.print("now - micros = " + String(micros() - tsend));
SERIAL_PORT_MONITOR.println("sent msg from cid: " + String(id,HEX));
}
tend = micros();
////Old way of sending messages, took ~4ms/msg
// while(count<39){
// // tsend = micros();
// CAN.sendMsgBuf(cid[count], 1, 8, stmp);
// SERIAL_PORT_MONITOR.print("now - micros = " + String(micros() - tsend));
// SERIAL_PORT_MONITOR.println(" sent msg from cid: " + String(cid[count],HEX));
// count++;
}
}
else{
SERIAL_PORT_MONITOR.println("rec'd from canID: "+String(canId,HEX)+String(canId&0xfff,HEX));
}
// SERIAL_PORT_MONITOR.println(String(tend-tsend));
count=0;
}
// count++;
}
// END FILE