@mdancer @YellowDog Thanks for your posts and ideas. Its good to find others withing this the CAN485 and I will check this forum more frequently.
I did figure out a way to include multitasking in a CAN485 designed to be a receive CAN messages while also doing other tasks. I have extracted the code below from a sketch that I’ve tested extensively and found to be reliable. I have taken out most all of the code that does not relate to receiving CAN messages. There are lots of ways to improve on what I have done but, for me, its a workable start…
#include <ASTCanLib.h>
#include <at90can_drv.h>
#include <can_compiler.h>
#include <can_drv.h>
#include <can_lib.h>
#include <config.h>
#include <Wire.h>
// Time values to multitask between polling local switches and CAN controller
const long CAN_REFRESH_TIME = 50;
const long CAN_CMD_TIMEOUT = 50;
long CAN_Cmd_Timeout;
// CAN message constants
#define MESSAGE_ID 0 // Message ID
#define MESSAGE_PROTOCOL 1 // CAN protocol (0: CAN 2.0A, 1: CAN 2.0B)
#define MESSAGE_LENGTH 8 // Data length: 8 bytes
#define MESSAGE_RTR 0 // rtr bit
// CAN message object
st_cmd_t Msg;
// Buffer for CAN data
uint8_t Buffer[8] = {};
void setup() {
canInit(500000); // Initialise CAN port. must be before Serial.begin
Serial.begin(115200); // start serial port
Msg.pt_data = &Buffer[0]; // reference message data to buffer
// Initialise CAN packet.
// All of these will be overwritten by a received packet
Msg.ctrl.ide = MESSAGE_PROTOCOL; // Set CAN protocol (0: CAN 2.0A, 1: CAN 2.0B)
Msg.id.ext = MESSAGE_ID; // Set message ID
Msg.dlc = MESSAGE_LENGTH; // Data length: 8 bytes
Msg.ctrl.rtr = MESSAGE_RTR; // Set rtr bit
// Clear the message buffer
clearBuffer(&Buffer[0]);
// Send receive command to the CAN port controller
Msg.cmd = CMD_RX_DATA;
while (can_cmd(&Msg) != CAN_CMD_ACCEPTED);
Serial.println(“System Follower Node #2”);
}
void loop() {
// otherFunctions.poll();
char cmd = checkForCanMsg();
if (cmd != ‘0’) executeCmd(cmd);
}
// setCanRxMode ()
// Configure the CAN peripheral to be in receive mode
void setCanRxMode() {
// Send receive command to the CAN port controller
Msg.cmd = CMD_RX_DATA;
CAN_Cmd_Timeout = millis() + CAN_CMD_TIMEOUT;
U8 canCmdStatus = 0x08; // != to refused or accepted
while ( canCmdStatus != CAN_CMD_ACCEPTED) {
canCmdStatus = can_cmd(&Msg);
if (millis() > CAN_Cmd_Timeout) {
if ( canCmdStatus == CAN_CMD_REFUSED) {
Serial.println(“Error: CAN command refused. Reinitializing CAN peripheral…”);
canInit(500000); // reinitialize the CAN peripheral
}
else {
Serial.println(“Error: CAN command not accepted - timeout”);
}
break;
}
}
}
char checkForCanMsg() {
char cmd = ‘0’;
U8 canStatus = can_get_status(&Msg);
if (canStatus == CAN_STATUS_NOT_COMPLETED) {
// do nothing
}
else if ( canStatus == CAN_STATUS_ERROR ) {
Serial.println(" Error in configuration or in the CAN communication");
setCanRxMode();
}
else {
// Data is now available in the message object
// Print received data to the terminal
serialPrintData(&Msg);
// extract the command
cmd = Msg.pt_data[0];
// Setup for the next receive
// Clear the message buffer
clearBuffer(&Buffer[0]); // clear the rx buffer
// Msg.cmd = CMD_NONE; // clear the CAN status
// can_cmd(&Msg);
// Setup CAN peripheral to receive the next message
setCanRxMode();
}
return (cmd);
}
void serialPrintData(st_cmd_t *msg) {
for (int i = 0; i < msg->dlc; i++) {
Serial.print(char(msg->pt_data*));*
}
Serial.print(“\r\n”);
}
void executeCmd(char cmd) {
switch (cmd) {
case ‘1’:
cabHeatOn((void*)‘R’); // Cabin heating on
break;
case ‘2’:
cabHeatOff((void*)‘R’); // Cabin heating off
break;
case ‘3’:
dhwOn((void*)‘R’); // DHW heating on
break;
case ‘4’:
dhwOff((void*)‘R’); // DHW heating off
break;
default:
Serial.print("Could not understand the command: ");
Serial.println( cmd);
}
}