Creating coordinated Christmas light displays with mesh networking

Now that Particle’s third generation of devices have shipped, developers all over the world are unboxing, claiming and playing with their new Argons, Borons, and Xenons. And while there are thousands of things one can build with these new devices (like robot friends, or dog food monitoring systems), I’ve been working on a few projects designed to test and show off the mesh networking capabilities unique to the third generation hardware. In this post, I’ll introduce a new API for low-latency mesh network messaging and show how it can be used to create coordinated holiday light animations.

Introducing Mesh Pub/Sub for local network messaging

All of new mesh-ready devices have the ability to participate in a local mesh network with other devices. Each device is assigned an IPv6 address local to the network, and can communicate with other devices on the local mesh network via UDP.

And while it’s possible to implement UDP messaging yourself, Particle provides the ability to send multicast messages between devices on a local network via the Mesh.publish and Mesh.subscribe methods in the Particle Device OS firmware. These methods are similar to Particle.publish and Particle.subscribe, but instead of communicating through the Particle Device Cloud, Mesh Pub/Sub is for local network messaging only. Local-only messaging is a powerful capability that works regardless of the network’s connection to the outside world.

It’s also very fast. I wanted to see just how fast, so I decided to create a test project using Mesh pub/sub to play coordinated light animations across several devices. And, since it’s mid-December, it’s only fitting that those lights would be wrapped around mini-Christmas trees and set to holiday music!

Setting up the Meshmas Tree hardware

My hardware setup is simple, with five total third generation devices, though you could accomplish the same result with as few as three. My specific setup includes:

  • (1x) Particle Mesh network with an Argon as a gateway.
  • (1x) Particle Xenon connected to the PartiBadge (more on that below). This is solely so I can use the built-in piezo buzzer and menu user-interface (UI). You could breadboard a piezo and Xenon as well.
  • (3x) Particle Xenons connected to Neopixel strips.
  • (3x) 12-inch artificial Christmas trees I purchased online.

All five of the Particle devices are on the same mesh network. This is critical for Mesh pub/sub to operate correctly.

Writing the firmware

On the firmware side, there are two key pieces to this demo, the music player/message publisher, and the message subscriber/light controller.

For the music player, I modified the source code for the Particle PartiBadge that we provided to Spectra attendees earlier this year. The PartiBadge includes a piezo and menu UI for exploring device features, so it was easy to add new commands for playing festive holiday songs.

For the holiday songs themselves, I borrowed code from Particle’s 2017 Christmas Tree project. Specifically, I pulled the xmassongs.h file into the PartiBadge source and modified each song to perform a Mesh.publish each time a note is played. Here’s what it looks like for one of the songs:

void playWeWishYouAMerryXmas()
{
  int noteCount = NOTE_COUNT_WEWISHYOUAMERRYXMAS;

  for (int i = 0; i < noteCount * 3; i += 3)
  {
    if (changeSong)
      return;

    Mesh.publish("tone", String(notes_weWishYouAMerryXmas[i]));
    tone(BUZZER_PIN, notes_weWishYouAMerryXmas[i], notes_weWishYouAMerryXmas[i + 1]);
    delay(notes_weWishYouAMerryXmas[i + 2]);
    Mesh.publish("no-tone", NULL);
  }
}

Before a note is played on the Piezo, the code sends a publish message called tone that all of the devices on the local mesh network receive. Because the network is so fast, there is almost no perceptible delay between the audible tone and the blinking. Then, after the delay between notes, the code publishes another message, this time with a no-tone string. This is all that’s needed to mesh-enable my music player!

Next up, I need to subscribe to the messages from the player and light up my neopixel strips. I have the exact same firmware running on all three of my Xenons, and you can view the complete sketch here. The critical piece is in the setup() function, where I’m using Mesh.subscribe to set-up listeners for the “tone” and “no-tone” messages:

void setup()
{
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show();

  Mesh.subscribe("tone", playTone);
  Mesh.subscribe("no-tone", stopTone);
}

The playTone handler sets a lightUp boolean to true and the red, green and blue values to a random integer between 1 and 255. The stopTone handler flips the lightUp boolean back to false.

void playTone(const char *event, const char *data)
{
  lightUp = true;

  redValue = random(1, 256);
  greenValue = random(1, 256);
  blueValue = random(1, 256);
}

void stopTone(const char *event, const char *data)
{
  lightUp = false;
}

Finally, in the loop() function, I check the lightUp boolean and, if false, set the red, green and blue values to 0 to turn them off, before calling the setAllPixels function, which sets each pixel on the neopixel strip to the current red, green or blue value.

void loop()
{
  if (!lightUp)
  {
    redValue = 0;
    greenValue = 0;
    blueValue = 0;
  }

  setAllPixels();
}

void setAllPixels()
{
  for (int i = 0; i < strip.numPixels(); i++)
  {
    strip.setPixelColor(i, redValue, greenValue, blueValue);
  }
  strip.show();
}

The end result is a pleasing, coordinated light show powered by a Particle Mesh network!

To the naked eye, it sure looks to be pretty well synchronized to me! And while the latency of mesh pub/sub will vary based on distance between devices on the network and the general RF conditions you’re operating that network in, it’s pretty cool to see this new messaging API operate so seamlessly out of the box!

Now it’s your turn!¬†What can you do this holiday season to explore the power of Particle Mesh and your new devices? Be sure to let us know on the comments, or post your #ParticlePowered mesh-enabled holiday projects to Twitter, Facebook and Instagram and tag us!

Author Bio

Brandon Satrom is the Developer Evangelist for Particle. An unabashed lover of the web, mobile and an avid tinkerer, Brandon loves to talk about sensors and circuits, microcontrollers, open source, robots and whatever new shiny tool or technology has distracted him from that other thing he was working on. Brandon has spoken at national, international and online events, and is the author of four books. He lives in Austin, TX with his wife, Sarah, and three sons, Benjamin, Jack and Matthew.