@@ -258,6 +258,93 @@ bool setupTWAI() {
258258 return true ;
259259}
260260
261+ /* *
262+ * Send an LED control sequence to the ESC
263+ * @param ledData Array of packed LED entries (use SineEsc::makeLedControlEntry)
264+ * @param ledNum Number of entries (max 10)
265+ */
266+ void setESCLedControl (const uint16_t *ledData, uint8_t ledNum) {
267+ if (!escTwaiInitialized) return ;
268+ esc.setLedControl (ledData, ledNum);
269+ }
270+
271+ /* *
272+ * Send a motor beep sequence to the ESC
273+ * @param beepData Raw byte array of 3-byte entries (tone, duration_10ms, volume)
274+ * @param beepDataLen Length of beepData in bytes (entries * 3)
275+ * @param beepNum Number of beep entries
276+ */
277+ void setESCMotorSound (const uint8_t *beepData, uint8_t beepDataLen, uint8_t beepNum) {
278+ if (!escTwaiInitialized) return ;
279+ esc.setMotorSound (beepData, beepDataLen, beepNum);
280+ }
281+
282+ // Helper to pack a beep entry into 3 bytes in a buffer
283+ // tone: 0-9, duration: in 10ms units, volume: 0-100
284+ static void packBeepEntry (uint8_t *buf, uint8_t tone, uint8_t duration10ms, uint8_t volume) {
285+ buf[0 ] = tone;
286+ buf[1 ] = duration10ms;
287+ buf[2 ] = volume;
288+ }
289+
290+ /* *
291+ * Play ascending arm beep on ESC motor (matches hand controller: C7 -> E7)
292+ * Uses two tones at 100ms each, ascending pitch
293+ */
294+ void escMotorBeepArm () {
295+ uint8_t beepData[6 ];
296+ packBeepEntry (&beepData[0 ], 3 , 10 , 50 ); // lower tone, 100ms, 50% vol
297+ packBeepEntry (&beepData[3 ], 6 , 10 , 50 ); // higher tone, 100ms, 50% vol
298+ setESCMotorSound (beepData, 6 , 2 );
299+ USBSerial.println (" ESC: arm beep sent" );
300+ }
301+
302+ /* *
303+ * Play descending disarm beep on ESC motor (matches hand controller: E7 -> C7)
304+ * Uses two tones at 100ms each, descending pitch
305+ */
306+ void escMotorBeepDisarm () {
307+ uint8_t beepData[6 ];
308+ packBeepEntry (&beepData[0 ], 6 , 10 , 50 ); // higher tone, 100ms, 50% vol
309+ packBeepEntry (&beepData[3 ], 3 , 10 , 50 ); // lower tone, 100ms, 50% vol
310+ setESCMotorSound (beepData, 6 , 2 );
311+ USBSerial.println (" ESC: disarm beep sent" );
312+ }
313+
314+ // FreeRTOS task: aviation strobe pattern
315+ // Quick red pulse, quick green pulse, then off for ~1.5s, repeat
316+ static void escLedStrobeTask (void *pvParameters) {
317+ // Wait for ESC connection before starting
318+ vTaskDelay (pdMS_TO_TICKS (3000 ));
319+
320+ const uint16_t pattern[] = {
321+ SineEsc::makeLedControlEntry (SineEsc::LED_RED, 1 ), // red flash 50ms
322+ SineEsc::makeLedControlEntry (SineEsc::LED_OFF, 2 ), // gap 100ms
323+ SineEsc::makeLedControlEntry (SineEsc::LED_GREEN, 1 ), // green flash 50ms
324+ SineEsc::makeLedControlEntry (SineEsc::LED_OFF, 30 ), // off 1500ms
325+ };
326+
327+ USBSerial.println (" ESC LED aviation strobe started" );
328+
329+ for (;;) {
330+ setESCLedControl (pattern, 4 );
331+ USBSerial.println (" ESC LED: sent aviation strobe" );
332+ // Wait for full cycle (50 + 100 + 50 + 1500 = 1700ms) before resending
333+ vTaskDelay (pdMS_TO_TICKS (1700 ));
334+ }
335+ }
336+
337+ static TaskHandle_t escLedStrobeTaskHandle = NULL ;
338+
339+ /* *
340+ * Start the ESC LED strobe test pattern
341+ * Creates a FreeRTOS task that repeatedly sends the strobe sequence
342+ */
343+ void startESCLedStrobeTest () {
344+ if (escLedStrobeTaskHandle != NULL ) return ; // already running
345+ xTaskCreate (escLedStrobeTask, " ESCLedTest" , 2048 , NULL , 1 , &escLedStrobeTaskHandle);
346+ }
347+
261348/* *
262349 * Debug function to dump ESC throttle response data to serial
263350 * @param res Pointer to the throttle response structure from ESC
0 commit comments