Back to engineering archive

Record 046 / Firmware and control

Motion triggered light and sound prop

Hall-armed prop firmware that uses tilt input to request sound and sequence blue, white-fade and off states across 12 addressable LEDs.

Firmware development
Motion inputLightingAudio control

Firmware flow

Applying one sound-and-light effect burst

Selected fireBurst() routine from an inspected firmware variant. Arming and the tilt/cooldown gate are handled outside this routine.

The routine ignores requests when disarmed or empty. Otherwise it requests one audio track, fades up to three remaining pixels in sequence and records the completion time. It disarms, requests audio sleep and clears the strip only when every configured pixel has been used.

The diagram describes one selected source variant and its command order. Blocking fades, audio playback timing and physical prop behavior were not tested; the routine does not establish one burst per distinct gesture.

Read the implementation

Selected firmware excerpts. The diagram explains the code; it is not a hardware test.

One effect burst and exhaustion handling

void fireBurst() {
  if (!armed || birdsUsed >= NUM_LEDS) return;

  playSafe(TRK_SHOT);

  // Turn off 3 LEDs one-by-one with white fade
  for (uint8_t k=0; k<SHOT_GROUP_SIZE && birdsUsed<NUM_LEDS; k++) {
    whiteFadeOutOne(birdsUsed);   // sequential effect
    birdsUsed++;
  }

  lastTiltTime = millis();

  if (birdsUsed >= NUM_LEDS) {
    armed = false;
    df.sleep();          // next arm will df.reset()
    allOff();
  }
}

Blue, off and single-pixel white-fade helpers

void showAllBlue() {
  for (uint8_t i=0; i<NUM_LEDS; i++) strip.setPixelColor(i, strip.Color(0,0,255));
  strip.show();
}

void allOff() {
  strip.clear();
  strip.show();
}

void whiteFadeOutOne(uint8_t idx) {
  // flash white quickly, then fade to off
  strip.setPixelColor(idx, strip.Color(255,255,255));
  strip.show();
  delay(25);
  for (int b=255; b>=0; b-=18) {                   // fade steps ~15 frames
    strip.setPixelColor(idx, strip.Color(b, b, b));
    strip.show();                                  // interrupts briefly disabled
    delay(14);
  }
  strip.setPixelColor(idx, 0);
  strip.show();
}
ResultReturn without starting an effect
ActionRequest the effect audio track
ActionFade up to three remaining LEDs in sequenceEach call flashes one pixel white, fades it to off and then advances the used-pixel count. Stop at the group limit or when no LEDs remain.
ActionDisarm, request audio sleep and clear the LEDs
ResultReturn to the main loop

Technical notes

Arming and tilt input

The selected variant resets the audio module, restores all 12 LEDs to blue and requests the startup track when armed. Its tilt routine accepts a closing edge or a sustained LOW state, with a cooldown check before another effect burst.

A three-pixel effect sequence

Each accepted burst requests one audio track and processes up to three remaining LEDs in sequence. A helper flashes each selected pixel white, fades it down and explicitly turns it off before the used-pixel count advances.

Finishing the sequence

After every configured LED has been used, the routine disarms, requests audio-module sleep and clears the strip. The fades use blocking delays. This source review establishes command order, without verifying physical playback timing, wake behavior or one burst per distinct gesture.

Engineering archiveArchive record

Project enquiries

Discuss your project.

Tell us what you’re developing and where you need engineering support.

Discuss your project