Categories
TUTORIALS

Multi-Directional Sequential LEDs with Direction/Gesture Sensor

THE PROGRAM

In this tutorial, we will

1) set up a gesture sensor that can detect to which direction an object is heading and

2) respond with a row of LEDs that will light up in a timed sequence if the object is headed toward it.

This tutorial was developed as a prototype project for smart street lights. I am envisioning these lights can sense when a person is entering a street, then turn the lights on the street one after another — lighting up the way, if you will.

 

project diagram

 

As you can see in the diagram, when the person enters the left street, the sensor will initiate a sequential response for the left-side row of lights, starting from LC (left corner) LED. In three seconds, the L1 (left 1) LED will turn on, then L2 (left 2) LED will turn on three seconds after that. All three lights will stay on for 10 seconds since the LC first turned on, then all lights will turn off. Technically, they will go back to their default setting which is very dim, but not off.

I should make it clear that we are not building a set of smart street lights in this tutorial. There are a few limitations, which will be pointed out throughout the post.

What we will be able to do is to think about the logic of making the directional motion sensor and the real-time light response work together. Then when we have the necessary electrical/technological parts available to actually make the smart street lights, we will have a good place to start. This is also why I may refer to the row of LED lights as “streets” and hand gesture movement as “person entering street” at times throughout this tutorial.

The main takeaways from this tutorial will be:

  • How to set up and use a gesture sensor (APDS9960) with Arduino Uno and
  • How to use millis() to act as a timer to control the lighting sequence.
WHAT YOU NEED

WHY APDS9960 SENSOR? 

We very commonly see PIR sensors being used for Arduino projects that require motion detection. A PIR sensor could achieve some of the functionalities I was going for, but to be able to achieve the direction-sensitive responses I envisioned, APDS9960 seemed to be the way to go.

The main tradeoff for this decision was the detection range. APDS9960 is a lot more limited in its sensing range (Adafruit says about 6″ from the sensor) compared to the ~10-meter range a PIR sensor can work with. Depending on the purpose of your project and where you are installing it, you might want to turn to a PIR sensor instead.

* Adafruit’s APDS9960 sensor can work with both 3.3V and 5V microcontroller (thank you built-in level-shifter!). If for some reason you can’t purchase from Adafruit, SparkFun also has its own APDS9960 RGB + Gesture Sensor (with detection range 4-8″). Please note that SparkFun APDS9960 can only work with a 3.3V microcontroller (like this Arduino Pro 328). If you are working with an Uno (5V), like I am, you will need a level shifter like this one. SparkFun has a great setup guide for its APDS9960 if you want to find out how to do that.

** Another caveat: You can only connect one APDS9960 to an Uno. Without going into much detail, SCL and SDA pins on the breakout board are I2C clock and data pins, which technically can support multiple devices on a single line as long as each device has a unique address. Adafruit’s APDS9960 uses a fixed address 0x39, which cannot be changed. But you should be able to use 2+ Unos to use more than one APDS9960 on one program. For instructions on how to make two Arduino Unos talk to each other, check out this post by Nate Klass.

 

SETTING IT UP

1. Soldering

Your APDS-9960 breakout board will arrive with a small strip of male header pins, so you can solder it onto your breadboard using a soldering iron. There are lots of soldering tutorials on YouTube, but I found this one helpful.

when the breakout board arrives (source: adafruit.com)
soldered onto a mini breadboard

You first prepare the header pins (insert the longer metal legs into the breadboard). It doesn’t matter particularly where on the breadboard you choose to put the breakout board, but do make sure that you will have enough room for wires (i.e. soldering the pins to the bottom row wouldn’t be ideal).  If you are using a half-sized or a full-sized breadboard, this shouldn’t be a big issue. Next, place the breakout board onto the sticking out header pins so that each of them can poke through the power and logic pin holes. Now solder all six pins.

When we have the breakout board securely attached to the breadboard, we can move onto the circuitry.

 

2. Wiring 

First, make sure each of the breakout board’s pin is connected to the right pin ports on Arduino.

  • Connect Vin to 5V power supply.
  • Connect GND to ground.
  • Connect SCL to A5. (This is because for Arduino Uno A5 acts as SCL. If you are using a different microcontroller, check here to find out how you can wire correctly for your board)
  • Connect SDA to A4.  (Same as SCL)

