Build Humphrey the Sharknicorn: a wearable Particle Photon project to track Uber API events

Meet Humphrey the Sharknicorn: a wearable Particle Photon project to track Uber API events. Read on to learn how to build your own.

Charlyn Gonda article author avatarCharlyn GondaSeptember 05, 2018
Build Humphrey the Sharknicorn: a wearable Particle Photon project to track Uber API events

This guide will teach you everything you need to know to build your very own uni-creature wearable that reacts to real-time events from the Uber API. Check out this sweet magical hat zoo that came out of a workshop I taught recently, happily supported by Particle!


It’s a 3D printed unicorn horn on a shark hat that
lights up depending on the state of your Uber ride!

I am a software engineer. Code is my primary means of creating and solving. But I also love working with my hands and creating physical things, like making flowers from felt or folding origami. For the longest time, these were separate skills that I thought were completely unrelated.

And then one day, a coworker gave me a challenge: make a hat light up in response to realtime events from the Uber API. This simple ask launched me into a world I knew nothing about; 3D printing, microcontrollers, circuits, soldering, and more. It also allowed me to discover people in the maker community who are just as excited about taking their code from bits and pixels to circuits and cloth.

So, challenge accepted. This is Humphrey the Sharknicorn, and he’s very happy to meet you!

I was incredibly happy to discover that there has been a lot of effort to really make microcontrollers easy to use, robust, and flexible for makers to create whatever pops out of their imagination. I chose a Particle board to power this project because of how incredibly easy it was to make this device connect to the web — one line of code! This project was inspired by this incredibly well written unicorn hat tutorial from Adafruit, adapted to use the Particle Photon and my own bit of server code that receives events from the Uber API.

I believe that software engineers are chronic problem solvers, and when we learn how to pull our code beyond the screen, we expand our toolset, gain a new perspective on solving challenges and have more ways to inject delight into the everyday.


How to build your own Humphrey

This guide will teach you everything you need to know to build your very own uni-creature that reacts to real-time events. Check out this sweet magical hat zoo that came out of a workshop I taught recently, happily supported by Particle!


No animals or poops were harmed in the making of these hats.

Note: This guide requires some soldering, some basic coding skills, some knowledge about how APIs work, and some appreciation of the silly. Let’s get started.

Step 0: What you’ll need to build your Sharknicorn

Main components:

  • Particle Photon Kit (with breadboard)
  • NeoPixel stick – 8 x 5050 RGB LED with Integrated Drivers
  • Lithium ion battery – 3.7v 2000mAh
  • Resistor – 470 Ohm
  • Unicorn horn
  • Hat (any hat! animal ones work best 😀 )
  • Fiber fill (to keep the lights centered on the horn)

Testing:

  • Male/Male jumper wires
  • Male/Alligator clip jumper wires
  • Switched JST-PH 2-Pin SMT right angle breakout board

Tools:

  • Soldering iron and rosin core solder
  • Safety googles
  • Diagonal flush cutter
  • Wire stripper

Step 0.1: Particle set up

First, you’ll want to make sure that your Particle board is setup. Follow the detailed step-by-step guide on particle.io/start. We’ll be talking about the Particle Photon specifically, but you can use the same firmware code for the Particle Electron as well.


Step 1: Connecting the circuit

You’ll use a switched JST breakout board to control power to the Photon (this just makes testing way easier), and use the VIN and GND pins to power the Photon. With your Photon in the breadboard, make the following connections:

  1. Align the SW pin of the switched breakout board to red power rail and GND to blue ground rail.
  2. Photon VIN to red power rail.
  3. Photon GND to blue ground rail.
  4. (White) alligator clip jumper cable to D5.
  5. (Green) alligator clip jumper cable to blue ground rail.
  6. (Yellow) alligator clip jumper cable to red power rail.
Note: GND is short for ground and VIN is short for voltage in.



Next, prep the Neopixel sticks for connecting. The idea is that we’ll have two Neopixels sticks back to back to light up the entire unicorn horn, and they’ll be connected “in parallel” — this means that they will animate identically to each other since they’ll share the same data wire.


Step 1.1: Preparing the Neopixel Sticks

Because the Neopixel strip only has these pads to connect to, you have to either solder wires or headers to it. It really just depends on how excited you are to see lights.

Speedy version of step 1.1

If you are really excited to see lights, you can use four header pins to connect. Cut off four header pins, see that they align nicely with the pads, then solder them on the shorter side.


Please excuse the haphazard soldering 🙂

Slower version of step 1.1

Alternatively, if you can be a bit patient, you can skip the above step and solder the wires directly instead (you’ll need to do this eventually). Take one Neopixel stick, and for the 5VDC, DIN pad, solder one long wire (to connect to your microcontroller) and one short wire (to connect to the other Neopixel). Then, since there are two GND pads, solder one long wire to one GND pad and solder a shorter one to the other. You’ll get something that looks like the image below.


Step 1.2: Connecting the Neopixel sticks to the microcontroller

You’re now ready to make the connection between the Photon and the Neopixels! Connect the following to each other:

  1. Ground rail alligator clip to the Neopixel stick GND wire.
  2. D5 alligator clip to the Neopixel stick DIN wire.
  3. Power rail alligator clip to the Neopixel stick 5V DC wire.

Then, making sure that your switch is on the OFF position, you can connect your battery using the JST port. Everything should look like this (I used the headers on the Neopixels for this photo so that it’s easy to see — make sure that the clips don’t touch each other!):

Go ahead and turn on the switch. The Photon should light up, but nothing will happen to the Neopixels because you haven’t loaded the firmware yet. Let’s do that now.


Step 2: Loading the firmware and testing

Ok, now it’s time to see some lights! The other great thing about Particle is that you can easily send the firmware wirelessly to your Photon. We’ll first do a simple test to make sure our connections are working. Then, we’ll learn about how to set up different light animations that can be triggered with an API call to Particle.

Go to your web console build.particle.io, copy and paste the code below, make sure you install the Neopixel library for this to work, and flash the firmware to your Photon by clicking the lightning bolt shaped button labeled “Flash”.

// You're probably going to have to delete this include line after copy-pasta'ing
#include <neopixel.h>

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_COUNT 8
#define PIXEL_PIN D5
#define PIXEL_TYPE WS2812B //for rgb stick

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

// a color macro (values are R,G and B)
#define PEACH 200,50,5

void one_blink(int,int,int);

void setup() {
  strip.begin();
  strip.show();
}

void loop() {
  // start with this to test right away
  one_blink(PEACH); //the macro PEACH gets replaced with 200,50,5 when compiled
}

// blink just the first pixel
void one_blink(int R, int G, int B) {
    //first pixel on
    strip.setPixelColor(0, R,G,B);
    delay(500);
    strip.show();

    //first pixel off
    strip.setPixelColor(0, 0,0,0);
    delay(500);
    strip.show();
}

You should now see a blinking light on your Neopixel! The code above has one animation that simply blinks the first pixel in a peach light color. Note that the loop() function actually gets called forever, and the setup() function is called only once in the beginning.

Right now, there’s no way to trigger an animation from the web yet. Let’s add that next.


Step 2.1: Trigger a function through the web

In your setup() function, add this line to expose a function that will be triggered through the web:

// publish a function named changeAnimation to the web
Particle.function("state-change", changeAnimation);

The code above says that you will call a function called changeAnimation when an HTTP POST is made to the URL: https://api.particle.io/v1/devices/DEVICE_ID/state-change. The state-change in the URL is specified in the Particle.function call, and that DEVICE_ID denotes your Photon’s unique Device ID.

Let’s create the changeAnimation function now, it will receive one String variable passed from the args field of the web request, then will set the value global string variable named mode to whatever is string passed and return an int 1.

String mode;

int changeAnimation(String args){
    mode = args;
    return 1; 
}

Now, go back to the loop() function, check the value of the string mode and trigger some animation function based on that string’s value.

void loop() {
    if (mode == "in_progress"){
        rainbow_up();
    } else {
        move_up(0,0,0); //turn off
    }
}

You’ll need to write this rainbow_up() function inside that if statement. First, at the bottom of the file, create a new animation function called move_up() that will create a “moving” effect on the lights, making each pixel at every index light up a specific color:

void move_up(int R, int G, int B) {
    int wait = 25;
    //light up each pixel
    for(int i=0; i < PIXEL_COUNT; i++) {
      strip.setPixelColor(i, R,G,B);
      strip.show();
      delay(wait);
    }
    
    //turn off each pixel
    for(int i=0; i < PIXEL_COUNT; i++) {
      strip.setPixelColor(i, 0,0,0);
      strip.show();
      delay(wait);
    }
}

