Hey Guys,
so im pretty new into working with CAN and i run into some issue.
I have a code that reads CAN messages out of a CAN network and should then do X when receiving X CAN ID. The issue that i know have is that on higher BUS loads i have to send the CAN messages multiple times for the Arduino to recognize. Its completly random sometimes it works on the first send and sometimes i have to spam 20 times before it gets the message.
I already double checked with an second code that just reads CAN messages and my sender node is working flawless.
that the code:
#include <SPI.h>
#include <mcp_can.h>
#include <Arduino.h>
#include <Wire.h>
#include "DisplayManager.h"
#define IDLE_STATE 0
#define PRE_CHARGE_STATE 1
#define FULL_CHARGE_STATE 2
#define OFF_STATE 3
#define IDLE_CMD_ID 0x01
#define CONNECT_CMD_ID 0x02
#define DISCONNECT_CMD_ID 0x03
#define OFF_CMD_ID 0x04
const int preChargeOutputPin = 6;
const int fullChargeOutputPin = 7;
const int idleOutputPin = 5;
int currentState = OFF_STATE;
unsigned long preChargeStartTime = 0;
DisplayManager displayManager;
MCP_CAN CAN(10); // CS Pin is 10
void setup() {
Serial.begin(9600);
pinMode(preChargeOutputPin, OUTPUT);
pinMode(fullChargeOutputPin, OUTPUT);
pinMode(idleOutputPin, OUTPUT);
digitalWrite(preChargeOutputPin, LOW);
digitalWrite(fullChargeOutputPin, LOW);
digitalWrite(idleOutputPin, LOW);
// Initialize the MCP2515 CAN controller
if (CAN.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) {
Serial.println("CAN-Bus initialized");
CAN.setMode(MCP_NORMAL);
} else {
Serial.println("CAN-Bus initialization error");
while (1);
}
// Initialize the OLED Display
displayManager.begin();
}
void loop() {
float voltageA0 = analogRead(A0) * (60.0 / 1023.0);
float voltageA1 = analogRead(A1) * (60.0 / 1023.0);
// Debugging-Nachrichten für die Spannungen hinzufügen
//Serial.print("Voltage A0: ");
//Serial.println(voltageA0, 2); // Anzeige auf zwei Dezimalstellen genau
//Serial.print("Voltage A1: ");
//Serial.println(voltageA1, 2); // Anzeige auf zwei Dezimalstellen genau
if (currentState == IDLE_STATE) {
displayManager.showStateAndVoltage("Idle", voltageA0, voltageA1);
} else if (currentState == PRE_CHARGE_STATE) {
displayManager.showStateAndVoltage("Pre-charge", voltageA0, voltageA1);
if (abs(voltageA0 - voltageA1) <= 200.0 && millis() - preChargeStartTime >= 1000) {
currentState = FULL_CHARGE_STATE;
digitalWrite(fullChargeOutputPin, HIGH);
delay(1500);
digitalWrite(preChargeOutputPin, LOW);
Serial.println("State: Full-charge");
} else {
// Debugging-Nachricht, wenn die Bedingung nicht erfüllt ist
Serial.println("Pre-charge condition not met");
Serial.print("Voltage A0: ");
Serial.println(voltageA0);
Serial.print("Voltage A1: ");
Serial.println(voltageA1);
}
} else if (currentState == FULL_CHARGE_STATE) {
displayManager.showStateAndVoltage("Full-charge", voltageA0, voltageA1);
} else if (currentState == OFF_STATE) {
displayManager.showStateAndVoltage("Off", voltageA0, voltageA1);
}
// Check for CAN messages
if (CAN_MSGAVAIL == CAN.checkReceive()) {
unsigned char len = 0;
unsigned char buf[8];
unsigned long canId = 0;
CAN.readMsgBuf(&canId, &len, buf);
if (canId == IDLE_CMD_ID) {
handleCommand("idle");
} else if (canId == CONNECT_CMD_ID) {
if (currentState == IDLE_STATE && voltageA0 >= 30.0 && voltageA1 >= 30.0) {
handleCommand("connect");
}
} else if (canId == DISCONNECT_CMD_ID) {
handleCommand("disconnect");
} else if (canId == OFF_CMD_ID) {
handleCommand("off");
}
}
// Check for serial messages
if (Serial.available() > 0) {
String command = Serial.readString();
command.trim();
handleCommand(command);
}
}
void handleCommand(const String& command) {
float voltageA0 = analogRead(A0) * (60.0 / 1023.0);
float voltageA1 = analogRead(A1) * (60.0 / 1023.0);
if (command == "idle") {
currentState = IDLE_STATE;
digitalWrite(idleOutputPin, HIGH);
Serial.println("State: Idle");
} else if (command == "connect" && currentState == IDLE_STATE && voltageA0 >= 30.0 && voltageA1 >= 30.0) {
currentState = PRE_CHARGE_STATE;
digitalWrite(preChargeOutputPin, HIGH);
preChargeStartTime = millis();
Serial.println("State: Pre-charge");
} else if (command == "disconnect") {
currentState = IDLE_STATE;
digitalWrite(preChargeOutputPin, LOW);
digitalWrite(fullChargeOutputPin, LOW);
Serial.println("State: Idle");
} else if (command == "off") {
currentState = OFF_STATE;
digitalWrite(idleOutputPin, LOW);
digitalWrite(preChargeOutputPin, LOW);
digitalWrite(fullChargeOutputPin, LOW);
Serial.println("State: Off");
}
// Update Display State
if (currentState == IDLE_STATE) {
displayManager.showStateAndVoltage("Idle", voltageA0, voltageA1);
} else if (currentState == PRE_CHARGE_STATE) {
displayManager.showStateAndVoltage("Pre-charge", voltageA0, voltageA1);
} else if (currentState == FULL_CHARGE_STATE) {
displayManager.showStateAndVoltage("Full-charge", voltageA0, voltageA1);
} else if (currentState == OFF_STATE) {
displayManager.showStateAndVoltage("Off", voltageA0, voltageA1);
}
}