Я использую Arduino Uno с экраном CAN-шины SEEED и ЖК-дисплеем 4x20 с рюкзаком Adafruit I2C. Я пытаюсь заставить Uno получать несколько разных сообщений через CAN, а затем отображать полученные от них данные на ЖК-дисплее с помощью кнопки, позволяющей конечному пользователю пролистывать, какие данные отображаются.
Мне удалось заставить настройку экрана Uno+CAN-шины работать в более простой схеме, где она просто непрерывно отображает один байт или слово сообщения CAN на ЖК-дисплее, без каких-либо «изменений экрана».
Я не могу получить моя кнопка для смены экранов, и я думаю, что это вызвано какой-то основной структурной проблемой. Я не очень хорошо разбираюсь в кодировании, большую часть времени мне удается просто модифицировать примеры, но этот проект слишком сложен для этой стратегии.
Я попробовал использовать срабатывание по прерыванию по нарастающему фронту на выводе я подключился к НО контакту моей кнопки, контакт С которой был подключен к 5В. Этот штифт (3) также вытягивается вниз на 10К. Я проверил, что на контакте 3 напряжение 0 В, когда кнопка не нажата, и 5 В, когда она нажата. Но ничего не происходит.
Я также проверил, что экран SEEED получает данные CAN, как и ожидалось. Также не возникает никаких проблем с арбитражем или странных событий с протоколом CAN, поскольку на этом этапе я отправляю сообщения вручную (используя ECUMaster Light Client).
У меня есть данные CAN, которые сохраняются и перемещаются. вокруг и т. д. во время цикла().
Затем в моем цикле Миллиса происходят обновления экрана.
Все, что происходит во время bingus() (прерывание моей кнопки), — это изменение переменной номера экрана и задержки, чтобы помочь немного смягчить нажатие кнопки шум.
Вот мой код. Пожалуйста, проигнорируйте некоторые незавершенные моменты, касающиеся флагов; проблема не в них, поскольку, когда я их комментирую, происходит то же самое.
long previousMillis = 0; //used later in a non-blocking millis loop
long interval = 10; //that loop runs every 10 ms
#include "Adafruit_LiquidCrystal.h"
Adafruit_LiquidCrystal lcd(0);
#define CAN_2515 //choosing the correct IC
// For Arduino MCP2515 Hat (I used the UNO one from SEEED):
const int SPI_CS_PIN = 9; //don't change these if using the SEEED hat.
const int CAN_INT_PIN = 2;
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
int screennum = 0;
bool faultpresent = 0;
void setup() {
pinMode(3, INPUT);
attachInterrupt(digitalPinToInterrupt(3), bingus, RISING);
// set up the LCD's number of columns and rows:
lcd.begin(20, 4);
// Print a message to the LCD.
lcd.print("hello!");
pinMode(3, INPUT);
delay(5000);
while (CAN_OK != CAN.begin(CAN_250KBPS)) { // init can bus : baudrate = 250k BE SURE TO CHANGE IF YOUR BUS IS RUNNING FASTER / SLOWER!!!
delay(100); //give it time to wake up
}
}
void loop() {
uint8_t len = 8;
uint8_t buf[8]; //this is an array of 8 bytes, where every incoming CAN message is stored during its "turn".
int SOCa;
int tempa;
int currenta;
int voltagea;
int parallelLedstate;
int flagnum;
int position;
String faultcode;
String faultcodeID1;
String faultcodeID2;
String message[7] = { "State of Charge:", "Battery Temp:", "DC Current:", "Motor Temp:", "Controller Temp:", "Battery Volts:", "Parallel State:" };
String flag1[8] = { "P0A0F", "P0A02", "P0A9C", "U0100", "P0560", "P0AA6", "P0A05", "P0A06" };
String flag2[8] = { "P0A07", "P0A08", "P0A09", "P0A0A", "P0A0B", "P0A0C", "P0A0E", "P0A10" };
String flag3[8] = { "P0A11", "P0A1F", "P0A12", "P0A80", "P0AFA", "P0A04", "P0AC0", "P0A0D" };
String flag1ID[8] = { "Cell bank fault", "Weak pack fault", "Thermistor fault", "CAN communication", "Redundant power", "High voltage", "Invalid input suppl-", "Charge-enable" };
String flag1ID2[8] = { " ", " ", " ", "fault", "supply fault", "isolation fault", "y voltage fault", "relay fault" };
String flag2ID[8] = { "Discharge-enable", "Charger safety", "Internal hardware", "Internal heatsink", "Internal logic", "Highest cell", "Lowest cell", "pack too hot" };
String flag2ID2[8] = { "relay fault", "relay fault", "fault", "thermistor fault", "fault", "voltage too high", "voltage too low", "fault" };
String flag3ID[8] = { "Abnormal state of", "Internal cell", "Cell balancing", "Weak cell fault", "Low cell voltage", "Cell open wiring", "Current sensor", "Cell voltage over" };
String flag3ID2[8] = { "charge behavior", "communication fault", "stuck off fault", " ", "fault", "fault", "fault", "5V fault" };
if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming
CAN.readMsgBuf(&len, buf); // read data
unsigned long canId = CAN.getCanId(); //store the Identifier in an unsigned long (in case it happens to be an extended ID)
if (canId == 0x6B0) { //can message from Orion that contains DC bus current and State Of Charge data; I think 0x6B0 is the default
SOCa = (uint16_t)(buf[4]); //Orion sends SOC in Byte 4 of the 6B0 message.
currenta = (int)buf[0] 1) { //don't pull any data from 0x666 unless the first bit is high, signaling that there is in fact a fault present
faultpresent = 1; //set the flag to tell the millis function to override the normal data displaying
if (buf[1] > 1) {
flagnum = 1;
//insert code here that returns the position of the first high bit in buf[1];
}
if ((buf[1] == 0) && (buf[2] > 1)) {
flagnum = 2;
//insert code here that returns the position of the first high bit in buf[2];
}
if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0)) {
flagnum = 3;
//insert code here that returns the first high bit in buf[3]
}
} else {
faultpresent = 0; //if the first bit of byte 0 of the fault message (0x666) is low, there is no fault.
}
}
}
unsigned long currentMillis = millis(); //non blocking timer loop to print current data to the LCD every 104 ms
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (faultpresent = 0) { //only show the normal flip-through-able data if there is no fault present
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(message[screennum]); //print the name of whatever parameter is being shown
lcd.setCursor(0, 2);
lcd.print(data[screennum]); //print the data of whatever parameter is being shown
}
else {
if (flagnum = 1) { //if the fault ID lies in byte 1 of 0x666...
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(flag1[position]); //print the fault code (Ex. "P0A0F")
lcd.setCursor(0, 2);
lcd.print(flag1ID[position]); //print the first line of the fault description
lcd.setCursor(0, 3);
lcd.print(flag1ID2[position]); //print the second line of the fault description
}
if (flagnum = 2) {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(flag2[position]);
lcd.setCursor(0, 2);
lcd.print(flag2ID[position]);
lcd.setCursor(0, 3);
lcd.print(flag2ID2[position]);
}
if (flagnum = 3) {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(flag3[position]);
lcd.setCursor(0, 2);
lcd.print(flag3ID[position]);
lcd.setCursor(0, 3);
lcd.print(flag3ID2[position]);
}
}
}
}
void bingus() {
if (screennum < 6) {
delay(500);
faultpresent = 0; //clear fault with button press
//code to set a timer for 1 minute until the code is instead shown on line 4
screennum = (screennum + 1); //increment the variable that governs what parameter is shown, by 1
delay(1000);
} else {
delay(500);
screennum = 0; //unless it is already at 6, in which case it increments back to 0
delay(1000);
}
}
Я очень ценю любую помощь и прошу прощения, если моя ошибка действительно тривиальна. Я не программист, а просто инженер, который любит пробовать что-то новое.
Я использую Arduino Uno с экраном CAN-шины SEEED и ЖК-дисплеем 4x20 с рюкзаком Adafruit I2C. Я пытаюсь заставить Uno получать несколько разных сообщений через CAN, а затем отображать полученные от них данные на ЖК-дисплее с помощью кнопки, позволяющей конечному пользователю пролистывать, какие данные отображаются. Мне удалось заставить настройку экрана Uno+CAN-шины работать в более простой схеме, где она просто непрерывно отображает один байт или слово сообщения CAN на ЖК-дисплее, без каких-либо «изменений экрана». Я не могу получить моя кнопка для смены экранов, и я думаю, что это вызвано какой-то основной структурной проблемой. Я не очень хорошо разбираюсь в кодировании, большую часть времени мне удается просто модифицировать примеры, но этот проект слишком сложен для этой стратегии. Я попробовал использовать срабатывание по прерыванию по нарастающему фронту на выводе я подключился к НО контакту моей кнопки, контакт С которой был подключен к 5В. Этот штифт (3) также вытягивается вниз на 10К. Я проверил, что на контакте 3 напряжение 0 В, когда кнопка не нажата, и 5 В, когда она нажата. Но ничего не происходит. Я также проверил, что экран SEEED получает данные CAN, как и ожидалось. Также не возникает никаких проблем с арбитражем или странных событий с протоколом CAN, поскольку на этом этапе я отправляю сообщения вручную (используя ECUMaster Light Client). У меня есть данные CAN, которые сохраняются и перемещаются. вокруг и т. д. во время цикла(). Затем в моем цикле Миллиса происходят обновления экрана. Все, что происходит во время bingus() (прерывание моей кнопки), — это изменение переменной номера экрана и задержки, чтобы помочь немного смягчить нажатие кнопки шум. Вот мой код. Пожалуйста, проигнорируйте некоторые незавершенные моменты, касающиеся флагов; проблема не в них, поскольку, когда я их комментирую, происходит то же самое. [code]long previousMillis = 0; //used later in a non-blocking millis loop long interval = 10; //that loop runs every 10 ms
#include "Adafruit_LiquidCrystal.h"
Adafruit_LiquidCrystal lcd(0);
#define CAN_2515 //choosing the correct IC
// For Arduino MCP2515 Hat (I used the UNO one from SEEED): const int SPI_CS_PIN = 9; //don't change these if using the SEEED hat. const int CAN_INT_PIN = 2;
void setup() { pinMode(3, INPUT); attachInterrupt(digitalPinToInterrupt(3), bingus, RISING); // set up the LCD's number of columns and rows: lcd.begin(20, 4); // Print a message to the LCD. lcd.print("hello!"); pinMode(3, INPUT); delay(5000);
while (CAN_OK != CAN.begin(CAN_250KBPS)) { // init can bus : baudrate = 250k BE SURE TO CHANGE IF YOUR BUS IS RUNNING FASTER / SLOWER!!! delay(100); //give it time to wake up } }
void loop() {
uint8_t len = 8; uint8_t buf[8]; //this is an array of 8 bytes, where every incoming CAN message is stored during its "turn". int SOCa; int tempa; int currenta; int voltagea; int parallelLedstate; int flagnum; int position; String faultcode; String faultcodeID1; String faultcodeID2; String message[7] = { "State of Charge:", "Battery Temp:", "DC Current:", "Motor Temp:", "Controller Temp:", "Battery Volts:", "Parallel State:" }; String flag1[8] = { "P0A0F", "P0A02", "P0A9C", "U0100", "P0560", "P0AA6", "P0A05", "P0A06" }; String flag2[8] = { "P0A07", "P0A08", "P0A09", "P0A0A", "P0A0B", "P0A0C", "P0A0E", "P0A10" }; String flag3[8] = { "P0A11", "P0A1F", "P0A12", "P0A80", "P0AFA", "P0A04", "P0AC0", "P0A0D" }; String flag1ID[8] = { "Cell bank fault", "Weak pack fault", "Thermistor fault", "CAN communication", "Redundant power", "High voltage", "Invalid input suppl-", "Charge-enable" }; String flag1ID2[8] = { " ", " ", " ", "fault", "supply fault", "isolation fault", "y voltage fault", "relay fault" }; String flag2ID[8] = { "Discharge-enable", "Charger safety", "Internal hardware", "Internal heatsink", "Internal logic", "Highest cell", "Lowest cell", "pack too hot" }; String flag2ID2[8] = { "relay fault", "relay fault", "fault", "thermistor fault", "fault", "voltage too high", "voltage too low", "fault" }; String flag3ID[8] = { "Abnormal state of", "Internal cell", "Cell balancing", "Weak cell fault", "Low cell voltage", "Cell open wiring", "Current sensor", "Cell voltage over" }; String flag3ID2[8] = { "charge behavior", "communication fault", "stuck off fault", " ", "fault", "fault", "fault", "5V fault" };
if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming CAN.readMsgBuf(&len, buf); // read data
unsigned long canId = CAN.getCanId(); //store the Identifier in an unsigned long (in case it happens to be an extended ID)
if (canId == 0x6B0) { //can message from Orion that contains DC bus current and State Of Charge data; I think 0x6B0 is the default SOCa = (uint16_t)(buf[4]); //Orion sends SOC in Byte 4 of the 6B0 message. currenta = (int)buf[0] 1) { //don't pull any data from 0x666 unless the first bit is high, signaling that there is in fact a fault present faultpresent = 1; //set the flag to tell the millis function to override the normal data displaying if (buf[1] > 1) { flagnum = 1; //insert code here that returns the position of the first high bit in buf[1]; } if ((buf[1] == 0) && (buf[2] > 1)) { flagnum = 2; //insert code here that returns the position of the first high bit in buf[2]; } if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0)) { flagnum = 3; //insert code here that returns the first high bit in buf[3] }
} else { faultpresent = 0; //if the first bit of byte 0 of the fault message (0x666) is low, there is no fault. } } }
unsigned long currentMillis = millis(); //non blocking timer loop to print current data to the LCD every 104 ms if (currentMillis - previousMillis > interval) { previousMillis = currentMillis; if (faultpresent = 0) { //only show the normal flip-through-able data if there is no fault present lcd.clear(); lcd.setCursor(0, 1); lcd.print(message[screennum]); //print the name of whatever parameter is being shown lcd.setCursor(0, 2); lcd.print(data[screennum]); //print the data of whatever parameter is being shown } else { if (flagnum = 1) { //if the fault ID lies in byte 1 of 0x666... lcd.clear(); lcd.setCursor(0, 1); lcd.print(flag1[position]); //print the fault code (Ex. "P0A0F") lcd.setCursor(0, 2); lcd.print(flag1ID[position]); //print the first line of the fault description lcd.setCursor(0, 3); lcd.print(flag1ID2[position]); //print the second line of the fault description } if (flagnum = 2) { lcd.clear(); lcd.setCursor(0, 1); lcd.print(flag2[position]); lcd.setCursor(0, 2); lcd.print(flag2ID[position]); lcd.setCursor(0, 3); lcd.print(flag2ID2[position]); } if (flagnum = 3) { lcd.clear(); lcd.setCursor(0, 1); lcd.print(flag3[position]); lcd.setCursor(0, 2); lcd.print(flag3ID[position]); lcd.setCursor(0, 3); lcd.print(flag3ID2[position]); } } } }
void bingus() {
if (screennum < 6) { delay(500); faultpresent = 0; //clear fault with button press //code to set a timer for 1 minute until the code is instead shown on line 4 screennum = (screennum + 1); //increment the variable that governs what parameter is shown, by 1 delay(1000); } else { delay(500); screennum = 0; //unless it is already at 6, in which case it increments back to 0 delay(1000); } } [/code] Я очень ценю любую помощь и прошу прощения, если моя ошибка действительно тривиальна. Я не программист, а просто инженер, который любит пробовать что-то новое.