Go Down

Topic: Digital RGB LED Strip + Bluetooth modules (Read 2192 times) previous topic - next topic

Gaspa

Hi to everyone!
I'm working on a project involving a digital rgb led strip (LPD8806, 160pixel) and a bluetooth module.
I'm using my MacBook Pro with the internal bluetooth to communicate with a bluetooth module that is connected to an Arduino, which is controlling the LED strip. Actually, I divided the LED Strip which was 5m long in 10 strips long 50cm each (16pixel).
I'm using them to form a grid, in which every strip is connected to another, here a image to give the idea:
http://tinypic.com/r/2l9ow6/6

I'm using Processing with a simple sketch to send the height of the grid through bluetooth, here is the sketch:
Code: [Select]
/* Lorenzo Gasparini joined@me.com 2013 */
/* Codice Processing per gestione striscia LED da remoto con */
/* i moduli Bluetooth Bluetooth */

//Importo la libreria per la comunicazione seriale
import processing.serial.*;
Serial myPort;

void setup()
{
  //Imposto dimensione finestra
  size(400, 600);
  frameRate(10);
  noStroke();
  //Apro la porta seriale corrispondente al modulo BT
  myPort = new Serial(this, "/dev/tty.HC-05-DevB", 115200);
}

void draw()
{
  //Calcolo la posizione verticale del mouse rispetto alla finestra e la mappo
  //con numeri da 0 a 16
  int c = (int) ((mouseY / 600.0) * 17.0);
  //Stampo per debug
  println(c);
  //Invio alla striscia tramite seriale bluetooth
  myPort.write((byte)c);
}


And the Arduino Uno with the bluetooth module has this sketch:
Code: [Select]

/* Lorenzo Gasparini joined@me.com 2013 */
/* Codice Arduino per gestione striscia LED con dati ricevuti */
/* da Bluetooth */

//Librerie per gestione striscia LED RGB
#include "LPD8806.h"
#include "SPI.h"


int tmp;
//Griglia di boolean rappresentante i pixel (on/off)
boolean grid[16][10];

//Striscia LED con 160 LED RGB (10 pezzi * 16 led)
LPD8806 strip = LPD8806(160);

void setup()
{
  //Inizializzazione seriale
  Serial.begin(115200);
 
  //Inizializzazione striscia LED
  strip.begin();

  //Reset iniziale pixel
  strip.show();
}


void loop()
{
  //Aspetto di ricevere qualcosa
  while (!Serial.available()) ;
 
  //Ricezione dati
  while (Serial.available())
  {
    tmp = Serial.read();
   
    //Riempimento fino all'altezza "tmp"
    Fill(tmp);
   
  }
 
  //Aggiornamento striscia
  showStrip();

}

//Riempimento griglia fino ad altezza "m"
void Fill(int m)
{
  //Scorro le colonne
  for (int k=0; k<10; k++)
  {
    //Scorro le righe
    for (int i=0;i<16;i++)
    {
      //Riempio fino all'altezza stabilita
      if (i < m)
      {
        grid[i][k] = true;
      }
      else grid[i][k] = false;
    }
  }
}

//Funzione che restituisce in che colonna della griglia un certo pixel va
int col(int n)
{
  return 10-(int)(n/16.0-0.05);
}

//Funzione che restituisce in che riga della griglia un certo pixel va
int riga(int n)
{
  if (col(n) % 2 == 0)
  {
    if (n % 16 == 0) return 1;
    else return 17 - (n % 16);
  } else {
    if (n % 16 == 0) return 16;
    else return (n % 16);
  }
}

//Update e display della striscia
void showStrip()
{
  int r,c;
 
  //Scorro tutti i pixel
  for (int i=0; i<160;i++)
  {
    //Trovo la riga e la colonna del pixel corrente
    r = riga(i+1)-1;
    c = col(i+1)-1;
   
    //Se il pixel va acceso
    if (grid[r][c])
    {
      //Colore del pixel in base alla riga
      strip.setPixelColor(i, Wheel((r/16.0)*384));
    }
    else
    {
      strip.setPixelColor(i, strip.Color(0,0,0));
    }
  }
 
  //Aggiorno la striscia LED
  strip.show();
}

