diff --git a/analog_system_monitor_arduino/analog_system_monitor_arduino.ino b/analog_system_monitor_arduino/analog_system_monitor_arduino.ino index 530d11d..2bf40dd 100644 --- a/analog_system_monitor_arduino/analog_system_monitor_arduino.ino +++ b/analog_system_monitor_arduino/analog_system_monitor_arduino.ino @@ -122,13 +122,21 @@ unsigned long lastPacketTime = 0; const unsigned long watchdogTimeout = 5000; // 5 seconds unsigned long lastFadeTime = 0; +// ------------------------------- +// Animation tuning +// ------------------------------- +const float FADE_IN_FACTOR = 0.999f; // boot-up 0 → 100% +const float FADE_OUT_FACTOR = 0.999f; // watchdog 100% → 0 +const unsigned long FADE_INTERVAL = 1; // ms between fade steps + // ------------------------------- // Connection state machine // ------------------------------- enum ConnectionState { - STATE_DISCONNECTED, // fade to zero - STATE_CONNECTING, // fade in 0 → 100% - STATE_CONNECTED // normal UDP-driven slew + STATE_DISCONNECTED, // fade to zero + STATE_CONNECTING, // fade in 0 → 100% + STATE_WAIT_FOR_FIRST_PACKET, // hold at 100%, wait for first UDP + STATE_CONNECTED // normal UDP-driven slew }; ConnectionState connectionState = STATE_DISCONNECTED; @@ -543,8 +551,8 @@ void loop() { if (idx == NUM_CHANNELS) { - // First valid packet after being disconnected → start CONNECTING if (connectionState == STATE_DISCONNECTED) { + // First valid packet after being disconnected → start CONNECTING Serial.println("STATE CHANGE: DISCONNECTED → CONNECTING (UDP connection established)"); connectionState = STATE_CONNECTING; @@ -562,6 +570,38 @@ void loop() { // Ignore UDP values during fade-in, just keep watchdog alive lastPacketTime = millis(); } + else if (connectionState == STATE_WAIT_FOR_FIRST_PACKET) { + // First real packet after fade-in completes + Serial.println("STATE CHANGE: WAIT_FOR_FIRST_PACKET → CONNECTED (first UDP packet received)"); + + for (int ch = 0; ch < NUM_CHANNELS; ch++) { + if (!overrideActive[ch]) { + targetDuty[ch] = values[ch]; + slewStartDuty[ch] = currentDuty[ch]; // currently ~100% + } + } + + slewStartTime = millis(); + lastPacketTime = millis(); + connectionState = STATE_CONNECTED; + + // Debug output + Serial.println("Received UDP packet (first after fade-in):"); + for (int i = 0; i < NUM_CHANNELS; i++) { + Serial.print(" CH"); + Serial.print(i); + Serial.print(" ("); + Serial.print(channelLabels[i]); + Serial.print("): "); + Serial.print(values[i], 2); + if (channelUnits[i][0] != '\0') { + Serial.print(" "); + Serial.print(channelUnits[i]); + } + Serial.println(); + } + Serial.println(); + } else if (connectionState == STATE_CONNECTED) { // Normal UDP-driven update for (int ch = 0; ch < NUM_CHANNELS; ch++) { @@ -631,10 +671,7 @@ void loop() { } // Fade-in animation: 0 → 100% on all non-override channels - const unsigned long fadeInterval = 1; - const float fadeInFactor = 0.999f; // fast at start, slow near 100% - - if (now - lastFadeTime >= fadeInterval) { + if (now - lastFadeTime >= FADE_INTERVAL) { lastFadeTime = now; bool allReached = true; @@ -644,7 +681,7 @@ void loop() { float cd = currentDuty[ch]; // Exponential approach to 100% - cd = cd * fadeInFactor + 100.0f * (1.0f - fadeInFactor); + cd = cd * FADE_IN_FACTOR + 100.0f * (1.0f - FADE_IN_FACTOR); currentDuty[ch] = cd; float calibratedDuty = applyCalibration(ch, cd); @@ -659,30 +696,27 @@ void loop() { } if (allReached) { - Serial.println("STATE CHANGE: CONNECTING → CONNECTED (fade-in complete)"); - // Initialize slew baseline from currentDuty - for (int ch = 0; ch < NUM_CHANNELS; ch++) { - slewStartDuty[ch] = currentDuty[ch]; - } - slewStartTime = millis(); - connectionState = STATE_CONNECTED; + Serial.println("STATE CHANGE: CONNECTING → STATE_WAIT_FOR_FIRST_PACKET (fade-in complete)"); + connectionState = STATE_WAIT_FOR_FIRST_PACKET; } } } break; + case STATE_WAIT_FOR_FIRST_PACKET: { + // Hold at ~100%, do nothing until first UDP packet arrives + // (handled in UDP parsing above) + } break; + case STATE_DISCONNECTED: { // Watchdog fade-to-zero (always active in this state) - const unsigned long fadeInterval = 1; - - if (now - lastFadeTime >= fadeInterval) { + if (now - lastFadeTime >= FADE_INTERVAL) { lastFadeTime = now; for (int ch = 0; ch < NUM_CHANNELS; ch++) { if (currentDuty[ch] > 0.0f) { - const float fadeFactor = 0.999f; - currentDuty[ch] *= fadeFactor; + currentDuty[ch] *= FADE_OUT_FACTOR; if (currentDuty[ch] < 0.01f) currentDuty[ch] = 0.0f;