hardware test complete

This commit is contained in:
legop3
2025-11-05 17:31:25 -05:00
parent 6232d5854a
commit 84ddd7e40e
4 changed files with 116 additions and 42 deletions
+1 -1
View File
@@ -11,4 +11,4 @@ on each roomba:
- USB wifi card
- microphone
- speaker
- MAYBE a master relay which can be turned off programatically to save the roomba from discharging
- MAYBE a master relay which can be turned off programatically to save the roomba from discharging. based on battery voltage plus urgent battery #?
+5 -3
View File
@@ -10,6 +10,8 @@ this event will be sent all of the module data at once, in JSON
split each JSON element to the UI element functions
one single system for loading and saving user settings
## esp-server comms
@@ -19,6 +21,6 @@ rover's name
enable / disable for each motor
camera IP address
battery info (for different battery behaviors):
full number
warn number
urgent number
- full number
- warn number
- urgent number
+2 -2
View File
@@ -1,6 +1,6 @@
[env:esp32dev]
[env:esp32s3]
platform = espressif32
board = esp32dev
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
+108 -36
View File
@@ -1,59 +1,131 @@
#include <Arduino.h>
// Use two GPIOs with onboard-friendly defaults; adjust to match your dev kit.
constexpr gpio_num_t LED1_PIN = GPIO_NUM_2; // Often labeled "LED_BUILTIN".
constexpr gpio_num_t LED2_PIN = GPIO_NUM_4;
// --- Hardware mapping -------------------------------------------------------
// Adjust these pins to match how your level shifter connects the ESP32 to the Roomba.
constexpr int ROBO_UART_RX = 16; // ESP32 pin receiving Roomba TX (ROI pin 4).
constexpr int ROBO_UART_TX = 17; // ESP32 pin driving Roomba RX (ROI pin 3).
constexpr gpio_num_t ROBO_BRC_PIN = GPIO_NUM_5; // GPIO pulsing the BRC line (ROI pin 5).
constexpr TickType_t LED1_DELAY = pdMS_TO_TICKS(250); // 4 Hz blink.
constexpr TickType_t LED2_DELAY = pdMS_TO_TICKS(700); // ~1.4 Hz blink.
// FreeRTOS cadences (1 Hz pulse, 150 ms low to ensure Roomba notices).
constexpr TickType_t BRC_PERIOD = pdMS_TO_TICKS(1000);
constexpr TickType_t BRC_LOW_PULSE = pdMS_TO_TICKS(150);
// FreeRTOS tasks must have C linkage-compatible signatures.
void ledTask(void *parameter) {
const gpio_num_t pin = static_cast<gpio_num_t>(reinterpret_cast<intptr_t>(parameter));
const TickType_t delay = (pin == LED1_PIN) ? LED1_DELAY : LED2_DELAY;
// Simple helper to send an Open Interface command over UART.
void sendRoombaCommand(std::initializer_list<uint8_t> bytes) {
Serial1.write(bytes.begin(), bytes.size());
Serial1.flush(); // Ensure command clears the UART FIFO before proceeding.
}
pinMode(pin, OUTPUT);
// Align the first toggle with system tick so the cadence stays consistent.
void brcTask(void * /*parameter*/) {
TickType_t nextWake = xTaskGetTickCount();
uint32_t pulseCount = 0;
bool state = false;
while (true) {
digitalWrite(pin, state ? HIGH : LOW);
state = !state;
// Idle high, pulse low to reset the five-minute sleep timer.
Serial.printf("[BRC] Pulse #%lu: pulling low\n", static_cast<unsigned long>(pulseCount));
gpio_set_level(ROBO_BRC_PIN, 0);
vTaskDelay(BRC_LOW_PULSE);
gpio_set_level(ROBO_BRC_PIN, 1);
Serial.printf("[BRC] Pulse #%lu: released high\n", static_cast<unsigned long>(pulseCount));
pulseCount++;
// vTaskDelayUntil keeps a steady period even if the loop body jitters.
vTaskDelayUntil(&nextWake, delay);
vTaskDelayUntil(&nextWake, BRC_PERIOD);
}
}
void roombaTask(void * /*parameter*/) {
// Give the Roomba a moment after wake-up before issuing commands.
vTaskDelay(pdMS_TO_TICKS(500));
Serial.println("Sending Start (128)...");
sendRoombaCommand({128}); // Start OI -> Passive mode.
vTaskDelay(pdMS_TO_TICKS(100));
Serial.println("Switching to Safe mode (131)...");
sendRoombaCommand({131}); // Safe gives actuator control with failsafes.
vTaskDelay(pdMS_TO_TICKS(100));
Serial.println("Loading a short test song into slot 0 (Song, opcode 140)...");
// Song format: [140][song #][length][note][duration]...
// Duration units are 1/64ths of a second; 32 ≈ 0.5 s.
sendRoombaCommand({140, 0, 1, 69, 32}); // A4 for ~0.5 s.
vTaskDelay(pdMS_TO_TICKS(100));
Serial.println("Playing song 0 (Play, opcode 141)...");
sendRoombaCommand({141, 0});
vTaskDelay(pdMS_TO_TICKS(1500)); // Allow song to finish.
Serial.println("Initial song played. Roomba ready for bumper test.");
// Nothing else to do on this task; park it.
vTaskDelete(nullptr);
}
void sensorTask(void * /*parameter*/) {
constexpr TickType_t pollPeriod = pdMS_TO_TICKS(100); // ~10 Hz polling.
TickType_t nextWake = xTaskGetTickCount();
bool bumperActive = false;
// Allow initialization commands to finish before polling.
vTaskDelay(pdMS_TO_TICKS(1000));
while (true) {
// Request packet 7 (Bumps & Wheel Drops).
sendRoombaCommand({142, 7});
uint8_t packet = 0;
const size_t received = Serial1.readBytes(&packet, 1);
if (received == 1) {
Serial.printf("[Sensor] Packet 7 raw byte: 0x%02X\n", packet);
const bool bumpRight = packet & 0b00000001;
const bool bumpLeft = packet & 0b00000010;
const bool wheelDropRight = packet & 0b00000100;
const bool wheelDropLeft = packet & 0b00001000;
const bool frontBump = bumpLeft || bumpRight;
if (wheelDropLeft || wheelDropRight) {
Serial.printf("[Sensor] Wheel drop detected (L:%d R:%d)\n",
wheelDropLeft, wheelDropRight);
}
if (frontBump && !bumperActive) {
Serial.println("Front bumper hit! Playing song 0.");
sendRoombaCommand({141, 0});
}
if (!frontBump && bumperActive) {
Serial.println("Front bumper released.");
}
bumperActive = frontBump;
} else {
Serial.println("[Sensor] Timed out waiting for packet 7.");
}
vTaskDelayUntil(&nextWake, pollPeriod);
}
}
void setup() {
Serial.begin(115200);
while (!Serial && millis() < 3000) {
// Give USB CDC boards a moment to enumerate; safe to ignore for pure UART boards.
while (!Serial && millis() < 2000) {
delay(10);
}
Serial.println("FreeRTOS dual LED blink demo starting up...");
Serial.println("\nRoomba hardware smoke test starting...");
// The Arduino core already starts the scheduler after setup() returns.
xTaskCreate(
ledTask, // Task function.
"LED1", // Label (shows up in diagnostics).
2048, // Stack size in words.
reinterpret_cast<void *>(static_cast<intptr_t>(LED1_PIN)),
1, // Priority.
nullptr);
// Configure the BRC pin; keep it high (inactive) until the pulse task starts.
pinMode(static_cast<uint8_t>(ROBO_BRC_PIN), OUTPUT);
gpio_set_level(ROBO_BRC_PIN, 1);
xTaskCreate(
ledTask,
"LED2",
2048,
reinterpret_cast<void *>(static_cast<intptr_t>(LED2_PIN)),
1,
nullptr);
// Initialize UART1 for the Roomba Open Interface at its default baud (115200 8N1).
Serial1.begin(115200, SERIAL_8N1, ROBO_UART_RX, ROBO_UART_TX);
Serial1.setTimeout(150); // Enough headroom for sensor replies.
Serial.println("UART1 configured for Roomba at 115200 8N1.");
// Launch the tasks that drive the Roomba and keep it awake.
xTaskCreatePinnedToCore(brcTask, "BrcPulse", 2048, nullptr, 1, nullptr, APP_CPU_NUM);
xTaskCreatePinnedToCore(roombaTask, "RoombaInit", 4096, nullptr, 1, nullptr, APP_CPU_NUM);
xTaskCreatePinnedToCore(sensorTask, "SensorPoll", 4096, nullptr, 1, nullptr, APP_CPU_NUM);
}
void loop() {
// Leave loop() empty; the FreeRTOS tasks do the work.
// Nothing needed here; FreeRTOS tasks run everything.
vTaskDelay(pdMS_TO_TICKS(1000));
}