How to make certain LED in a LED strip to blink?

Hi,

I am now controlling a series of WS2812B through daisy chain. Every single led in the daisy chain can lights up following the color i need. However, I need to make them blink. How to do that? Anyone can please advise? Below is my current code.

#include <CytronWiFiShield.h>
#include <CytronWiFiServer.h>
#include <SoftwareSerial.h>
#define WiFi wifi
#include <SPI.h>
#include <string.h>
#include <stdio.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif

char ssid[] = "TDE Office"; //  your network SSID (name) 
char pass[] = "tde257a698n";
int keyIndex = 0;            // your network key Index number (needed only for WEP)
ESP8266Server server(23);
boolean alreadyConnected = false; // whether or not the client was connected previously
boolean status = false;
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
//PIN is the pin number that control the first batch of LEDs
#define PIN            13
//PIN2 is the pin numver that control the second batch of LEDs
#define PIN2           12
// How many NeoPixels are attached to the Arduino?
//NUMPIXELS is the total number of LEDs
#define NUMPIXELS      10
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
int delayval = 50; // delay for half a second


void setup() {
   Serial.begin(9600);
   while (!Serial) {
    ;
   }
    if (!WiFi.begin(2, 3)) {
    Serial.println("WiFi shield not present");
    while (true);       // don't continue
  }

  String fv = WiFi.firmwareVersion();
  Serial.println(fv);

  // attempt to connect to Wifi network:
  while (!status) {
    
  Serial.print("Attempting to connect to Network named: ");
  Serial.println(ssid);                   // print the network name (SSID);
    
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
  status = WiFi.connectAP(ssid, pass);
  }
  server.begin();                           // start the web server on port 80
  printWifiStatus();                        // you're connected now, so print out the status
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code
  pixels.begin(); // This initializes the NeoPixel library.
  pixels2.begin();
}


