Cool looking synchronizing firefly demo

Here is a nice little demo that is able to sync up a bunch blinks so they all flash together. They will all be in sync within 20 flashes no matter how they out of phase they are when they start.

Pressing the button on a blink makes it flash immediately, so you can push a bunch of buttons at random times to unsync a bunch of synced blinks and enjoy watching them sync up again. The patterns look surprisingly complex and organic considering how simple the code is.

Improvements and suggestions welcome!

// Simple synchronizing fire fly demo
// Put a bunch of blinks together and they will eventually all sync to flash at the same time.
// Press the button to force a blink to immediately flash.
// Read more here: http://josh.com/ly/Firefly_sync.pdf

// Note that since this very simple demo is built on top of the general purpose
// continuous value sharing communications protocol, there is a relatively slow
// speed of propagation. This means that there may be visually noticeable delay with
// large and spread out constellations of blinks. This delay has an uncanny resemblance 
// to the way the actual fireflies look!

// Consts

// When urge gets to to this value, then we flash and set back to 0

unsigned int URGE_MAX_MS = 1000;


// Variables

// Urge starts at 0 and increases by 1 every every millisecond that passes
// Also increases when we see a neighbor flash

static unsigned urge_ms=0;

// Rememeber what time it was last time we ran loop()
// so we can calculate how many milliseconds passed since then

static unsigned long last_time_ms=0;


// This just increments each time we send a flash. We send this over the IRs so
// neighbors can tell when we have flashed.
// It is not the count that counts, just that it changes each time we flash.

byte flashCountValue = 0;

// Embelish the flash with a soothing fade to black

Timer flash_fade_timer; 


void setup() {
    // put your setup code here, to run once:
}

void loop() {    

    // UI

    if (buttonPressed() ) {

        // Flash immedeately when button pressed

        urge_ms= URGE_MAX_MS;
        
    }

    // Timekeeping

    unsigned diff_ms = millis() - last_time_ms;

    last_time_ms = millis();
    

    // Increment urge
    
    urge_ms += diff_ms;


    // Check for changes (flashes) from neighbors
    
    FOREACH_FACE(f) {

        if (didValueOnFaceChange(f)) {

            // If we see a flash, increment our urge to flash proportional to
            // out current urge. Higher divisors = longer sync times.

            // THIS is where the magic happens.

            urge_ms = urge_ms + (urge_ms/20);
            
        }
        
    }


    // Check if we can not hold it any more
    
    if (urge_ms>=URGE_MAX_MS) {

        // FLASH!!!


        // For simplicity, we will fade out over the next 255ms
        // which happens to look nice and also mean no math is needed
        // to map to the milliseconds left to the brightness
        
        flash_fade_timer.set( 255 );

        urge_ms=0;

        // Signal flash to neighbors

        flashCountValue++;

        if (flashCountValue >= IR_DATA_VALUE_MAX) {
            flashCountValue = 0 ;
        }
        
        setValueSentOnAllFaces( flashCountValue );

    }

    setColor( dim( GREEN , flash_fade_timer.getRemaining() ) );

}
4 Likes

Awesome way to use the API to synchronize timings between blinks… I might have to keep this tabbed.

1 Like


:point_up: seeing this and knowing my game is already at 99% of storage space

2 Likes

Let us know if you want some more eyes looking for ways to trim the code size down.

We’ve learned some tricks over the years, this would be a great place to trade some!

1 Like

that would be awesome if anything jumps out (PR’s welcome):

mainly, I would love to get all the blinks syncing up their flashing on the final victory end state

Really lovely code, thanks for sharing it. I was able to free up 190 bytes with some simple optimizations, and I think there is room to free up more if you need it.

I think this might be interesting to others, so I pick it up in this new thread.

I sent a PR with the changes. LMK if I messed up anything! :slight_smile:

2 Likes