First serial console controllable version
This commit is contained in:
parent
cf825b97fb
commit
0d158eaa78
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"string_view": "cpp",
|
||||||
|
"*.new": "c"
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,8 +8,19 @@
|
||||||
; Please visit documentation for the other options and examples
|
; Please visit documentation for the other options and examples
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[env:nodemcu-32s]
|
[env:nodemcu-32s-dev]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = nodemcu-32s
|
board = nodemcu-32s
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
upload_speed = 115200
|
||||||
|
build_flags = -DCORE_DEBUG_LEVEL=5
|
||||||
|
|
||||||
|
[env:nodemcu-32s-prod]
|
||||||
|
platform = espressif32
|
||||||
|
board = nodemcu-32s
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
upload_speed = 115200
|
||||||
|
build_flags = -DCORE_DEBUG_LEVEL=3
|
452
src/main.cpp
452
src/main.cpp
|
@ -1,70 +1,412 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
#include <CAN.h>
|
#include <CAN.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
#define TX_DELAY 3 // Delay between messages
|
// Task handles
|
||||||
|
TaskHandle_t xCANSendTaskHandle = NULL;
|
||||||
|
TaskHandle_t xSerialConsoleTaskHandle = NULL;
|
||||||
|
|
||||||
byte sndStat; // Status of the sent message (global variable)
|
// Task functions
|
||||||
|
void vCANSendTask(void *pvParameters);
|
||||||
|
void vSerialConsoleTask(void *pvParameters);
|
||||||
|
|
||||||
// Struct to hold CAN packet information
|
// Define CAN frame IDs and data
|
||||||
struct CanPacket {
|
struct CANFrame
|
||||||
unsigned long id;
|
{
|
||||||
char data[24];
|
unsigned long id;
|
||||||
|
byte length;
|
||||||
|
byte data[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Array of CAN packets to be sent
|
CANFrame frames[] = {
|
||||||
const CanPacket packets[] PROGMEM = {
|
{0x418, 8, {0x30, 0x07, 0x00, 0x03, 0x28, 0x28, 0xF8, 0xA0}},
|
||||||
{0x418, "30 07 00 03 28 28 F8 A0"},
|
{0x46B, 8, {0x01, 0x00, 0xA3, 0x00, 0x01, 0x00, 0x00, 0xC0}},
|
||||||
{0x46B, "01 00 A3 00 01 00 00 C0"},
|
{0x47C, 8, {0x64, 0x7D, 0x42, 0x01, 0x91, 0x00, 0x70, 0x04}},
|
||||||
{0x47C, "64 7D 42 01 91 00 70 04"},
|
{0x47D, 8, {0x04, 0xC1, 0x77, 0x95, 0x60, 0x01, 0x20, 0xC4}},
|
||||||
{0x47D, "04 C1 77 95 60 01 20 C4"},
|
{0x47F, 8, {0x04, 0x0C, 0xFA, 0x00, 0xEA, 0x72, 0x44, 0x00}},
|
||||||
{0x47F, "34 0C 96 00 EA 72 44 00"},
|
{0x25B, 6, {0x04, 0x46, 0x00, 0xFF, 0xFF, 0xC0}},
|
||||||
{0x25B, "04 46 00 FF FF C0"},
|
{0x69F, 4, {0x75, 0x01, 0x33, 0x6F}}}; // Easylink anti-theft protecion, last 7 number of VIN in reverse order + last byte F.
|
||||||
{0x69F, "75 01 33 6F"}, //Anti-Theft protection, VIN encoding unknown
|
|
||||||
};
|
// Define byte indices for CAN frame modification
|
||||||
|
#define STANDBY_BYTE_INDEX 0
|
||||||
|
#define MUTE_BYTE_INDEX 2
|
||||||
|
#define REVERSE_BYTE_INDEX 0
|
||||||
|
#define BRIGHTNESS_BYTE_INDEX 1
|
||||||
|
#define BRIGHTNESS_LEVEL_BYTE_INDEX 2
|
||||||
|
#define VOLUME_BYTE_INDEX 4
|
||||||
|
|
||||||
|
// Define GPIO pins
|
||||||
|
#define IGNITION_GPIO_PIN 6
|
||||||
|
#define REVERSE_GPIO_PIN 7
|
||||||
|
#define DEBOUNCE_DELAY_IGNITION 1000
|
||||||
|
#define DEBOUNCE_DELAY_OTHERS 100
|
||||||
|
#define STANDBY_DURATION 3600000 // 60 minutes in milliseconds
|
||||||
|
|
||||||
|
// Define initial states for variables
|
||||||
|
bool ignitionState = false;
|
||||||
|
bool reverseState = false;
|
||||||
|
bool brightnessState = false; // false: day, true: night
|
||||||
|
bool muteState = false;
|
||||||
|
bool standbyState = false;
|
||||||
|
bool volumeState = false; // false: normal, true: lowered
|
||||||
|
int brightnessLevel = 50; // Default brightness level (0-100)
|
||||||
|
bool gpioEnabled = false;
|
||||||
|
unsigned long lastIgnitionTime = 0;
|
||||||
|
unsigned long lastReverseTime = 0;
|
||||||
|
bool gpioIgnitionState = false; // Tracks the state of GPIO ignition
|
||||||
|
unsigned long standbyStartTime = 0; // Tracks the start time of standby mode
|
||||||
|
|
||||||
|
// Internal variables
|
||||||
|
bool serial_init = false;
|
||||||
|
bool can_enabled = false;
|
||||||
|
|
||||||
|
// Function to initialize CAN bus
|
||||||
|
void initCAN()
|
||||||
|
{
|
||||||
|
while (!CAN.begin(500E3))
|
||||||
|
{
|
||||||
|
ESP_LOGE("CAN Interface", "Initialization failed, retrying...");
|
||||||
|
vTaskDelay(100);
|
||||||
|
}
|
||||||
|
ESP_LOGI("CAN Interface", "Initialization succeeded!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopCAN()
|
||||||
|
{
|
||||||
|
CAN.end();
|
||||||
|
ESP_LOGI("CAN Interface", "Shutdown succeeded!");
|
||||||
|
}
|
||||||
|
|
||||||
// Function to send a CAN message
|
// Function to send a CAN message
|
||||||
void sendCanMessage(unsigned long canId, const char* hexString) {
|
void sendCANFrame(unsigned long canId, const byte *data, int len)
|
||||||
int len = strlen(hexString) / 3 + 1; // Determine the length of the data in bytes
|
{
|
||||||
byte data[len]; // Create an array to store the data bytes
|
ESP_LOGD("CAN Interface", "TX ID 0x%02X DATA %02X", canId, data);
|
||||||
|
CAN.beginPacket(canId);
|
||||||
// Convert hex string to bytes
|
CAN.write(data, len);
|
||||||
for (int i = 0; i < len; i++) {
|
CAN.endPacket();
|
||||||
unsigned int byteData;
|
ESP_LOGD("CAN Interface", "TX successful");
|
||||||
sscanf(&hexString[i * 3], "%x", &byteData);
|
|
||||||
data[i] = (byte)byteData;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAN.beginPacket(canId);
|
|
||||||
CAN.write(data, len);
|
|
||||||
CAN.endPacket();
|
|
||||||
|
|
||||||
Serial.print("Message Sent: ID = ");
|
|
||||||
Serial.print(canId, HEX);
|
|
||||||
Serial.print(", Data = ");
|
|
||||||
Serial.println(hexString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to update CAN frame data based on variables
|
||||||
void setup() {
|
void updateCANFrameData(CANFrame *frames)
|
||||||
Serial.begin(115200);
|
{
|
||||||
Serial.println("CAN_Waker starting up...");
|
frames[4].data[BRIGHTNESS_BYTE_INDEX] = brightnessState ? 0x8C : 0x0C;
|
||||||
|
frames[4].data[VOLUME_BYTE_INDEX] = volumeState ? 0xEE : 0xEA;
|
||||||
|
frames[4].data[BRIGHTNESS_LEVEL_BYTE_INDEX] = map(brightnessLevel, 0, 100, 0x00, 0xFA);
|
||||||
// start the CAN bus at 500 kbps
|
frames[5].data[REVERSE_BYTE_INDEX] = reverseState ? 0x08 : 0x04;
|
||||||
if (!CAN.begin(500E3)) {
|
frames[3].data[MUTE_BYTE_INDEX] = muteState ? 0x00 : 0x77;
|
||||||
Serial.println("Starting CAN failed!");
|
frames[1].data[STANDBY_BYTE_INDEX] = standbyState ? 0x00 : 0x01;
|
||||||
while (1);
|
ESP_LOGD("CAN", "Frame update successful");
|
||||||
}
|
|
||||||
|
|
||||||
delay(2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
// Function to handle GPIO inputs
|
||||||
// Replay all the CAN packets
|
void handleGPIO()
|
||||||
for (unsigned int i = 0; i < sizeof(packets) / sizeof(packets[0]); i++) {
|
{
|
||||||
CanPacket packet;
|
// If GPIO is disabled, return without processing GPIO inputs
|
||||||
memcpy_P(&packet, &packets[i], sizeof(CanPacket)); // Copy packet from PROGMEM to SRAM
|
if (!gpioEnabled)
|
||||||
sendCanMessage(packet.id, packet.data); // packet.data is now a char array
|
{
|
||||||
delay(TX_DELAY); // Wait for the specified delay between messages
|
return;
|
||||||
|
}
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
// Ignition input
|
||||||
|
if (currentMillis - lastIgnitionTime >= DEBOUNCE_DELAY_IGNITION)
|
||||||
|
{
|
||||||
|
bool newIgnitionState = digitalRead(IGNITION_GPIO_PIN);
|
||||||
|
if (newIgnitionState != ignitionState)
|
||||||
|
{
|
||||||
|
if (!newIgnitionState)
|
||||||
|
{
|
||||||
|
ESP_LOGI("GPIO State machine", "Ignition turned off");
|
||||||
|
lastIgnitionTime = currentMillis;
|
||||||
|
ignitionState = false;
|
||||||
|
// Shut down CAN interface if ignition is off
|
||||||
|
if (!ignitionState)
|
||||||
|
{
|
||||||
|
stopCAN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI("GPIO State machine", "Ignition turned on");
|
||||||
|
ignitionState = true;
|
||||||
|
// Initialize CAN interface if ignition is on
|
||||||
|
if (ignitionState)
|
||||||
|
{
|
||||||
|
initCAN();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle reverse input
|
||||||
|
if (gpioEnabled && currentMillis - lastReverseTime >= DEBOUNCE_DELAY_OTHERS)
|
||||||
|
{
|
||||||
|
bool newReverseState = digitalRead(REVERSE_GPIO_PIN);
|
||||||
|
if (newReverseState != reverseState)
|
||||||
|
{
|
||||||
|
if (newReverseState)
|
||||||
|
{
|
||||||
|
// Reverse engaged
|
||||||
|
ESP_LOGI("GPIO State machine", "Reversing engaged");
|
||||||
|
reverseState = true;
|
||||||
|
volumeState = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reverse disengaged
|
||||||
|
ESP_LOGI("GPIO State machine", "Reversing disengaged");
|
||||||
|
reverseState = false;
|
||||||
|
volumeState = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to print summary of all serial variables
|
||||||
|
void printVariableSummary()
|
||||||
|
{
|
||||||
|
Serial.println("---CAN status summary----");
|
||||||
|
Serial.println("-------------------------");
|
||||||
|
Serial.print("Ignition: ");
|
||||||
|
Serial.println(ignitionState ? "on" : "off");
|
||||||
|
Serial.print("Standby:");
|
||||||
|
Serial.println(standbyState ? "yes" : "no");
|
||||||
|
Serial.print("Reverse: ");
|
||||||
|
Serial.println(reverseState ? "on" : "off");
|
||||||
|
Serial.print("Brightness: ");
|
||||||
|
Serial.println(brightnessState ? "night" : "day");
|
||||||
|
Serial.print("Mute: ");
|
||||||
|
Serial.println(muteState ? "on" : "off");
|
||||||
|
Serial.print("Volume: ");
|
||||||
|
Serial.println(volumeState ? "lowered" : "normal");
|
||||||
|
Serial.print("Brightness Level: ");
|
||||||
|
Serial.println(brightnessLevel);
|
||||||
|
Serial.print("GPIO: ");
|
||||||
|
Serial.println(gpioEnabled ? "enable" : "disable");
|
||||||
|
Serial.println("-------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
void vCANSendTask(void *pvParameters)
|
||||||
|
{
|
||||||
|
(void)pvParameters;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
handleGPIO();
|
||||||
|
|
||||||
|
// Send CAN frames at 10Hz if ignition is on
|
||||||
|
if (ignitionState || gpioIgnitionState)
|
||||||
|
{
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
static unsigned long lastTxTime = 0;
|
||||||
|
if (currentMillis - lastTxTime >= 100)
|
||||||
|
{
|
||||||
|
// Update CAN frame data based on variables
|
||||||
|
updateCANFrameData(frames);
|
||||||
|
// Send all CAN frames
|
||||||
|
int i = 0;
|
||||||
|
if (standbyState)
|
||||||
|
{
|
||||||
|
i = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
for (i; i < 6; i++)
|
||||||
|
{
|
||||||
|
sendCANFrame(frames[i].id, frames[i].data, frames[i].length);
|
||||||
|
}
|
||||||
|
lastTxTime = currentMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send CAN frame at 1Hz
|
||||||
|
static unsigned long lastTxTime69F = 0;
|
||||||
|
if (currentMillis - lastTxTime69F >= 1000)
|
||||||
|
{
|
||||||
|
sendCANFrame(frames[6].id, frames[6].data, frames[6].length); // Send anti-theft frame
|
||||||
|
lastTxTime69F = currentMillis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if ignition should go into standby mode
|
||||||
|
if (!gpioIgnitionState && ignitionState && !standbyStartTime)
|
||||||
|
{
|
||||||
|
standbyStartTime = millis(); // Start the standby timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if standby duration has elapsed and gpio ignition is still false
|
||||||
|
if (standbyStartTime && millis() - standbyStartTime >= STANDBY_DURATION && !gpioIgnitionState)
|
||||||
|
{
|
||||||
|
ignitionState = false; // Set ignition to off after standby duration
|
||||||
|
ESP_LOGI("State machine", "Ignition turned off after standby duration");
|
||||||
|
standbyState = false;
|
||||||
|
standbyStartTime = 0; // Reset standby timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// If GPIO ignition is true, reset standby timer
|
||||||
|
if (gpioIgnitionState)
|
||||||
|
{
|
||||||
|
standbyStartTime = 0; // Reset standby timer
|
||||||
|
standbyState = false;
|
||||||
|
}
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vSerialConsoleTask(void *pvParameters)
|
||||||
|
{
|
||||||
|
(void)pvParameters;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (Serial.available() > 0)
|
||||||
|
{
|
||||||
|
String input = Serial.readStringUntil('\n');
|
||||||
|
input.trim();
|
||||||
|
if (input.length() == 0)
|
||||||
|
{
|
||||||
|
printVariableSummary();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Parse input commands
|
||||||
|
if (input.startsWith("ignition"))
|
||||||
|
{
|
||||||
|
if (input.endsWith("on"))
|
||||||
|
{
|
||||||
|
ignitionState = true;
|
||||||
|
ESP_LOGI("State machine", "Ignition turned on");
|
||||||
|
standbyState = false;
|
||||||
|
if (!can_enabled)
|
||||||
|
{
|
||||||
|
ESP_LOGD("State machine", "Try to enable CAN Interface");
|
||||||
|
initCAN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.endsWith("off"))
|
||||||
|
{
|
||||||
|
ignitionState = false;
|
||||||
|
standbyStartTime = millis();
|
||||||
|
ESP_LOGI("State machine", "Ignition turned off");
|
||||||
|
if (can_enabled)
|
||||||
|
{
|
||||||
|
ESP_LOGD("State machine", "Try to disable CAN Interface");
|
||||||
|
stopCAN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.endsWith("standby"))
|
||||||
|
{
|
||||||
|
// Print current standby duration if ignition is in standby mode
|
||||||
|
if (standbyStartTime)
|
||||||
|
{
|
||||||
|
unsigned long remainingTime = STANDBY_DURATION - (millis() - standbyStartTime);
|
||||||
|
standbyState = true;
|
||||||
|
ESP_LOGI("State machine", "Ignition in standby mode, remaining time: %d minutes", remainingTime / 60000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI("State machine", "Ignition is not in standby mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.startsWith("gpio"))
|
||||||
|
{
|
||||||
|
if (input.endsWith("enable"))
|
||||||
|
{
|
||||||
|
gpioEnabled = true;
|
||||||
|
ESP_LOGI("Variables", "GPIO enabled");
|
||||||
|
}
|
||||||
|
else if (input.endsWith("disable"))
|
||||||
|
{
|
||||||
|
gpioEnabled = false;
|
||||||
|
ESP_LOGI("Variables", "GPIO disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.startsWith("mute"))
|
||||||
|
{
|
||||||
|
if (input.endsWith("on"))
|
||||||
|
{
|
||||||
|
muteState = true;
|
||||||
|
ESP_LOGI("Variables", "MUTE turned on");
|
||||||
|
}
|
||||||
|
else if (input.endsWith("off"))
|
||||||
|
{
|
||||||
|
muteState = false;
|
||||||
|
ESP_LOGI("Variables", "MUTE turned off");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.startsWith("reverse"))
|
||||||
|
{
|
||||||
|
if (input.endsWith("on"))
|
||||||
|
{
|
||||||
|
reverseState = true;
|
||||||
|
ESP_LOGI("Variables", "REVERSE turned on");
|
||||||
|
}
|
||||||
|
else if (input.endsWith("off"))
|
||||||
|
{
|
||||||
|
reverseState = false;
|
||||||
|
ESP_LOGI("Variables", "REVERSE turned off");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.startsWith("brightness"))
|
||||||
|
{
|
||||||
|
if (input.endsWith("day"))
|
||||||
|
{
|
||||||
|
brightnessState = false;
|
||||||
|
ESP_LOGI("Variables", "Brightness set to DAY");
|
||||||
|
}
|
||||||
|
else if (input.endsWith("night"))
|
||||||
|
{
|
||||||
|
brightnessState = true;
|
||||||
|
ESP_LOGI("Variables", "Brightness set to NIGHT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input.startsWith("volume"))
|
||||||
|
{
|
||||||
|
if (input.endsWith("normal"))
|
||||||
|
{
|
||||||
|
volumeState = false;
|
||||||
|
ESP_LOGI("Variables", "VOLUME set to NORMAL");
|
||||||
|
}
|
||||||
|
else if (input.endsWith("lowered"))
|
||||||
|
{
|
||||||
|
volumeState = true;
|
||||||
|
ESP_LOGI("Variables", "VOLUME set to LOWERED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE("Variables", "Invalid command received");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.setTimeout(5000);
|
||||||
|
ESP_LOGI("SYS", "Easylink CAN Waker application starting up...");
|
||||||
|
|
||||||
|
//Print state of variables during bootup
|
||||||
|
printVariableSummary();
|
||||||
|
ESP_LOGD("SYS", "Print actual variable states");
|
||||||
|
|
||||||
|
//Start tasks one per CPU, because we have enough ressources :-)
|
||||||
|
vTaskStartScheduler();
|
||||||
|
ESP_LOGD("SYS", "Start FreeRTOS scheduler");
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(vCANSendTask, "CANSendTask", 8096, NULL, 10, &xCANSendTaskHandle, 0);
|
||||||
|
ESP_LOGD("SYS", "Start CANSendTask");
|
||||||
|
xTaskCreatePinnedToCore(vSerialConsoleTask, "SerialConsoleTask", 8096, NULL, 10, &xSerialConsoleTaskHandle, 1);
|
||||||
|
ESP_LOGD("SYS", "Start SerialConsoleTask");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
//We are using tasks instead
|
||||||
|
}
|
70
src/main.cpp.old
Normal file
70
src/main.cpp.old
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <CAN.h>
|
||||||
|
|
||||||
|
#define TX_DELAY 3 // Delay between messages
|
||||||
|
|
||||||
|
byte sndStat; // Status of the sent message (global variable)
|
||||||
|
|
||||||
|
// Struct to hold CAN packet information
|
||||||
|
struct CanPacket {
|
||||||
|
unsigned long id;
|
||||||
|
char data[24];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Array of CAN packets to be sent
|
||||||
|
const CanPacket packets[] PROGMEM = {
|
||||||
|
{0x418, "30 07 00 03 28 28 F8 A0"},
|
||||||
|
{0x46B, "01 00 A3 00 01 00 00 C0"},
|
||||||
|
{0x47C, "64 7D 42 01 91 00 70 04"},
|
||||||
|
{0x47D, "04 C1 77 95 60 01 20 C4"},
|
||||||
|
{0x47F, "34 0C 96 00 EA 72 44 00"},
|
||||||
|
{0x25B, "04 46 00 FF FF C0"},
|
||||||
|
{0x69F, "75 01 33 6F"}, //Anti-Theft protection, VIN encoding unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to send a CAN message
|
||||||
|
void sendCanMessage(unsigned long canId, const char* hexString) {
|
||||||
|
int len = strlen(hexString) / 3 + 1; // Determine the length of the data in bytes
|
||||||
|
byte data[len]; // Create an array to store the data bytes
|
||||||
|
|
||||||
|
// Convert hex string to bytes
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
unsigned int byteData;
|
||||||
|
sscanf(&hexString[i * 3], "%x", &byteData);
|
||||||
|
data[i] = (byte)byteData;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN.beginPacket(canId);
|
||||||
|
CAN.write(data, len);
|
||||||
|
CAN.endPacket();
|
||||||
|
|
||||||
|
Serial.print("Message Sent: ID = ");
|
||||||
|
Serial.print(canId, HEX);
|
||||||
|
Serial.print(", Data = ");
|
||||||
|
Serial.println(hexString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("CAN_Waker starting up...");
|
||||||
|
|
||||||
|
|
||||||
|
// start the CAN bus at 500 kbps
|
||||||
|
if (!CAN.begin(500E3)) {
|
||||||
|
Serial.println("Starting CAN failed!");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Replay all the CAN packets
|
||||||
|
for (unsigned int i = 0; i < sizeof(packets) / sizeof(packets[0]); i++) {
|
||||||
|
CanPacket packet;
|
||||||
|
memcpy_P(&packet, &packets[i], sizeof(CanPacket)); // Copy packet from PROGMEM to SRAM
|
||||||
|
sendCanMessage(packet.id, packet.data); // packet.data is now a char array
|
||||||
|
delay(TX_DELAY); // Wait for the specified delay between messages
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue