@@ -59,8 +59,10 @@ LoadComms loadComms;
5959// SyncedClock netClock(adapterESPNow); // todo
6060
6161Adafruit_NeoPixel leds (1 , UM_PROS3 ::LED_DATA_PIN , NEO_GRB + NEO_KHZ800 );
62- MCP23008T loadDevice (static_cast <MCP23008T ::I2C_ADDRESS >(LOAD ::I2C_ADDRESS ),
63- &Wire);
62+ MCP23008T
63+ loadDevice (static_cast <MCP23008T ::I2C_ADDRESS >(LOAD ::I2C_ADDRESS ),
64+ &Wire); // AI: Does not protect against invalid addresses, but
65+ // will fail to initialize if address is not valid`
6466bool loadConfigured = false ;
6567
6668LoadContainer load (loadDevice, loadComms);
@@ -79,12 +81,18 @@ bool configureLoad() {
7981 ESP_LOGE (TAG , " Failed to initialize INA260 power sensor at 0x%02X" ,
8082 PSENSOR ::I2C_ADDRESS );
8183 return false ;
84+ } else {
85+ ESP_LOGI (TAG , " INA260 power sensor init at 0x%02X" ,
86+ PSENSOR ::I2C_ADDRESS );
8287 }
8388
8489 if (!loadDevice.begin ()) {
8590 ESP_LOGE (TAG , " Failed to initialize MCP23008T device at 0x%02X" ,
8691 loadDevice.getAddress ());
8792 return false ;
93+ } else {
94+ ESP_LOGI (TAG , " MCP23008T IO device init at 0x%02X" ,
95+ loadDevice.getAddress ());
8896 }
8997
9098 // First six pins outputs, made last two inputs as that's the default
@@ -159,6 +167,16 @@ void setup() {
159167
160168 // Configure ESTOP pin
161169 pinMode (UM_PROS3 ::ESTOP_PIN , INPUT_PULLUP );
170+ attachInterrupt (
171+ digitalPinToInterrupt (UM_PROS3 ::ESTOP_PIN ),
172+ []() {
173+ // Note: This ISR is not guaranteed to trigger on every ESTOP press,
174+ // but that's acceptable as the main safety check is in the FSM
175+ // task, and this is just a backup. Also, we want to avoid doing too
176+ // much in the ISR to prevent potential issues.
177+ load.updateSafetyFlag ();
178+ },
179+ CHANGE );
162180
163181 // Configure New ESP-NOW + WiFI implementation
164182
@@ -296,6 +314,9 @@ void setup() {
296314 taskDesc->stackSize_bytes );
297315 }
298316 }
317+ vTaskResume (load.tFSM .pxHandle );
318+ // vTaskResume(load.tPoll.pxHandle); // TODO: Verify that this isn't
319+ // needed
299320 tasksSetup = true ;
300321
301322 // pitchPIDController.enable(
@@ -335,6 +356,8 @@ void setup() {
335356[[noreturn]] void
336357vTaskUpdateFSM ([[maybe_unused]] void *pvParameters) { // NOSONAR
337358 while (true ) {
359+ static TickType_t xLastWakeTime = xTaskGetTickCount ();
360+
338361 LoadFSM::UPDATE_RESULT result = loadFSM.updateState ();
339362 if (result == LoadFSM::UPDATE_RESULT ::STATE_CHANGED ) {
340363 ESP_LOGI (TAG , " FSM State Changed: %d" , loadFSM.getCurrentState ());
@@ -344,7 +367,12 @@ vTaskUpdateFSM([[maybe_unused]] void *pvParameters) { // NOSONAR
344367 } else {
345368 // No change, nothing to log
346369 }
347- delay (RUN ::TASK_INTERVALS ::TI_FSM_mS);
370+
371+ BaseType_t xWasDelayed = xTaskDelayUntil (
372+ &xLastWakeTime, pdMS_TO_TICKS (RUN ::TASK_INTERVALS ::TI_FSM_mS));
373+ if (xWasDelayed != pdTRUE) {
374+ ESP_LOGE (TAG , " Timing not met!" );
375+ }
348376 }
349377}
350378
@@ -354,16 +382,28 @@ vTaskUpdateFSM([[maybe_unused]] void *pvParameters) { // NOSONAR
354382[[noreturn]] void
355383vTaskPollSensors ([[maybe_unused]] void *pvParameters) { // NOSONAR
356384 while (true ) {
385+ static TickType_t xLastWakeTime = xTaskGetTickCount ();
386+
387+ // load.updateSafetyFlag(); // Moved to interrupts before noticing that
388+ // the backoff was the problem, might as well leave it that way
389+
357390 static uint32_t backoffFactor =
358391 RUN ::TASK_INTERVALS ::FAIL_BACKOFF_BASE_FACTOR ;
392+ uint32_t delay_ms = 0 ;
359393 if (INA260::updateReadings ()) {
360394 backoffFactor = RUN ::TASK_INTERVALS ::FAIL_BACKOFF_BASE_FACTOR ;
361- delay ( RUN ::TASK_INTERVALS ::TI_POLL_SENSORS_mS) ;
395+ delay_ms = RUN ::TASK_INTERVALS ::TI_POLL_SENSORS_mS;
362396 } else {
363397 // Logging already handled
364- delay ( RUN ::TASK_INTERVALS ::TI_POLL_SENSORS_mS * backoffFactor) ;
398+ delay_ms = RUN ::TASK_INTERVALS ::TI_POLL_SENSORS_mS * backoffFactor;
365399 backoffFactor *= RUN ::TASK_INTERVALS ::FAIL_BACKOFF_MULTIPLIER ;
366400 }
401+
402+ BaseType_t xWasDelayed =
403+ xTaskDelayUntil (&xLastWakeTime, pdMS_TO_TICKS (delay_ms));
404+ if (xWasDelayed != pdTRUE) {
405+ ESP_LOGE (TAG , " Timing not met!" );
406+ }
367407 }
368408}
369409
@@ -402,17 +442,18 @@ vTaskRecvData([[maybe_unused]] void *pvParameters) { // NOSONAR
402442 static TickType_t xLastWakeTime = xTaskGetTickCount ();
403443
404444 NacellePacket packet;
405- if (xQueueReceive (LoadComms::priorityDataQueue, &packet, 0 ) == pdPASS) {
445+ if (xQueueReceive (LoadComms::priorityDataQueue, &packet,
446+ RUN ::TASK_INTERVALS ::TI_RECV_ms) == pdPASS) {
406447 ESP_LOGV (TAG , " Received packet: rpm=%u" , packet.rpm );
407448 load.setRPM (packet.rpm );
408449 load.setAngularAccel_RPMPS (packet.angularAccel_RPMPS );
409450 }
410451
411- BaseType_t xWasDelayed = xTaskDelayUntil (
412- &xLastWakeTime, pdMS_TO_TICKS (RUN ::TASK_INTERVALS ::TI_RECV_ms));
413- if (xWasDelayed != pdTRUE) {
414- ESP_LOGE (TAG , " Timing not met!" );
415- }
452+ // BaseType_t xWasDelayed = xTaskDelayUntil(
453+ // &xLastWakeTime, pdMS_TO_TICKS(RUN::TASK_INTERVALS::TI_RECV_ms));
454+ // if (xWasDelayed != pdTRUE) {
455+ // ESP_LOGE(TAG, "Timing not met!");
456+ // }
416457
417458 // Never need to suspend on the load
418459 }
0 commit comments