Adding Bluetooth control for WS2812B animation

Hello and greetings everyone.
For a project of mine, I’ve been using the WS2812B RGB LEDs and the Fastled library. As far as the effect I want to play on the LEDs goes, I have got it to work, with a lot of references of course. I would like to control this effect via Bluetooth (I use the HC06 Bluetooth module). I understand the basics of controlling the WS2812B using Bluetooth, that is turning on and off a single color, but to play an effect, I am unsure of how to do it. My code would be as follows:

#include “FastLED.h”
#define NUM_LEDS 5
#define DATA_PIN 2

// Define the array of leds
CRGB leds[NUM_LEDS];

void setup() {

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

}

void IndicatorSweep() {

leds[0] = CRGB(0,0,255);
FastLED.show();
delay(250);

leds[4] = CRGB(255,255,255);
FastLED.show();
delay(250);

leds[3] = CRGB(255,255,255);
FastLED.show();
delay(250);

leds[2] = CRGB(255,255,255);
FastLED.show();
delay(250);

leds[1] = CRGB(255,255,255);
FastLED.show();
delay(250);

FastLED.clear();
delay(200);
}

void loop() {
IndicatorSweep();
}

I really hope to receive some assistance on where to add the necessary code to run this effect using Bluetooth. I truly apologize if I may be asking too much but I could seriously use some help on this. Finally, thank you all for taking the time to read this and helping me out.

Also, credits to the author of this thread and everyone that have contributed t it:

I got a lot of help from there.

Hanee786: I understand the basics of controlling the WS2812B using Bluetooth, that is turning on and off a single color, but to play an effect, I am unsure of how to do it.

Then you really don't understand. The bluetooth does NOT control the leds. The Arduino controls the leds. The bluetooth just gets some data into or out of the Arduino.

You have to get the two things separated and it becomes easier. Learn to write code to read from your bluetooth and parse the strings you receive. You already know how to play your animations. Once you know how to receive some string from the bluetooth, then it is just a matter of setting up if statements to compare what you receive and see which animation you want to run. You get to define the entire protocol.

Have a look at Robin2's Serial Input Basics thread. I believe it has an example of executing functions in response to commands over serial. Your bluetooth is basically communicating to the Arduino over serial. But that doesn't matter, the techniques in that thread would apply to anything giving data to the Arduino one character at a time like that.

It's useful to know, too, just what is sending data to the bluetooth device, and how much control over that application/device you have.

Sending '1' to make the Arduino execute effect number 1, one time, is far different from sending "Play effect #1" or sending instructions that define just what effect #1 does.

Also, your loop() function, where you will read the data from the bluetooth device currently does nothing but call IndicatorSweep(), which takes in excess of 1.45 seconds to execute.

If you write other effects that block like that one does, don't expect any data sent to the bluetooth device to be reacted to in a timely fashion.

Thanks to getting back on the topic. After further understanding, I did create a new code to play that effect using my HC06 Bluetooth module. The code is verified by the Arduino IDE and is uploaded but when I send the signal using my app, the LEDs do not light up. I hope someone would be able to look at this code and assist me in modifying it to make it work.

#include <SoftwareSerial.h>
#include <Adafruit_NeoPixel.h>
#include "FastLED.h"
FASTLED_USING_NAMESPACE
SoftwareSerial BT(10, 11);
#define PIXEL_PIN    2    
#define PIXEL_COUNT 5
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

bool IndicatorSweepOld = LOW;
int showType = 0;
CRGB leds[PIXEL_COUNT];

void setup() {
  
   BT.begin(9600);
    BT.println("Hello from Arduino");
  strip.begin();
  strip.show();
}

char a;
void loop() {
   bool IndicatorSweep = LOW;
  bool ende;
if (BT.available())
   {
    a= (char)BT.read();
    if(a=='t')
    {
      IndicatorSweep = HIGH;
      
    }else{
          IndicatorSweep = LOW;
  
    }
   }
if (IndicatorSweep == LOW && IndicatorSweepOld == HIGH) {
    delay(20);
   
    
    if (IndicatorSweep == LOW) {
       showType = 9;
       
     
      startShow(showType);
    }
  }
IndicatorSweepOld = IndicatorSweep;
}

void startShow(int i) {
  switch(i){
  case 9: IndicatorSweep ();
            break;
  }
}