If you pass 0,0,0 to move_up, it will just set all pixels to black, turning it off (as shown in our loop function). And then, rainbow_up() will just call the move_up() function above for different colors:

void rainbow_up(){
    move_up(PEACH);
    move_up(CYAN);
    move_up(PURPLE);
    move_up(BLUE);
    move_up(WHITE);
    move_up(GREEN);
}

Step 2.2: Test loaded firmware with curl request

Your code should now look like this (remember, you removed the one_blink function because you don’t need it anymore):

#include <array>

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_COUNT 8
#define PIXEL_PIN D5
#define PIXEL_TYPE WS2812B //for rgb stick

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

// a color macro (values are R,G and B)
#define PEACH 200,50,5
#define CYAN 10,150,70
#define PURPLE 180,3,180
#define BLUE 5,5,190
#define WHITE 150,150,150
#define GREEN 10,180,10

String mode = "";

void setup() {
    Particle.function("state-change", changeAnimation);

    strip.begin();
    strip.show();
}

void loop() {
    if (mode == "in_progress"){
        rainbow_up();
    } else {
        move_up(0,0,0); //turn off
    }
}

int changeAnimation(String args){
    mode = args;
    return 1; 
}


void move_up(int R, int G, int B) {
    int wait = 25;
    //light up each pixel
    for(int i=0; i < PIXEL_COUNT; i++) {
      strip.setPixelColor(i, R,G,B);
      strip.show();
      delay(wait);
    }
    
    //turn off each pixel
    for(int i=0; i < PIXEL_COUNT; i++) {
      strip.setPixelColor(i, 0,0,0);
      strip.show();
      delay(wait);
    }
}

void rainbow_up(){
    //create a rainbow animation!
    move_up(PEACH);
    move_up(CYAN);
    move_up(PURPLE);
    move_up(BLUE);
    move_up(WHITE);
    move_up(GREEN);
}

Now turn on the switch on your breadboard. Nothing should happen to your Neopixels when you first turn the switch on. Then, copy and paste this curl request on your terminal, making sure to replace DEVICE_ID and ACCESS_TOKEN with your own.

curl https://api.particle.io/v1/devices/DEVICE_ID/state-change \
             -d access_token=ACCESS_TOKEN \
             -d "args=in_progress"

You should see some beautiful lights scrolling across your Neopixel sticks now. Success!

Head on over to the firmware code in the sharknicorn repo to get a few more light animations built in. You can replace the current code above with the code in the repo. You can read the code and understand what each animation function is doing.


Step 2.3: Solder everything together to make it wearable

I won’t go into detail here, but now that you have your firmware working, right now would be a good time to transfer your circuit into a perma-proto board, solder everything in place, add a switch for turning the entire thing on or off, and then put together your hat!

All this has set us up nicely for the next part: receiving realtime events from the Uber API and changing light animations accordingly.


Step 3: Server setup — Realtime events receiver

Now that you have different light animations that you can trigger with Particle API calls, you can build a server that accepts webhooks from the Uber API, and then triggers these animations based on the status of the Uber ride.

Here’s what the system will look like:

Everytime the state of your ride changes, the Uber API will send a realtime event to your server (highlighted in green) in the form of a webhook. The server will then forward that state to the Photon, which will then react just like it did when you made that curl request. The sharknicorn repo details a step by step guide on how to get your server up and running locally using ngrok, so check that out if you want to try this yourself.


Step 4: Testing it all together!

Now it’s time to test everything end-to-end! Use the Uber Trip Simulator to simulate a real ride; every state change triggers an event and Sharknicorn happily announces what’s happening. Check out this demo video to see it in action.

That’s it! You’ve created a magical uni-creature hat to impress your friends and maybe even your Uber driver and fellow POOLers. You can also make your hat react to other realtime events, such as tweets, the weather, trains arriving, wikipedia edits, or whatever you can dream up and have API access to.

Hope you had fun building this, and more importantly, I hope this post shows you that making things with circuits is not as hard as it may initially seem. There’s so much possibilities for creating something delightful with just a bit of knowledge. Particle made this project easy when I first started and has really given me the courage and motivation to try out more projects. Let’s continue this maker journey together!