2

I want to be able to control multiple LED strip via bluetooth with one arduino. I coded my own android app and everything work fine with one or two led strip with few pixel. But as soon as I had to many pixel data send by BT is missing a few byte (ex "colfff5dff" instead of "color fff5dff"). It doen't happen every time but it's unrealiable. I feel like sending data to the led strip take so many time that it skip some letter.

I'm ussing dsd tech hc-05 with an arduino UNO R3 and a esp8266 led strip.

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

#ifdef __AVR__
 #include <avr/power.h> 
#endif

//SoftwareSerial blueTooth(13,12);

#define PIN       5
#define SIZE      200

#define BRIGHTNESS 200

enum MODE {FIXED, LOOP_RGB, RUNNING, RAINBOW};
enum MODE mode = FIXED;

Adafruit_NeoPixel strip(SIZE, PIN, NEO_RGB + NEO_KHZ800);

int lastTime;

uint32_t color;
char Incoming_value = 0;
char bufferStr[100];
int bufferIndex = 0; 

void setup() {

  Serial.begin(9600); //open the serial port
  Serial.setTimeout(10);
  strip.begin();           
  strip.show();            
  strip.setBrightness(50); 

  color = Adafruit_NeoPixel::Color(0, 255 ,0 );  
}

void loop() {
  if(Serial.available() > 0)  
  {
    String s = Serial.readString();
    Serial.print(s);

    //I've tried some other way like read();  readString();  readBytes(); readBytesUntil();
    
    /*
     * ---- not needed for the issue
     */
  }
  switch (mode){
    case FIXED : fixedMode(); break;
    case RUNNING : runningLights(); break;
    case RAINBOW : rainbow(); break;    
    }  
    showAll();
}


void parseBlueTooth(){
  //---- not needed for the issue
}


void fixedMode(){
  setAll(color);
  showAll();
}

void rainbow(){
  //---- not needed for the issue
}


void runningLights() {
  //---- not needed for the issue
}


void setAll(byte r, byte g, byte b) {
  setAll(Adafruit_NeoPixel::Color(r,g,b));
}

void setAll(uint32_t color) {
  strip.fill(color, 0, SIZE);
}

void showAll(){
  long curTime = millis();
  if(curTime - lastTime >16){
    if(strip.canShow()) {
      strip.show();     
    }
    lastTime = curTime;
  }

}
1

IMHO, after reading Majenko and raddevus reply, you may do something to "reduce missing data"

  1. reduce baud rate (may be 9600), give more time for bluetooth data transfer.

  2. add a checksum byte for your data.

Rererence :

https://lucidar.me/en/serialib/most-used-baud-rates-table/

0

Your problem is that you are using two blocking routines that can't operate together. Both the SoftwareSerial and the NeoPixel objects take time to perform operations stopping anything else from happening.

  • SoftwareSerial blocks inside an ISR while receiving a byte
  • NeoPixel blocks with interrupts disabled while outputting the LED status

That means that while NeoPixel is being updated SoftwareSerial is incapable of receiving any data. It was fine when you only had a few LEDs, since NeoPixel only took a very short time to update, but now that you have more LEDs it takes too long to update and SoftwareSerial can no longer work reliably.

In order to get around the problem you will have to use a hardware UART port. The Uno only has one - pins 0/1 and the Serial object. If you're not using that for communication with your computer you can connect your Bluetooth module there instead and use Serial instead of SoftwareSerial - however you will most probably need to disconnect your Bluetooth module every time you want to upload fresh code to your Arduino.

3
  • That's exactly what I did and it got better but not perfect. Jun 3 at 20:51
  • Maybe you need to upgrade your Arduino to one that will update the NeoPixels using DMA instead of locking up the CPU.
    – Majenko
    Jun 3 at 20:52
  • I'm gonna try that, thanks for the information Jun 3 at 21:14
-1

I am working with HC-05 also and retrieving files over it. I send commands and get files back over Bluetooth. The speed of bluetooth should be fine. (Although you need to set it faster -- mine's at 38400)

Up in your setup() loop do:

Serial.begin(38400)

Also your code to read off serial is a bit different.

You just need the following:

while (Serial.available()){
    command = Serial.read();
}

I was sending String-based commands but just today I decided to change them to 1 byte commands because it is much easier to deal with in a switch statement. In the code above my command variable is a byte.

Then my switch looks like the following in loop():

switch (command){
    case 49: { // ASCII Char 1 - get Temperature
      SW_Serial.print(getString(currentRoom) + " : " + currentTemp);
      // CALL YOUR SPECIFIC CODE TO DO EACH THING IN EACH CASE
      break;
    }
    case 50: { // ASCII char 2 - start data write
      // #### Allow Data Write start/stop to be done via BT
      // turns on logging of temp data (to SD card)
      // turn on data writing and LED
      // CALL YOUR SPECIFIC CODE TO DO EACH THING IN EACH CASE
...

Of course, each time through the loop you should set your command variable back to 0 (I use 0 as the no-command). Otherwise you'll keep processing on the same command value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.