void IndicatorSweep() { 
      
  leds[0] = CRGB(0,0,255);
  FastLED.show();
  delay(250);
  
  leds[4] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  leds[3] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  leds[2] = CRGB(255,255,255);
  FastLED.show();
  delay(250); 

  leds[1] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  FastLED.clear();
  delay(200);
}

Why are you using SoftwareSerial to get data from the bluetooth device? You are NOT using Serial to debug your program. Why not is a real mystery, because debugging by guesswork is the worst possible way to debug anything.

if (IndicatorSweep == LOW && IndicatorSweepOld == HIGH) {
    delay(20);
   
   
    if (IndicatorSweep == LOW) {

Is there some reason to believe that, while you have your head buried in the sand, the value in IndicatorSweep will somehow change?

Is IndicatorSweep a variable that you haven't declared, or is it a function?

Well as far as the code for the indicatorsweep goes, I simply tried to merge two sets of codes together. So firstly, there is this code that I found on Instructables that is used to play the WS2812B LEDS with effects such as Red, Blue, Green, Rainbow and RGB.

Then there is the code for the effect that I want my LED strip to run, which is the one about the Indicatorsweep. However I do not know how to implement the Bluetooth function into the code. I’d just like to know how to merge the two sets of codes I’ve left below or simply add the necessary lines of code into the indicatorsweep code to implement the Bluetooth function to it so I can make my LED strip play this effect. I really hope someone could help with the coding for this issue.

The YouTube video in the link below shows what the LED strip does based on the first set of code I’ve left below.

First set of code - Bluetooth controlled LED strip

#include <SoftwareSerial.h>
#include <Adafruit_NeoPixel.h>

SoftwareSerial BT(10, 11);

#define PIXEL_PIN    2    

#define PIXEL_COUNT 5
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
bool RotOld = LOW;
bool GreenOld = LOW;
bool BlueOld = LOW;
bool offOld = LOW;
bool rainOld = LOW;
bool rgbOld = LOW;
int showType = 0;



void setup() {
  
   BT.begin(9600);
    BT.println("Hello from Arduino");
  strip.begin();
  strip.show();
}
char a;
void loop() {
  bool off = LOW;
  bool Blue = LOW;
  bool Rot = LOW;
  bool Green = LOW;
  bool rain = LOW;
  bool rgb = LOW;
  bool ende;
   if (BT.available())
   {
    a= (char)BT.read();

    if(a=='o')
    {
      off = HIGH;

    }else{
          off = LOW;
  
    }
    if(a=='b')
    {
      Blue = HIGH;
       
    }else{
          Blue = LOW;
  
    }

if(a=='r')
    {
      Rot = HIGH;
      
    }else{
          Rot = LOW;
  
    }

if(a=='g')
    {
      Green = HIGH;
      
    }else{
          Green = LOW;
  
    }
    if(a=='a')
    {
      rain = HIGH;
      
    }else{
          rain = LOW;
  
    }
     if(a=='m')
    {
      rgb = HIGH;
      
    }else{
          rgb = LOW;
  
    }
}
  
  if (off == LOW && offOld == HIGH) {
    delay(20);
   
    
    if (off == LOW) {
       showType = 0  ;
     
      startShow(showType);
    }
  }
  if (Blue == LOW && BlueOld == HIGH) {
    delay(20);
   
    
    if (Blue == LOW) {
       showType = 3  ;
     
      startShow(showType);
    }
  }
  if (Rot == LOW && RotOld == HIGH) {
    delay(20);
   
    
    if (Rot == LOW) {
       showType = 1  ;
     
      startShow(showType);
    }
  }
  if (Green == LOW && GreenOld == HIGH) {
    delay(20);
   
    
    if (Green == LOW) {
       showType = 2  ;
     
      startShow(showType);
    }
  }
    if (rain == LOW && rainOld == HIGH) {
    delay(20);
   
    
    if (rain == LOW) {
showType = 8;
      startShow(showType);
    }
  }
      if (rgb == LOW && rgbOld == HIGH) {
    delay(20);
   
    
    if (rgb == LOW) {
   showType = 7;
     rgb = HIGH;

      startShow(showType);
    }
  }


RotOld = Rot;
  BlueOld = Blue;
GreenOld = Green;
  offOld = off;
  rainOld = rain;
  rgbOld = rgb;
}

void startShow(int i) {
  switch(i){
    case 0: colorWipe(strip.Color(0, 0, 0), 50);    // Black/off
            break;
    case 1: colorWipe(strip.Color(255, 0, 0), 50);  // Red
            break;
    case 2: colorWipe(strip.Color(0, 255, 0), 50);  // Green
            break;
    case 3: colorWipe(strip.Color(0, 0, 255), 50);  // Blue
            break;
    case 7: colorWipe(strip.Color(255, 255, 255), 50);
            colorWipe(strip.Color(255, 255, 255), 50);  // Green
            colorWipe(strip.Color(255, 255, 255), 50);  // Blue
            colorWipe(strip.Color(0, 0, 0), 20);
            colorWipe(strip.Color(0, 0, 0), 20);  // Green
            colorWipe(strip.Color(0, 0, 0), 20);  // Blue
            colorWipe(strip.Color(255, 255, 255), 50);
            colorWipe(strip.Color(255, 255, 255), 50);  // Green
            colorWipe(strip.Color(255, 255, 255), 50);  // Blue
            theaterChase(strip.Color(  127,   127, 127), 50); // Blue
            theaterChase(strip.Color(127,   127,   127), 50); // Red
            theaterChase(strip.Color(127,   127,   127), 50); // Red
            colorWipe(strip.Color(255, 255, 255), 50);
            colorWipe(strip.Color(255, 255, 255), 50);  // Green
            colorWipe(strip.Color(255, 255, 255), 50);  // Blue
            colorWipe(strip.Color(0, 0, 0), 20);
            colorWipe(strip.Color(0, 0, 0), 20);  // Green
            colorWipe(strip.Color(0, 0, 0), 20);  // Blue
            colorWipe(strip.Color(255, 255, 255), 50);
            colorWipe(strip.Color(255, 255, 255), 50);  // Green
            colorWipe(strip.Color(255, 255, 255), 50);  // Blue
            theaterChase(strip.Color(  127,   127, 127), 50); // Blue
            theaterChase(strip.Color(127,   127,   127), 50); // Red
            theaterChase(strip.Color(127,   127,   127), 50); // Red
            colorWipe(strip.Color(255, 0, 0), 50);
            colorWipe(strip.Color(255, 255, 255), 50);
            colorWipe(strip.Color(255, 255, 255), 50);  // Green
            colorWipe(strip.Color(255, 255, 255), 50);  // Blue
            colorWipe(strip.Color(0, 0, 0), 20);
            colorWipe(strip.Color(0, 0, 0), 20);  // Green
            colorWipe(strip.Color(0, 0, 0), 20);  // Blue
            colorWipe(strip.Color(255, 255, 255), 50);
            colorWipe(strip.Color(255, 255, 255), 50);  // Green
            colorWipe(strip.Color(255, 255, 255), 50);  // Blue
            theaterChase(strip.Color(  127,   127, 127), 50); // Blue
            theaterChase(strip.Color(127,   127,   127), 50); // Red
            theaterChase(strip.Color(127,   127,   127), 50); // Red
            
            break;
    case 8: rainbowCycle(20);
            break;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Second set of code - the effect I want to play on my LED strip via Bluetooth

#include "FastLED.h"
// How many leds in your strip?
#define NUM_LEDS 5
// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 2
// Define the array of leds
CRGB leds[NUM_LEDS];

void setup() { 
       FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);     
}

void IndicatorSweep() { 
      
  leds[0] = CRGB(0,0,255);
  FastLED.show();
  delay(250);
  
  leds[4] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  leds[3] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  leds[2] = CRGB(255,255,255);
  FastLED.show();
  delay(250); 

  leds[1] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  FastLED.clear();
  delay(200);
}

void loop() {
 IndicatorSweep();
}
#include <Adafruit_NeoPixel.h>
#include "FastLED.h"
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

Will those libraries work together?

That first code is far more complicated that it needs to be. If you send an 'a', you should call a function to do whatever that means. That function should manage ALL the LEDs. Ditto if you send a 'b', a 'c', or any other letter.

I really don't understand what you are try to accomplish with the bluetooth device and one effect that repeats over and over.

Lets say that you want to send 'a' and make something happen. Just EXACTLY what should happen? Should that effect be executed ONCE? Should that effect be executed over and over? If the latter, what's the point of sending something, regardless of what it is, to the Arduino?

PaulS: That first code is far more complicated that it needs to be. If you send an 'a', you should call a function to do whatever that means. That function should manage ALL the LEDs. Ditto if you send a 'b', a 'c', or any other letter.

I really don't understand what you are try to accomplish with the bluetooth device and one effect that repeats over and over.

Lets say that you want to send 'a' and make something happen. Just EXACTLY what should happen? Should that effect be executed ONCE? Should that effect be executed over and over? If the latter, what's the point of sending something, regardless of what it is, to the Arduino?

Okay then, point taken. Regarding what I want to achieve with this: Use the Arduino and Bluetooth module (HC06) to play the 'Trail' effect on my LED strip. The effect should play over and over again. I've left a YouTube link that'll show you the effect I am trying to achieve.

https://www.youtube.com/watch?v=eRZ6RkpnoqE&feature=youtu.be

I want to use my Android device to send a command, the alphabet "s" for example and be able to play this effect. To create the communication between my Android device and Arduino, I'd need the Bluetooth module. As for the Android app, I've got it under control but I don't know how to modify my code to make my LED strip compatible with the Bluetooth module.

I truly apologize if for any type of inconvenience I would've caused but I truly hope for some assistance in the part of the coding to make my LED strip play the effect I'm wanting it too. Once again, thank you all so much for getting back to me.

I want to use my Android device to send a command, the alphabet "s" for example and be able to play this effect. To create the communication between my Android device and Arduino, I'd need the Bluetooth module. As for the Android app, I've got it under control but I don't know how to modify my code to make my LED strip compatible with the Bluetooth module.

So, nothing should happen until you send 's'? When the 's' arrives, run the effect forever?

bool runEffect = false;

void loop()
{
   if(BT.available() > 0)
   {
      char c = BT.read();
      if(c == 's')
         runEffect = true;
   }

   if(runEffect)
   {
      IndicatorSweep();
   }
}

PaulS:
So, nothing should happen until you send ‘s’? When the ‘s’ arrives, run the effect forever?

Yes and yes. Also, thank you so much for the code you sent.
So, I tried the code and this is the final code I came up of:

#include <SoftwareSerial.h>
#include "FastLED.h"

SoftwareSerial BT(10, 11);

#define DATA_PIN    2    

#define NUM_LEDS 5
CRGB leds[NUM_LEDS];
bool runEffect = false;

void loop()
{
   if(BT.available() > 0)
   {
      char c = BT.read();
      if(c == 's')
         runEffect = true;
   }

   if(runEffect)
   {
      IndicatorSweep();
   }
}
void setup() { 
       FastLED.addLeds<WS2812B, DATA_PIN>(leds, NUM_LEDS);     
}


void IndicatorSweep() { 
      
  leds[0] = CRGB(0,0,255);
  FastLED.show();
  delay(250);
  
  leds[4] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  leds[3] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  leds[2] = CRGB(255,255,255);
  FastLED.show();
  delay(250); 

  leds[1] = CRGB(255,255,255);
  FastLED.show();
  delay(250);
  
  FastLED.clear();
  delay(200);
}

However, the LED strip does not play the effect when I send the command ‘s’. I am thinking there is something wrong with the parts I added into the code. I hope you could look into and assisst me in where I went wrong.
Thank you!

However, the LED strip does not play the effect when I send the command 's'.

You created an instance of the SoftwareSerial class, but you never call begin() in that instance, so it, effectively, doesn't exist, and, therefore, can't actually receive data.

PaulS: but you never call begin() in that instance, so it, effectively, doesn't exist, and, therefore, can't actually receive data.

Alright. I implemented that and it works great now.Thank you so so much for your time and effort. It is highly appreciated and has brought the best for me. Once again, thank you so much.

Would someone mind posting his code with the updated begin() for those of us who are a little more challenged?

iceflare42: Would someone mind posting his code with the updated begin() for those of us who are a little more challenged?

You mean that you can't figure out how to add

   whateverYourSoftwareSerialInstanceNameIs.begin(whatevreSpeedYouNeed);

to setup()?

Can now :D . I have issues with syntax and figuring out what is name sensitive and what is just calling your naming scheme. That's why this is just a hobby for me.