How to Use an Ultrasonic Sensor to Control Neopixels With Arduino.
by dlb92 in Circuits > Arduino
5204 Views, 36 Favorites, 0 Comments
How to Use an Ultrasonic Sensor to Control Neopixels With Arduino.
A "basic" showcase and explanation on how to use a Ultrasonic sensor to change the colors on a Neopixel strip.
Supplies
- x1 Arduino UNO R3.
- I use an Elegoo, but using any UNO is okay.
- Any size Breadboard.
- x1 Ultrasonic Sensor
- I use the HR-SR04 with 4 pins (TRIG & ECHO pin).
- 8-count Adafruit Neopixel (WS2812B RGB) strip.*
- x1 Polarized Capacitor.
- x1 330 kΩ (Ohm) Resistor.
- x7 Wires used
- x3 Male to Male wires.
- Use more if needed for prototype if needed.
- x4 Male to Female wires.
- Use more if you need too; use extra M-F wires for your Neopixel wires if needed (like me).
- x3 Male to Male wires.
*I have soldered my Neopixel so I am able to use it in this capacity. Below are the materials I used to solder the Neopixel.
- x1 Soldering Iron
- Spool of solder wire.
- lead, or lead-free solder wire works.
- x1 Red wire
- Active wire.
- x1 Black wire
- Ground wire.
- x1 Yellow wire
- Data wire.
- Any color can work, but make sure you remember which one is the data wire.
- Data wire.
Setting Up the Breadboard, Arduino Uno, & Ultrasonic Sensor
First, refer to the Tinkercad Circuit build above and assemble your breadboard, UNO, ultrasonic sensor, and Neopixel strip appropriately. This digital recreation is as close to the physical layout as I could make it, keeping in mind simplicity, and using appropriate wire colors, types of wires, etc..
Here is a basic run down of what components are present in the screenshot(s) of the circuit:
- Arduino UNO R3.
- Ultrasonic sensor.
- 8-count Neopixel strip.
- Breadboard.
- Polarized Capacitor.
- 330 kΩ (Ohm) Resistor.
- x7 Wires used.*
- Refer back to supplies for what kind of wire used.
On the right is the physical circuit assembled with labeled components.
* I used orange rather than yellow wires for the digital screenshot due to the yellow wires in Tinkercad being difficult to see.
Downloading the Arduino Software
Here is the link to download the Arduino software in order to start coding: https://www.arduino.cc/en/software
After you have downloaded the Arduino IDE, open a new sketch (or new file), and follow the next step for inputting said code.
Disclaimer: most of this code was compiled using, and involving, libraries! Please refer to Arduino's official tutorial on libraries: https://docs.arduino.cc/learn/programming/librarie...
I will be doing a basic implantation of libraries, but if you want the full extent please learn from the best via the amazing people at Arduino.
Finding/Downloading the Code for the Ultrasonic Sensor
**Please download the library for the HC-SR04 here: https://github.com/Martinsos/arduino-lib-hc-sr04 or by accessing the library through the library manager.
To use the Library Manager follow these steps:
- After opening a new sketch, click "Sketch" at the top left of the window.
- If you are on MacOS look at the very top left of your screen given if you have the Arduino sketch selected. To select the window just simply click on it, and search at the top left again.
- Select "Include library..."
- Select "Manage libraries"
- A window will pop-up named "Library Manager."
- Search for "HCSR04" by Martin Sosic
- This library is the most up to date, and measures the distance in centimeters with the Ultrasonic sensor.
- Click "install"
- This will download the HC-SR04 file, located in a file named "libraries."
- Locate the examples folder, and open the "SR04 example" sketch.
- This is where we will find the code we need for using the Ultrasonic sensor to measure distances.
Implementing the HC-SR04 Code, Part 1
By either copy and pasting this from the "SR04_Example.ino" sketch, or by typing this in the global section (the area above the "void setup()" will run the external code from "SR04.h" file that basically does all of the functions needed for the Ultrasonic sensor to operate.
In the "#define TRIG_PIN" & #define ECHO_PIN" please put in a number between 2 and 13 for each, but not the same number for both. These "#define" variables will assign a pin on the UNO R3 that the appropriate wire from the Ultrasonic sensor must go too, i.e., "#define TRIG_PIN 12" must go to pin hole 12 on the UNO R3. The same applies to the ECHO_PIN if you assign a number between 2 through 13, and cannot be 12, then you must put the pin to the number. I used pin 11 for the ECHO_PIN for simplicity sake, and helps keep the wires organized.
Then, you must define/create the global variable of "sr04" so that it may be used later in the code, this creates the "object" that allows for us to call upon the Ultrasonic sensor itself to measure distance, or grabbing numerical values for "if" and "else" statements.
The "long" variable is an extended size variable for number storage, and store 32 bits (4 bytes), from -2,147,483,648 to 2,147,483,647. For the Ultrasonic sensor it could be needed for long distance gathering, or short measurements, opening up numerous applications for this sensor. For us, the "a" is the variable's number simplified and defined into an assigned definition, i.e., "a."
Implementing the HC-SR04 Code, Part 2
Here is the "setup ()" section, where we let the serial monitor shine, by using the function "serial.begin(9600);" to let the Ultrasonic sensor output the measurements it's receiving into the IDE's (the coding software we are using) serial monitor. The serial monitor is a place to test, take from, put, and read code that you are testing. For us, we are taking the outputted distance measurements in centimeters and plugging them later into the Neopixel.
The (9600) refers to the bits per second (BPS) that initializes with the serial monitor, allowing for us to receive information quickly; however, we can intentionally delay how fast the monitor updates through the "delay ()" function. Effectively allowing us to read, record, or monitor what we assigned the "serial.begin()" too.
Implementing the HC-SR04 Code, Part 3
In this section we are in "void loop()" which, as the greyed-out comment says it loops whatever code you implement forever. Referencing the SR04_Example.ino code once more, we will put the aforementioned global variables to use in "loop()."
Using the "a" variable, the sr04 object, and the ".Distance" function we can combine these ingredients together in "a=sr04.Distance();." Effectively allowing us to find the distance with the Ultrasonic sensor, and use "serial.print(a)" to fill the serial monitor with the recorded distances picked up from the Ultrasonic sensor. As well as making sure we print each line with ("cm") for detail intended purposes.
With "a=sr04.Distance();" we can find an average number, or a "setpoint" that we can use to control when the Neopixel to change colors, cycle, color-wipe, or flash when this setpoint is reached.
Next, we will be exploring the coding for the Neopixel, and changing the color of the strip.
Finding/Plugging in Adafruit's Neopixel
Repeating nearly verbatim Step 3, plugging in the Neopixel library from the Library Manager, we will be setting up the global variables as well as the setup() and loop() variables.
The necessary library can be found through the Library Manager under the name, "Adafruit_Neopixel" by Adafruit.
For better ease of access, the GitHub for both ".ino" files we will be pulling from are here: https://github.com/adafruit/Adafruit_NeoPixel/tree... and https://github.com/adafruit/Adafruit_NeoPixel/tree...
The first link is to the "simple.ino" sketch that hold much of the necessary components to make the Neopixel light up, and the second link holds a specific "for()" variable that will allow the Neopixel to change to whatever color(s) we want.
Implementing the Neopixel Code, Part 1
**Foreword: this code is being put into the global region of our code, I forgot to mention that in the passage below, along with our "sr04" global variables.**
From before we know that "#include" called upon an external file, downloaded with the examples, that our code will be running from. We also remember that "#define" is being used to classify the PIN that the Neopixel will be using to receive output data from the Ultrasonic sensor. Allowing us to tell the Neopixel what to do whenever the data reaches a desirable threshold to change the color of the strip. The next "#define," named NUMPIXELS, declares how many Neopixles we have in a strip that we want to turn on, off, or change the color/brightness. Since our small strip has 8 Neopixels, we declare that the NUMPIXELS is 8. As well we #define(d) our PIN on the UNO R3 to be pin hole 6. Our last #define value is the DELAYVAL, and as the grey comment describes, determines the time (in milliseconds) to pause between pixels.
Lastly, describing the "Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);," we are effectively defining, organizing, and assigning these variables in the command "Adafruit_NeoPixel" with the value "pixels" being assigned to said variables.
Implementing the Neopixel Code, Part 2
This one line of code is situated in the "void setup()" were, as the comment says, initializes the Neopixel strip in use. Allowing it to light up the strip before any changes are applied.
Implementing the Neopixel Code, Part 3
Housed in the "void loop()" section of our code is the "pixels.clear()" function that starts at the loop right after declaring step 6's code. The .clear function is constantly being run, because without it we would not have the ability to change the color of the strip as quickly as we need it too. Thus, we continuously clear the strip until we need it to change colors, clearing again once the color change is no longer needed.
Implementing the Neopixel Code, Part 4
Arguably the largest section of our code since it contains the most vital parts of the color changing process, and has a lot of parts to breakdown for this "basic" guide.
For the sake of simplicity, please read the comments pertaining to certain lines of code, as I will be covering what is not described via comments.
First, we classify what our "setpoint" condition is for our Neopixel to change to a bright red color. Although, if this "if" condition is not met, then the color of the strip continues to stay a bright white.
The "pixels.setPixelColor" is what defines what color is sent to the strip, and as a new function the "pixels.show" sends the updated color to the Neopixel strip.
And the variable "delay (DELAYVAL)" is using the global variable DELAYVAL to set the delay values as explained in step 8.
The "for()" condition, and the variables housed inside of it's parentheses, are the backbone to the pixels changing in the first place. As the "int = i" is being declared as the integer "i" and being assigned to the value 0. Thus "int i=0." The integer "i" is given the task to command the strip as we see fit as long as it is WITHIN it's "for()" statement. Since "i" now controls how many pixels are being displayed we can tell "i" to increase or decrease how many pixels change color and is active once the "if()" or "else()" statement is active. However, since we are also telling it to increase with "i++". Therefor, the "i<NUMPIXELS" is the catalyst for this growth upwards from the first pixel "0" to whatever NUMPIXELS's value is defined as (for us it is 8). In short, this "for()" statement facilitates the necessary means for us to change the color once the "for()" condition is met or not; by rapidly changing the pixels color once the switch is activated or deactivated. Almost like an "on and off" switch that changes the color of your lights rather than turning them off.
Implementing the Neopixel Code, Part 5
Coming off from the last part, this final bit of code is the cherry on the top, as it allows us to wipe the color from the strip so that a new color can be displayed.
Although this small bit of code is only called upon once, see step 11 (part 4), everything has already been covered except for what is contained within the parentheses, and a new type of integer that is being used specifically within this fraction of code. The "uint#_t" is intresting to me as "uint32_t" that is being used, is a numeric type that guarantees 32 bits. Same goes for the "uint16_t" and "uint8_t," sharing the same type that guarantees their allotted amount of bits for what it is being used for in the function itself.
The "void colorWipe()" is pulled from the Neopixel library, titled as "strandtest.ino," underneath the color wheel function within said example sketch. We've seen "colorwipe" be used before, but is not the only way to wipe color from the strip; however, we must use it in this sense as it provides the previous block of code with the necessary function in order to wipe the color from the strip.
Completed Product & Video
Sources & Code Referenced/Used:
Adafruit Circuit Playground, by Adafruit: https://github.com/adafruit/Adafruit_CircuitPlayg...
Adafruit Neopixel, by Adafruit: https://github.com/adafruit/Adafruit_NeoPixel
HC-SR04, updated by Martin Sosic: https://github.com/Martinsos/arduino-lib-hc-sr04 This library is written by Phil "Paint Your Dragon" Burgess for Adafruit Industries, with contributions by PJRC, Michael Miller and other members of the open source community.
Adafruit’s Neopixel Simple.ino sketch: https://github.com/adafruit/Adafruit_NeoPixel/tree...
Adafruit’s Neopixel strandTest.ino sketch: https://github.com/adafruit/Adafruit_NeoPixel/tree...