//Funzione degli esempi della libreria per striscie LED LPD8806 che
//Dato un numero tra 0 e 384, restituisce un colore (stile "arcobaleno")
uint32_t Wheel(uint16_t WheelPos)
{
  byte r, g, b;
  switch(WheelPos / 128)
  {
    case 0:
      r = 127 - WheelPos % 128;   //Red down
      g = WheelPos % 128;      // Green up
      b = 0;                  //blue off
      break;
    case 1:
      g = 127 - WheelPos % 128;  //green down
      b = WheelPos % 128;      //blue up
      r = 0;                  //red off
      break;
    case 2:
      b = 127 - WheelPos % 128;  //blue down
      r = WheelPos % 128;      //red up
      g = 0;                  //green off
      break;
  }
  return(strip.Color(r,g,b));
}


Sorry for the comments in Italian but I think it's quite understandable!
The problem is that the refreshing speed is too low.. I think it's due to the bluetooth communication but it sounds strange to me because the connection should be at 115200 bps. I'm sending just a byte every time! Have you got any idea?
If you need any other info.. just tell me!

Oh, forgot to mention.. I'm using this bluetooth modules:
http://www.usconverters.com/downloads/bluetooth-module-btm5-datasheet.pdf

Thanks!

billroy

This line in the Processing sketch is setting the sample rate to 10 per second:
Code: [Select]

  frameRate(10);


Says here the default is 60: http://processing.org/reference/frameRate_.html

I would experiment with increasing this setting to see if it helps.

Good luck with your project,

-br


PaulS

Unlike loop() on the Arduino, draw() is not called as fast as possible. There is a frame rate that determines when the next call to draw() happens.

I don't think that the problem involves the amount of data being sent. Rather, it involves how often data is sent.

Look at the Processing documentation for frame rate. Or, create a while loop in draw() to send more data per invocation of draw().

Gaspa

#3
Feb 17, 2013, 05:25 pm Last Edit: Feb 17, 2013, 05:32 pm by Gaspa Reason: 1

Unlike loop() on the Arduino, draw() is not called as fast as possible. There is a frame rate that determines when the next call to draw() happens.

I don't think that the problem involves the amount of data being sent. Rather, it involves how often data is sent.

Look at the Processing documentation for frame rate. Or, create a while loop in draw() to send more data per invocation of draw().


Thank you both, but the problem isn't the low frameRate.
In fact, I can esclude the "draw" and do
Code: [Select]

void setup()
{
..
while (true) myPort.write((byte) (int)random(16));
}


But I can say that it surely doesn't go over 3-4 fps.

EDIT: Tried with this
Code: [Select]
while (true)
  {
    myPort.write((byte) count);
    if (count==16) count = 0;
    else count++;
  }


and the FPS turns out to be exactly 4 (16 pixels updats in 4 seconds).

PaulS

Code: [Select]
while (true) myPort.write((byte) (int)random(16));
Maybe you need a cast to a float in there, too.


Disconnect all the LED strips. Connect one LED. Turn the LED on or off every time a byte arrives. I'm willing to bet that you get more than 4 bytes per second.

Gaspa

#5
Feb 17, 2013, 05:42 pm Last Edit: Feb 17, 2013, 05:44 pm by Gaspa Reason: 1

Code: [Select]
while (true) myPort.write((byte) (int)random(16));
Maybe you need a cast to a float in there, too.


Disconnect all the LED strips. Connect one LED. Turn the LED on or off every time a byte arrives. I'm willing to bet that you get more than 4 bytes per second.


Okay, tried with this:
Code: [Select]

void loop()
{
 while (!Serial.available()) ;
 
 while (Serial.available())
 {
   tmp = Serial.read();
   
   if (t)
   {
     strip.setPixelColor(1, strip.Color(127,0,0));
     t = false;
   }
   else
   {
     strip.setPixelColor(1, strip.Color(0,0,0));
     t = true;
   }
 }
 
 strip.show();
}


Aaaaand.. the pixel blinks 2 times per second :(

EDIT: Message received, the (int) casting isn't necessary.. Instead, the (byte) one is necessary because in this way I send 1 byte vs 4 bytes (int)

Gaspa

#6
Feb 17, 2013, 06:44 pm Last Edit: Feb 17, 2013, 06:46 pm by Gaspa Reason: 1
Tried with this code on the Arduino:
Code: [Select]
boolean temp = false;
void setup() {

 Serial.begin(115200);
 pinMode(3,OUTPUT);
}
void loop() {
 while (Serial.available())
 {
   int t = Serial.read();
   
   if (temp)
   {
     digitalWrite(3,HIGH);
     temp = false;
   }
   else
   {
     digitalWrite(3,LOW);
     temp = true;
   }
 }
}


with a LED connected on pin 3, and the Processing sketch continuously sending bytes.. it blinks only 2 times per second!
How can this be possible?

EDIT: I even tried with "Serial tools" sending random characters and the max speed is 2 blinks per second.. I'm really confused..

PaulS

Quote
I'm really confused..

So am I. What is "Serial tools"? How fast does it actually send data?

Since you are not setting the pin state based on what you are reading, the LED should toggle faster than you can see it change.

Gaspa


Quote
I'm really confused..

So am I. What is "Serial tools"? How fast does it actually send data?

Since you are not setting the pin state based on what you are reading, the LED should toggle faster than you can see it change.


Serial tools is a terminal for the serial port that I'm using in OSX. It is set to 115200 bps. If i send bytes continuously (i.e. keeping one key pressed) the led blinks 2 times per second. If i press repeatedly one key i can't get over 2 times per second of blinking..

PaulS

If you use the Serial Monitor, and enter a string of characters, then hit send, what do you see happening? More than 2 characters per second?

Gaspa


If you use the Serial Monitor, and enter a string of characters, then hit send, what do you see happening? More than 2 characters per second?


If I write "1", the led turns on (or off). If i write "11" the led blinks 1 time but very 'fast'. If i write "111" the led turns on (or off). And so on..

PaulS

Quote
If i write "11" the led blinks 1 time but very 'fast'.

Faster than 1/2 a second?

What you describe tells me that the Serial Monitor is able to send data to the Arduino faster than 2 bytes per second. So, there is no reason that Processing should not be able to do the same.

Processing is able to read the data that the Arduino sends to the serial port. So, forget about the LED strips for a while. When the Arduino gets a byte from the serial port, Serial.println(millis()); and have Processing read and display the serial data, using the bufferUntil() method of the Serial class and overriding the serialEvent() function.

Show us what you get in Processing.

Gaspa


Quote
If i write "11" the led blinks 1 time but very 'fast'.

Faster than 1/2 a second?

What you describe tells me that the Serial Monitor is able to send data to the Arduino faster than 2 bytes per second. So, there is no reason that Processing should not be able to do the same.

Processing is able to read the data that the Arduino sends to the serial port. So, forget about the LED strips for a while. When the Arduino gets a byte from the serial port, Serial.println(millis()); and have Processing read and display the serial data, using the bufferUntil() method of the Serial class and overriding the serialEvent() function.

Show us what you get in Processing.


First, thank you for the help you are giving me. Here the sketch I've tried following your advices.
Arduino sketch
Code: [Select]
void setup() {

  Serial.begin(115200);
}
void loop() {
  while (Serial.available())
  {
    Serial.read();
   
    Serial.println(millis());
  }
}


Processing code:
Code: [Select]
import processing.serial.*;
Serial myPort;

void setup()
{
  size(400, 600);
  frameRate(60);
  myPort = new Serial(this, "/dev/tty.HC-05-DevB", 115200);
  myPort.bufferUntil(10);
}

void draw()
{
  myPort.write((byte)1);
}

void serialEvent()
{
  println(myPort.readString());
}


Result: nothing printed on the console..

PaulS

The serialEvent() function has a specific signature:
Code: [Select]
void serialEvent(Serial thePort)
{
}

When the correct COM port for windows, and use the correct signature, I get:
Code: [Select]
187789

187805

187822

187838

187854

187872

187888

That's roughly 16 milliseconds per byte, including the time needed to generate the response. Far faster then twice a second.

Gaspa


The serialEvent() function has a specific signature:
Code: [Select]
void serialEvent(Serial thePort)
{
}

When the correct COM port for windows, and use the correct signature, I get:
Code: [Select]
187789

187805

187822

187838

187854

187872

187888

That's roughly 16 milliseconds per byte, including the time needed to generate the response. Far faster then twice a second.


Corrected the signature, result:
Code: [Select]
78295

78544

78794

79044

79295

79546

79796

80046

80297


It works like this:
-Processing send a byte via bluetooth serial port to the bluetooth module
-The bluetooth module sends millis() as response

Go Up