It’s probably a good idea to check if your sensor is working before moving forward. Let’s test it!

Place one LED on the breadboard, then wire as shown below:

Once routing is complete, upload the code below:

You should be able to turn the light on and off by your moving your hand to different directions in front of the sensor. If the LED turns on and off as it should (check the “expected response” section at the top of the code), we can start connecting more LEDs.

Note: If the test code didn’t work as it was supposed to, there could be a couple different reasons for that. First, be careful with the wires covering over the sensor. Remember that this breakout board is sensing the movement by using photodiodes to detect reflected IR energy from the LED. This means that if there is a wire hovering over the sensor, this can interfere with the sensor reading your gesture correctly. Same goes with the LED. If you have the LED placed right next to the sensor, the light beaming out of the LED can also interfere with the sensor. Or possibly you didn’t properly initiate the sensor. The library is designed so that the directional gesture reading functionality is activated AFTER it first detects something with its proximity sensor. You have to put your hand close to the sensor for a couple seconds, then it will start reading your gesture.

Because we are using the total of 6 LEDs, each of which needs to be controlled individually, we need to connect them to separate pin ports. Also, we need to play with the LED light output intensity, so we can only use the PWM (pulse width modulation) pins. These are the digital pin ports with tilde(~) next to their pin number. Here are the pin numbers, to which each LED should be connected:

pin port assignments for each LED

 

Note that only two center LEDs are red and called corner lights. Remember the diagram at the beginning of this tutorial? Like the diagram, the sensor will be placed between those two red LEDs, and depending on the direction the sensor detects, the yellow LEDs will response in sequence (as the street lights would).

A note on using resistors:
Don’t forget to place resistors for each circuit. A LED each only uses up (called forward voltage) about 1.85V out of 5V that each pin port provides, and that’s way too much when we only want the current of 20mA. The ideal resistor for each circuit with an LED is about 158 Ohm, but I am using 330 Ohm resistors because I do not have smaller value resistors available.  Use any resistor you have between 158 and 330 Ohm, but I wouldn’t go much higher than 330.

The completed circuit should look like this:

the complete circuit diagram

 

CODE

There are several things to keep in mind when building a sketch for this. Here are some things we want to achieve in this code:

    • Gesture sensor to tell us where the object is heading to.
    • When the sensor detects a movement to left, we want the LEDs on the left side to turn on one-by-one, light the entire row eventually. Imagine a row of street lights turning on one-by-one, lighting the street ahead of you as you enter the street.
    • We want more intense light level on the side of the street where there are more people. This means, with more movements detected going left, the left-side LED lights will become brighter.
    • We also want the gesture sensor to be constantly detecting motion, so we don’t miss any movements made in front of the sensor. This means we don’t want to use delay functions. Instead, we will be using millis() to keep a timer going so different tasks can be done at different time intervals. This way we don’t have to put the entire brain power of Arduino on hold (like what delays do). (If you went huh? here is a great post by Bill Earl that talks about choosing between delay and millis() in a detailed, easy-to-understand manner. Do check it out!)
    • This also means it could get tricky when we detect a movement to left before the lighting response initiated by the previous movement to the left has fully completed. Think streets again: if there is one person walking down the left-side street, and before the person exits the street, there comes another person entering the street. Now we have two people on the street, so we want the street to be brighter.

We are dealing with two rows of LED sequences (on the left and right), and each row can have up to two response sequences going on at any given time. This can get really messy really fast. It may be helpful to see this image to connect LEDs on breadboard and variables in code.

 

WHEN YOUR ARDUINO WORKS

If everything went as shown here in this post, your Arduino can now do this!

The video was filmed in a dark room to best display the light intensity changes, but it is still somewhat hard to see light level change for the red LEDs. You can still see, though, that the default level of the LEDs is dim (light level 20 out of 255). If the code works correctly, they should never turn completely off. When the hand moved from right to left again, the left-side LEDs one-by-one augmented their light intensity. Also notice we can initiate the sequence for the right-side LEDs before the left-side sequence is completed, which means that our Arduino now can respond immediately to the sensed motion, without waiting.

For the first part of the video, the serial monitor displayed:

More Links to Check Out

*Mentioned above or otherwise

Leave a Reply

Your email address will not be published. Required fields are marked *