-
Notifications
You must be signed in to change notification settings - Fork 2
5. Managing device setting
You might wonder what REV hardware Client and CTRE Phoenix Tuner does? How they communicate with the device?
The main difference between CTRE Tuner X and REV Client is how connection to the actual device is handled. CTRE use a more complicated implementation which had a CAN bridging service on roboRIO (phoenix diagnostic) that hardware client connect to. On the other hand, REV use USB direct to device connection which the USB interface act as a CAN adaptor (preparatory to REV).
They both had their own benefit. CTRE always require roboRIO to configure device, but you could do it wirelessly. On the other hand, REV doesn’t require roboRIO but require USB tethering to the device itself. Both manufacturer use GitHub - wpilibsuite/vendor-template to create their library while our roboRIO implementation is simpler.
The short answer is no. but we still need some massage to manage device setting. Here are some of the options.
Hard code all configuration to the device. CAN Device Number change would require re-flashing the firmware via USB after changing it on the code. Also all the settings are hardcoded. (for things like battery RFID this is completely fine).
CAN Device Number and default setting is hardcoded. However, most setting could be modified from roboRIO by API. To facilitate these, your sensor needs to echo back it’s configuration to roboRIO. RoboRIO would compare it to your code set configuration and automatically apply settings to CAN device if discrepancy is found. I actually do the exact same thing in my ToF project. These settings will lost if MCU is powered down.
To extend on Method 3, you could add a command that if received by ESP32, it would save its current setting. You can also create a command to set CAN Device Number. However, if you do this, you would need to have your robot code handle the ID change which add a lot of complication. I wouldn’t suggest doing CAN Device Number change via CAN command from roboRIO because this is just too much work. Re-flash your MCU during competition is more feasible and faster in competition.
Create some serial protocol to change settings and make a custom program to interrogate with ESP32. You could do this on top of method 2, or do a partial implementation (for example, serial only used for CAN Device Number change), and all settings relating to the sensor itself are pulled from roboRIO.
Create a full hardware client that could do everything. This is a lot of work. Unless you plan on selling a product, it might not worth the effort.
Here is a basic flow chart of how this will work.
+------------------------------+
| Power On / Reset |
+------------------------------+
|
v
+---------------------------------------------+
| Check Flash Memory for Saved CAN Device ID |
+---------------------------------------------+
| |
| Setting Found | No Setting Found
v v
+-------------------+ +--------------------+
| Use Saved Setting | | Use Default Setting|
+-------------------+ +--------------------+
|
v
+-----------------------------------------+
| Start 3 Tasks (Parallel Execution): |
| 1. Serial CAN ID Helper |
| 2. CAN Send |
| 3. CAN Receive |
+-----------------------------------------+
| | |
| | |
v v v
+-------------------+ +---------------------------+ +----------------------------+
| Serial CAN ID | | CAN Send Task | | CAN Receive Task |
| Helper Task | |---------------------------| |----------------------------|
|-------------------| | Send current sensor config| | On new config frame: |
| If "change ID" cmd| |---------------------------| | Apply setting to sensor |
| → Apply new ID | | RoboRIO compares desired | +----------------------------+
| If "save" cmd | | vs. actual config |
| → Write to Flash | | If different → send frame |
+-------------------+ +---------------------------+
Currently, this is implemented in addressable LED project. CAN device number change can be done by using Arduino IDE serial monitor or Web Tool. Source code of the web tool can be found in this repository. You could also save that HTML file and use it offline. Only Chrome is supported.
Under this setup, CAN device number can be setted using serial command. This setting will be saved inside ESP32 and will not be overwritten, even if you flushed the firmware. The only way to clear it is use ESPTool to erase flash.
https://randomnerdtutorials.com/esp32-erase-flash-memory/
- Set the device number temporarily (
&CANID SET xx) - Save it permanently to EEPROM (
&CANID SAVE) - Retrieve current, saved, and default IDs (
&CANID GET)
#include <Arduino.h>
#include <EEPROM.h>
// =================== Configuration ===================
#define EEPROM_ADDRESS 64
#define DEFAULT_DEVICE_NUMBER 9 // default fallback ID
#define DEVICE_ID 0x0A // FRC Device Type (fixed)
#define MANUFACTURER_ID 0x08 // FRC Manufacturer ID (fixed)
// Global CAN Device Number
volatile uint8_t g_deviceNumber = DEFAULT_DEVICE_NUMBER;
// =================== EEPROM Functions ===================
void EEPROMReadCANID() {
uint8_t saved = EEPROM.read(0);
g_deviceNumber = (saved <= 63) ? saved : DEFAULT_DEVICE_NUMBER;
}
void EEPROMSaveCANID() {
EEPROM.write(0, (uint8_t)g_deviceNumber);
EEPROM.commit();
}
// =================== Serial CAN ID Helper ===================
void TaskCANIDHelper(void* parameter) {
Serial.println("[CANID] Helper task started. Use &CANID SET xx / SAVE / GET");
while (true) {
if (Serial.available()) {
String line = Serial.readStringUntil('\n');
line.trim();
// --- Set live CAN ID ---
if (line.startsWith("&CANID SET ")) {
int val = line.substring(11).toInt();
if (val >= 0 && val <= 63) {
g_deviceNumber = (uint8_t)val;
Serial.printf("[CANID] Running DEVICE_NUMBER set to %d\n", (int)g_deviceNumber);
} else {
Serial.println("[CANID] Invalid value. Must be 0–63.");
}
}
// --- Save to EEPROM and reboot ---
else if (line.equals("&CANID SAVE")) {
EEPROMSaveCANID();
Serial.println("[CANID] Saved to EEPROM. Rebooting...");
delay(1000);
ESP.restart();
}
// --- Query CAN ID status ---
else if (line.equals("&CANID GET")) {
uint8_t eepromVal = EEPROM.read(0);
Serial.printf("[CANID] Current=%d, EEPROM=%d, Default=%d\n",
(int)g_deviceNumber, (int)eepromVal, (int)DEFAULT_DEVICE_NUMBER);
}
}
// Small delay to avoid tight loop
vTaskDelay(pdMS_TO_TICKS(50));
}
}
// =================== CAN ID Encoding Helper ===================
static inline uint32_t encode_id(uint8_t dt, uint8_t man, uint16_t api, uint8_t dn) {
return ((uint32_t)dt << 24) | ((uint32_t)man << 16) | ((uint32_t)api << 6) | (dn & 0x3F);
}
static inline uint32_t make_can_id(uint16_t api) {
return encode_id(DEVICE_ID, MANUFACTURER_ID, api, (uint8_t)g_deviceNumber);
}
// =================== Setup ===================
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("\n=== ESP32 FRC CAN ID Helper Example ===");
// Initialize EEPROM and load CAN ID
EEPROM.begin(EEPROM_ADDRESS);
EEPROMReadCANID();
Serial.printf("[BOOT] DEVICE_NUMBER=%d\n", (int)g_deviceNumber);
// Start helper task for serial command parsing
xTaskCreatePinnedToCore(TaskCANIDHelper, "TaskCANIDHelper", 4096, nullptr, 1, nullptr, APP_CPU_NUM);
Serial.println("[BOOT] Setup complete. Ready for &CANID commands.");
}
void loop() {
// Nothing here — all logic handled in FreeRTOS task
}When the ESP32 boots, it reads the saved device number from EEPROM:
EEPROM.begin(EEPROM_ADDRESS);
EEPROMReadCANID();If no valid value is found, it defaults to:
#define DEFAULT_DEVICE_NUMBER 9The helper task continuously monitors serial input:
- Reads complete lines using
Serial.readStringUntil('\n') - Matches them against
&CANIDcommands - Updates or saves the ID accordingly
Each valid command prints confirmation via Serial.printf.
When &CANID SAVE is issued:
- The current
g_deviceNumberis written to EEPROM - The ESP32 reboots
- On reboot, the stored value is reloaded and applied globally
Whenever a CAN message is built using make_can_id(), it automatically uses the current live device number:
uint32_t id = make_can_id(0x185); // Example API IDThis allows immediate application of new IDs even before rebooting.
=== ESP32 FRC CAN ID Helper Example ===
[BOOT] DEVICE_NUMBER=9
[BOOT] Setup complete. Ready for &CANID commands.
[CANID] Helper task started. Use &CANID SET xx / SAVE / GET
> &CANID GET
[CANID] Current=9, EEPROM=9, Default=9
> &CANID SET 12
[CANID] Running DEVICE_NUMBER set to 12
> &CANID SAVE
[CANID] Saved to EEPROM. Rebooting...
... reboot ...
[BOOT] DEVICE_NUMBER=12
- Each ESP32 node on the CAN bus must have a unique device number (0–63).
- The EEPROM can wear out after many write cycles; avoid frequent saves.
- Always use
Serial.begin(115200)to match Web Tool baud rate. - The helper task can safely run alongside other FreeRTOS tasks like CAN RX/TX.
- The CAN ID will update live immediately after
&CANID SET, even without reboot. However&CANID SAVEwill trigger a reboot.