void loop() {
  // wait for a new client:
  ESP8266Client client = server.available();

  // when the client sends the first byte, say hello:
  if (client) {
    
//    if (!alreadyConnected) {
//      // clead out the input buffer:
//      client.flush();    
//      Serial.println("We have a new client!");
//      alreadyConnected = true;
//    } 

    if (client.available() > 0) {
      // read the bytes incoming from the client:
      String incomingBytes = client.readString();
      //change the charBuf number according to the total number to LEDs
      char charBuf[10];
      incomingBytes.toCharArray(charBuf, NUMPIXELS);
      for (int j=0; j<NUMPIXELS; j++) {
      charBuf[j]=incomingBytes[j];

    for (int j=0; j<4; j++) {
    Serial.print(charBuf[j]);

        if (charBuf[j] == 'R') {
        pixels.setPixelColor(j, pixels.Color(50,0,0)); 
        }
     
          else if (charBuf[j] == 'G') {
          pixels.setPixelColor(j, pixels.Color(0,50,0));    
          }

          else if (charBuf[j] == 'B') {
          pixels.setPixelColor(j, pixels.Color(0,50,50));    
          }

          else if (charBuf[j] == 'W') {
          pixels.setPixelColor(j, pixels.Color(50,50,0));  
          }

          else if (charBuf[j] == 'O') {
          pixels.setPixelColor(j, pixels.Color(0,0,0));  
          }
    }
//change the j to the starting number of second batch LEDs
    for (int j=4; j<NUMPIXELS; j++) {
    Serial.print(charBuf[j]);

        if (charBuf[j] == 'R') {
        pixels2.setPixelColor(j-4, pixels2.Color(10,0,0)); 
        }
    
          else if (charBuf[j] == 'G') {
          pixels2.setPixelColor(j-4, pixels2.Color(0,10,0));    
          }

          else if (charBuf[j] == 'B') {
          pixels2.setPixelColor(j-4, pixels2.Color(0,0,10));    
          }

          else if (charBuf[j] == 'W') {
          pixels2.setPixelColor(j-4, pixels2.Color(10,10,10));  
          }

          else if (charBuf[j] == 'O') {
          pixels2.setPixelColor(j-4, pixels2.Color(0,0,0));  
          }
    }
    
    pixels.show(); // This sends the updated pixel color to the hardware.
    pixels2.show(); 
    delay(delayval); // Delay for a period of time (in milliseconds).
//    client.flush();
    alreadyConnected = false;
    client.stop();       
   }
  }
 }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
[\code]

I need to make them blink. How to do that?

Keep changing the values in the buffer and sending it out at regular intervals. Simple as that.

Grumpy_Mike:
Keep changing the values in the buffer and sending it out at regular intervals. Simple as that.

Hi Mike,

Thanks for your reply.
Is there any other way? I am sending out the values through LabVIEW via telnet. Keep changing the values in buffer making the process slow down.
I would like to make it blink once i send out the value.
I see many examples out there to making a LED strips to blink. However, there is no example showing how to make selective LED in strips to blink.
Thanks.

There is no other way.

But if your code is too slow, that is because it is inefficient. It uses delay() which wastes processing time. It uses show() too frequently when data arrives to change several pixels at the same time.

Use millis() to ensure you do not update the strip too often, and don't need to use delay().

Do the two strips always show the same pattern as each other? If so, wire them to the same pin and change your code to update only one strip.

I am sending out the values through LabVIEW via telnet.

To what? Directly to the strip or to an Arduino?

If the latter then have the Arduino store the information in a buffer and modify & resend the data from the Arduino.

If you are not using an Arduino then why are you posting in an Arduino forum?

PaulRB:
There is no other way.

But if your code is too slow, that is because it is inefficient. It uses delay() which wastes processing time. It uses show() too frequently when data arrives to change several pixels at the same time.

Use millis() to ensure you do not update the strip too often, and don't need to use delay().

Do the two strips always show the same pattern as each other? If so, wire them to the same pin and change your code to update only one strip.

Hi PaulRB,

Thanks for your advice. I am only using one strip. And i am controlling every single LEDs in a strip by sending a command to assign color to each of them.

For example, i have 4 LEDs in a strip, i want to make the first blue and the rest all red, i have to send "BRRR" from my LabVIEW through telnet to my Arduino, which will then control all LEDs with theirs own color respectively.

Now i want to make all the 4 LEDs blinks. I do not know how to do that. I can constantly send command "BRRR" to on and "OOOO" to off LEDs but that was too troublesome since i am not directly send my command to Arduino through serial or what. I am sending my command to Arduino using LabVIEW. I hope you can understand what i am trying to explain. Thank you.

Grumpy_Mike:
To what? Directly to the strip or to an Arduino?

If the latter then have the Arduino store the information in a buffer and modify & resend the data from the Arduino.

If you are not using an Arduino then why are you posting in an Arduino forum?

Hi Mike,

I am sorry if i making you misunderstand my meaning.
I am controlling my LED strip using Arduino. Arduino will control the color of every LED in the strip based on the command it received. For example, I have 4 LEDs in a strip, i want to make the first red, second green, third blue and last white. I will send a command of "RGBW" to Arduino. I am not directly sending the command to Arduino via serial or what, i am sending the command to Arduino using LabVIEW. There is nothing to worry aboout the LabVIEW since it is just a media like serial. I am doing so is because my Arduino is attached to a WIFI module.

I have no problem in this area. I can control my LEDs well.
But now i want to make each WS2812B LEDs blinking with their own color. I cannot do that. I know i can constantly sending "RGBW" to make them on and "OOOO" to make them off continuously until i want to stop. However, i believe there are easier ways out there.

Hopefully i am making myself clear. I really hope that i can get some advice or suggestion here on how to make my LEDs BLINK. Thanks

As I said before "then have the Arduino store the information in a buffer and modify & resend the data from the Arduino".

However, i believe there are easier ways out there.

Is it just that you feel there should be a better way? Basically as PaulRB and myself have pointed out there is no easier way than sending the data for all the LEDs again with the changes. This is because you can not access individual LEDs in a WS2812B chain. That is the clue it is a chain.

Sending from Lab View is slow so send from the Arduino.

negotxj:
I am only using one strip.

According to your code, you have two strips, each 10 leds long, attached to pins 12 and 13. If that is not true, it may be a reason why your code is slow.

negotxj:
I hope you can understand what i am trying to explain.

I think I do understand. But how will you control if the leds flash or do not flash? Will you send different codes from LabView for flashing red versus steady red?

Grumpy_Mike:
Sending from Lab View is slow so send from the Arduino.

Hi Mike,

I am clearly understand what did you mean.

There is one thing i need to clarify. I am sending out my command from LabVIEW to Arduino. Then Arduino will control the LED strip. I cannot direct send command from Arduino to control the LED strip. This is because i have a wifi shield attached to the Arduino Uno. I have to send command to Arduino through wifi in order to control my LEDs.

Thank you.

PaulRB:
According to your code, you have two strips, each 10 leds long, attached to pins 12 and 13. If that is not true, it may be a reason why your code is slow.
I think I do understand. But how will you control if the leds flash or do not flash? Will you send different codes from LabView for flashing red versus steady red?

Hi PaulRB,

For question 1:
Yes in my code there are two pins used. But in reality i am just using only one strip for testing.
I might use two pins to control two strips in future.

For question 2:
That's what i am now struggling. I want my LEDs to flash.
I have to modified my Arduino sketch so that, when i send a command to Arduino, my Arduino receive the command, it will automatically make the LED strips attached to it to blink.

For now, i send "RGBO" to make all 4 LEDs in my strips to be turned on in red, green, blue and no color in sequence.

But i wish it to be like, when i send "RGBO", all the 4 LEDs will flash in red, green, blue and no color in sequence. That's what i want. But sadly i can't figure out on how to do that.

Thank you.

Something like THIS ?

Running fine here and if you stop at a number in the loop you can make it flash that one maybe.

I did not look at your code but how about making use of uppercase and lowercase?

Uppercase could e.g. indicate on and lowercase could indicate blink. The arduino will store the received command and next act accordingly on every iteration of loop. You only have to send the command once.

If you have a blink rate of e.g 1 Hz (500ms on, 500ms off) for all your leds, it should be easy to update all leds every 500ms using a millis() based timing. If you need one led to blink at 1 Hz and another one a 2 Hz or 3 Hz or not blink in sync, it will get a bit trickier.

OK, let me summarise what you are now saying you want to do. The Arduino receives a string such as "RBOGB". It changes all leds in the strip to red. After a delay it changes all the leds to blue. After another delay, all leds off. After another delay, all leds green. After another delay, all leds blue. After another delay, all leds back to red as the seqience restarts and so on, until another string is received?

This is because you can not access individual LEDs in a WS2812B chain. That is the clue it is a chain.

But... but... they are individually addressable LEDs!!! Everyone says so!

If you want them to blink, save the sequence that labview sends in.
Send that to the strip.
After your on-time, have the Arduino send the all-off sequence.
After your off-time, have the Arduino send the original sequence.
Repeat.
After every send to the LED strip, check to see if a new labview sequence was received.

boolrules:
But... but... they are individually addressable LEDs!!! Everyone says so!

Sure they are individually addressable but you have to send the all data for the whole chain all in one go. You can not send data to just one LED. If you think you can then you have misunderstood what "everyone" is saying.

PaulRB:
OK, let me summarise what you are now saying you want to do. The Arduino receives a string such as "RBOGB". It changes all leds in the strip to red. After a delay it changes all the leds to blue. After another delay, all leds off. After another delay, all leds green. After another delay, all leds blue. After another delay, all leds back to red as the seqience restarts and so on, until another string is received?

Hi PaulRB,

It wasn't like that.

When it receive RBOGB, first led turn red, second turn blue, third no on, forth turn green and last turn blue, all at the same time without any delay.

If u see my code, i control the color of every led in the strip individually.

Now i just want to let them blink but not on without blinking.

sterretje:
I did not look at your code but how about making use of uppercase and lowercase?

Uppercase could e.g. indicate on and lowercase could indicate blink. The arduino will store the received command and next act accordingly on every iteration of loop. You only have to send the command once.

If you have a blink rate of e.g 1 Hz (500ms on, 500ms off) for all your leds, it should be easy to update all leds every 500ms using a millis() based timing. If you need one led to blink at 1 Hz and another one a 2 Hz or 3 Hz or not blink in sync, it will get a bit trickier.

Hi sterretje,

I am using UPPERCASE to control my leds. However, that doesn't matter.

My problem now is, i don't want my led on only. I want them blink. I am controlling each led in the strip by sending a string to Arduino.

Sending RGBW means first led is red, second is green, third is blue and last is white color.
My code enable them to on with those color, but i want them blinks not on only. However i do not have any idea on making them blink. I do not want them to blink at different Hz. I want them to blink at the same frequency. I just have no idea on how to modified my sketch to make them work.

How do you tell the Arduino to blink a specific led? My suggestion was to use e.g. 'R' to switch red on and 'r' to blink red.

You can blink by remembering the current state of each led.

void loop()
{
  // received data
  static char rxData[11];
  // index where to store received character
  static byte index = 0;

  
  // workcopy of received data
  static char workData[11];
  // remember current on/off state for flashing
  static char states[11];

  // timing related (flash)
  static unsigned long startTime = 0;
  unsigned long currentTime = millis();

  if (Serial.available() > 0)
  {
    if (index == 10)
    {
      index = 0;
    }
    rxData[index++] = Serial.read();
  }

  if (rxData == 10)
  {
    // work copy
    memcpy(workData, rx_Data);
    // initial state of leds equals received pattern
    memcpy(states, rxData);

    // reset index for next receive
    index = 0;
  }


  if (currentTime - startTime >= 500)
  {
    startTime = currentTime;

    for (int cnt = 0; cnt < 10; cnt++)
    {
      switch (workData[cnt])
      {
        case 'R':
          pixels.setPixelColor(j, pixels.Color(50, 0, 0));
          break;
        case 'r':
          // if on, switch off
          if (states[cnt] == 'r')
          {
            states[cnt] = 'O';
            pixels.setPixelColor(j, pixels.Color(0, 0, 0));
          }
          // if off, switch on
          else
          {
            states[cnt] = 'r';
            pixels.setPixelColor(j, pixels.Color(50, 0, 0));
          }
          break;
        case 'G':
          ...
          break;
        case 'g':
          ...
          break;
        case 'B':
          ...
          break;
        case 'b':
          ...
          break;
        case 'W':
          ...
          break;
        case 'w':
          ...
          break;
        case 'O':
          ...
          break;
      } // end_of_switch
    } // end_of_for
  } // end_of_if
}

It will receive up to 10 characters (representing what needs to happen); once the 10 are received, it will make a copy to two variables. The 'workData' variable is used to allow you to receive new data while the rest of your process is in progress. The 'states' variable is used to remember the state of leds that are flashing.

The code uses a non-blocking timing for the blinking so you can receive data in the mean time.

The code is not compiled nor tested but it can give you the idea how to approach. You'll have to fill in the dots :wink: