Hello everyone, this is my first project here as well as my first intermediate Arduino project. Everything started when I bought the cheap LED strip a while back soon after soon I started getting curious whether I could control it with my computer. That's when I first got introduced to and started working with Arduino.
In this project, I will show you through my full build.
Version 1First, The circuit I begun with was very straight forward. I used Arduino NANO R3 for it's compact size. Then connecting an IR receiver module and the WS2812B LED strip like shown below in Diagram 1.
Now coming to the code, first thing you need collecting the IR code emitted by your remote. That could be done by loading the following code on your Arduino and writing down the hex codes belonging to each button on the remote. You'll need IRremote library installed to preform that.
#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
int type = -1;
int RECV_PIN = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop()
{
if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
irrecv.resume(); // Receive the next value
}
delay(100);
}
Once done with that, We start with main sketch. Here I did struggle a lot it in the beginning. My issue was how to have a running LED light effect and interrupting it at anytime by IR signal reading coming from the remote, or by serial input or Bluetooth which I will discuss later. After a lot of research and understanding the concept explained in Several Things At The Time and applying it in my code. The way I applied it was by making a LED mode function, simply that is an infinite loop function that drives the LEDs in pattern using Adafruit NeoPixel library. Each mode function has two things in common, first is the alternative of delay() function that utilize the "state machine" concept to allow various activities or function to be held or called at same time. Second is the function that accept interrupts. Using that method is how LED strip module works. Bellow is a sample code.
#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <Adafruit_NeoPixel.h>
#define Button0 0xFF6897 // Hex code of button 0
#define PIN 6
#define NUMPIXELS 30 // Number of LEDs used
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define ButtonNum 1 // number of buttons
int RECV_PIN = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;
long int CODES[ButtonNum] = {Button0}; // Array of all the Hex codes
int interval = 100;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
void setup() {
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
findCode();
}
}
void findCode() { // Function that accepts interrupts
if (irrecv.decode(&results)) {
if (exist(results.value, CODES, ButtonNum)) {
LEDMODE(results.value); // calls mode
}
irrecv.resume();
}
}
bool exist(long int compareValue, long int arrayName[], int arraySize) {
irrecv.resume();
for (int x = 0; x < arraySize; x++) {
if (arrayName[x] == compareValue) {
return true;
}
}
return false;
}
void LEDMODE(long int code)
{
irrecv.resume();
switch(code){
case Button0: blinkingstar();
break;
// case ?? : OTHERMODES();
// break;
}
}
void blinkingstar(){
while(true){
currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
for(int x=0;x<(NUMPIXELS/15);x++){
int i = rand() % NUMPIXELS;
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
}
pixels.show();
findCode();
}
pixels.clear();
}
}
In code above demonstrates the concepts I spoke about using one LED mode function. From this point I let my imagination lead by making several other mode functions enough to fit my remote.
Right after that I had everything working the way I wanted, I was not satisfied yet. I wanted a more compact and portable device, soon after I started researching into taking my design from the breadboard to PCB. It was sort of straight forward when it comes to making the connections. I used EasyEDA designer to make the PCB, and fabricated it using JLCpcb fabricating services. The result I ended up with after soldering everything together was like the following.
And to finish it. I design and 3D printed an enclosure, added threaded insert nut and screws to wrap it all up and make it look slightly better.
At this point the module was working fine. I even decided to create a windows remote application using Visual Studio 2019 to control the module via USB cable as an other alternative to control the LED strip module. But since I am not any good in C# the application is not the best, briefly how it work is by connected to desired serial port then sending serial data to the Arduino where it will decode data sent to do certain tasks like changing modes, setting RGB colors and even setting up new buttons from different remotes !
Version2
But still I was not happy, I believed that I could do better. Coming back to my sketch and breadboard, I decided that it should have music responsive modes.
After some more research on how I am going to apply that into my current module. Obviously I needed some sort of a microphone or a sound sensor, so for its low cost and small size the KY-038 Sound Sensor Module was the choice, also added in 3 buttons. So like shown in Diagram bellow show, I connected A0 pin on Arduino to analog pin on sound module, and pin 7, 8, 9 to the push buttons.
Now the fun part, coding. The output from KY-038 Module is a direct microphone signal as voltage value that is altered by the resistance of potentiometer, so what my approach was to get every two consecutive values and find the difference between them, as sound is played around the difference will increase thus it can trigger sound mode functions in different ways. Since the difference of the readings on its own is not suitable in every situation therefore I have added a variable called sensitivity and used two buttons to increase or decrease it. Also to handle all button functions I used ezButton Library.
To run both normal LED modes and sound modes on the Arduino, I had a main mode which is the usual LED modes, and secondary sound modes to alternate between them using a long mode button click (5sec click). Some might ask why don't I alternate them using the remote button instead, eventually that was my first plan, but due to some limitations in interval size for successful IR signal receival is around >75 for successful signal receival. While in sound mode function the interval is below that value, causing the remote to stop working. I found interval of 50ms suitable for sound modes.
int sensorPin = A0;
int Compare[2];
int i = 0;
int SoundInBoosted;
int sensitivity = 1;
int SoundInterval = 50;
bool soundmode = true;
int soundmodecall = 0;
void SoundMode(){
soundmode = true;
while(soundmode){
buttonUp.loop();
buttonDown.loop();
buttonMode.loop();
int inputValue = analogRead(sensorPin);
Compare[i] = inputValue;
i++;
if(i>1) // Finding the difference
{
SoundInBoosted = abs(Compare[0] - Compare[1]) * sensitivity;
SoundModeList(soundmodecall,SoundInBoosted);
i = 0;
}
if(buttonUp.isPressed()){ // Checking for UP button
Serial.println("The button Up is pressed");
if(sensitivity <= 201){
sensitivity += 5;
}
}
if(buttonDown.isPressed()){ // Checking for Down button
Serial.println("The button Down is pressed");
if(sensitivity > 1){
sensitivity -= 5;
}
}
if(buttonMode.isPressed()){ // Checking for Mode button
Serial.println("mode button pressed");
M_button_pressed = millis();
}else if(buttonMode.isReleased()){
M_button_released = millis();
if(M_button_released - M_button_pressed >= 3000) // If button was released
{ // in more than 3 sec return
Serial.println("Go to Remote mode"); // to main mode
soundmode = false;
}else{
if(soundmodecall < 6){ // Else go to next sound mode
soundmodecall++;
}else{
soundmodecall = 0;
}
}
}
delay(SoundInterval);
}
}
void SoundModeList(int count, int soundinput)
{
switch(count){
case 0: LEDSoundResponse_blue(soundinput);
break;
case 1: OTHER MODES(soundinput);
break;
}
}
void LEDSoundResponse_blue(int x){
pixels.clear();
int limit = x / (1000 / NUMPIXELS);
G = 0;
B = 1;
R = 0;
for(int i=0;i<=limit;i++){
if(B>=100){R += 10;}
pixels.setPixelColor(i, pixels.Color(R, G, B));
pixels.show();
B += 8;
}
}
Now modify findCode() function to switch between modes and to accept button interrupts. Also adding new function to shift between normal modes
void findCode() {
buttonMode.loop();
buttonUp.loop();
buttonDown.loop();
if (irrecv.decode(&results)) // look for IR signal
{
if (exist(results.value, CODES, ButtonNum))
{
LEDMODE(results.value); // calls mode
}
irrecv.resume();
}
if(buttonMode.isPressed()){
Serial.println("mode button pressed");
M_button_pressed = millis();
}else if(buttonMode.isReleased()){
M_button_released = millis();
if(M_button_released - M_button_pressed >= 3000){ // If button was released
Serial.println("Go to sound mode"); // in more than 3 sec return
SoundMode(); // to main mode
}else{
if(buttonshift < 1){
buttonshift++;
}else{
buttonshift = 0;
}
ButtonSwitch(buttonshift); // Else go to next LED mode
}
}
if(buttonUp.isPressed()){ // increase interval
if(interval <= 300){
interval += 50;}
}else if(buttonDown.isPressed()){ // decrease interval
if(interval > 50){
interval -= 50;
}
}
}
void ButtonSwitch(int z)
{
switch(z){
case 0: blinkingstar();
break;
// case 1: OTHER MODES();
// break;
}
}
void blinkingstar(){
buttonshift = 0;
while(true){
currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
for(int x=0;x<(NUMPIXELS/15);x++){
int i = rand() % NUMPIXELS;
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
}
pixels.show();
findCode();
}
pixels.clear();
}
}
Once I became happy with the code, I went straight to design the PCBs and fabricate them. Last minute decision was to add female pin header connection to attach HC-05 Bluetooth module for further control options, for example using mobile phone app, also added another female pin header connection to digital pin 11 to allow me to add electronics or sensors for extra features in the future. Finally I designed an enclosure and Printed it to fit the new PCB. Following pictures shows how things were looking at the end.
Now being satisfied with end results, but still room for improvements like.
- Strengthen IR signal, since it is not so good from inside the enclosure.
- Reduce interval required for successful IR signal receival.
- Find a Better way to mount the push buttons to enclosure.
- Write code for Bluetooth control (I have not made it yet) and an application to control it.
- Make it smaller in size.
- Ordinary LED strip for your room
- For your car
- Burglar LED alarm ( turn on a LED effect if sound detect )
- Attach a sensor and code it to do something cool
- Using a bunch them and the right interface, you could make a LED light system
Not the entire code is mine, I had inspiration from all over the internet. Also it is far from prefect since I am kind of new to coding too. I would love helpful criticism, new ideas to Improve it or uses for it, and hopefully someone would benefit from it.
Comments