Hi everyone, so I'm currently trying to run some gauges for my car using an Arduino Due. I have a 240x280 ST7789 IPS display that I want to use to display some error messages that I'm getting over CAN bus (if there are errors). I have some code that will display the errors, but there are a couple problems. It will refresh the display every time there is a new message, regardless of if the error status has changed. It also slows my Serial Printing down considerably, because the display function is integrated in the callback. I don't need the error decoding/displaying function to be running super fast, I just need it to display error messages around the time that they are sent over the CAN bus. Does anyone have any ideas on how to update the display only when needed? I'm pretty stumped. Thank you!
#include <Arduino.h>
#include <due_can.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#define TFT_CS 53
#define TFT_RST 52
#define TFT_DC 50
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
const uint32_t error_canID = 0x023;
const uint32_t cvtr_canID = 0x6B0;
// DTC fault descriptions
const char* DTC1_faults[] = {
"DISCHARGE LIMIT ENFORCEMENT FAULT", // 0x0001
"CHARGER SAFETY RELAY FAULT", // 0x0002
"INTERNAL HARDWARE FAULT", // 0x0004
"INTERNAL HEATSINK THERMISTOR FAULT", // 0x0008
"INTERNAL SOFTWARE FAULT", // 0x0010
"HIGHEST CELL VOLTAGE TOO HIGH FAULT", // 0x0020
"LOWEST CELL VOLTAGE TOO LOW FAULT", // 0x0040
"PACK TOO HOT FAULT" // 0x0080
};
const char* DTC2_faults[] = {
"INTERNAL COMMUNICATION FAULT", // 0x0001
"CELL BALANCING STUCK OFF FAULT", // 0x0002
"WEAK CELL FAULT", // 0x0004
"LOW CELL VOLTAGE FAULT", // 0x0008
"OPEN WIRING FAULT", // 0x0010
"CURRENT SENSOR FAULT", // 0x0020
"HIGHEST CELL VOLTAGE OVER 5V FAULT", // 0x0040
"CELL ASIC FAULT", // 0x0080
"WEAK PACK FAULT", // 0x0100
"FAN MONITOR FAULT", // 0x0200
"THERMISTOR FAULT", // 0x0400
"EXTERNAL COMMUNICATION FAULT", // 0x0800
"REDUNDANT POWER SUPPLY FAULT", // 0x1000
"HIGH VOLTAGE ISOLATION FAULT", // 0x2000
"INPUT POWER SUPPLY FAULT", // 0x4000
"CHARGE LIMIT ENFORCEMENT FAULT" // 0x8000
};
// Function declaration
void canCallbackERROR(CAN_FRAME *frame);
void canCallbackCVTR(CAN_FRAME *frame);
void setup() {
Serial.begin(115200);
// Initialize CAN0 with a baud rate of 250Kbps
Can0.begin(CAN_BPS_250K);
// Set a filter to receive frames with ID error_canID
Can0.setRXFilter(0, error_canID, 0x7FF, false);
// Set up a callback function for mailbox 0
Can0.setCallback(0, canCallbackERROR);
// Set a filter to receive frames with ID cvtr_canID
Can0.setRXFilter(1, cvtr_canID, 0x7FF, false);
// Set up a callback function for mailbox 1
Can0.setCallback(1, canCallbackCVTR);
tft.init(240, 280);
tft.fillScreen(ST77XX_BLACK);
}
void loop() {
// The loop is empty because we're using the callback to handle CAN messages
}
// Callback function for processing error CAN frames (0x023)
void canCallbackERROR(CAN_FRAME *frame) {
bool errorFound = false;
if (frame->length >= 8) {
// Access the data bytes
uint16_t DTC1 = frame->data.byte[1] << 8 | frame->data.byte[0];
uint16_t DTC2 = frame->data.byte[3] << 8 | frame->data.byte[2];
// Print DTC1 faults
for (int i = 0; i < 8; ++i) {
if (DTC1 & (1 << i)) {
Serial.print(DTC1_faults[i]);
Serial.print(" ");
errorFound = true;
}
}
// Print DTC2 faults
for (int i = 0; i < 16; ++i) {
if (DTC2 & (1 << i)) {
Serial.print(DTC2_faults[i] );
Serial.print(" ");
errorFound = true;
}
}
Serial.println();
}
if (errorFound) {
tft.fillScreen(ST77XX_BLACK); // Clear the screen
tft.setCursor(20, 120); // Set cursor position
tft.setTextColor(ST77XX_WHITE);
tft.setTextWrap(true);
tft.setTextSize(2);
tft.println("Fault detected");
}
}
void canCallbackCVTR(CAN_FRAME *frame) {
if (frame->length >= 8) {
uint16_t current = frame->data.byte[1] <<8 | frame->data.byte[0];
uint16_t voltage = frame->data.byte[3] << 8 | frame->data.byte[2];
uint16_t temperature = frame->data.byte[5] << 8 | frame->data.byte[4];
uint16_t resistance = frame->data.byte[7] << 8 | frame->data.byte[6];
Serial.print("Current: ");
Serial.print(current);
Serial.print(" A, ");
Serial.println();
Serial.print("Voltage: ");
Serial.print(voltage);
Serial.print(" V, ");
Serial.println();
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" C, ");
Serial.println();
Serial.print("Highest Resistance: ");
Serial.print(resistance);
Serial.print(" mOhm, ");
Serial.println();
}
}