Go Down

Topic: RGB LED Strip *help* (Read 3 times) previous topic - next topic

Dustin

The other day I was in RadioShack and bought this:

http://www.radioshack.com/product/index.jsp?productId=16306856

The source code provided isn't much help. Here it is:
Code: [Select]

#include <avr/pgmspace.h>

#define DATA_1 (PORTC |=  0X01)    // DATA 1    // for UNO
#define DATA_0 (PORTC &=  0XFE)    // DATA 0    // for UNO
#define STRIP_PINOUT (DDRC=0xFF)    // for UNO

PROGMEM const unsigned long pattern_test_red[10][10]={
  {0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000},
};
//there are more patterns but i deleted them to save space
};
void setup() {               
  STRIP_PINOUT;        // set output pin - DEBUG: should auto detect which mother board for use
  reset_strip();
}
void loop()
{
  send_1M_pattern(pattern_test_red, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_blue, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_green, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_white, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_comet1, 10, 70);
  delay(500);
  send_1M_pattern(pattern_test_comet2, 10, 70);
  delay(500);
  send_1M_pattern(pattern_test_comet3, 10, 70);
  delay(500);
  while (1)
  {
    send_1M_pattern(pattern_test_rainbow, 10, 70);
  }
}
void send_1M_pattern(const unsigned long data[][10], int pattern_no, int frame_rate)
{
  int i=0;
  int j=0;
  uint32_t temp_data;
  for (i=0;i<pattern_no;i++)
  {
    noInterrupts();
    for (j=0;j<10;j++)
    {
      temp_data=pgm_read_dword_near(&data[i][j]);
      send_strip(temp_data);
    }
    interrupts();
    delay(frame_rate);
  }
}
void send_strip(uint32_t data)
{
  int i;
  unsigned long j=0x800000;
  for (i=0;i<24;i++)
  {
    if (data & j)
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      DATA_0;
    }
    else
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      DATA_0;
    }
    j>>=1;
  }
}
void reset_strip()
{
  DATA_0;
  delayMicroseconds(20);
}


Someone in the comments had wrote this:
Code: [Select]

unsigned long createStripColor(unsigned char r, unsigned char g, unsigned char b) {
unsigned long color = 0x00;
color = color | ((unsigned long)g << 16);
color = color | ((unsigned long)b << 8);
color = color | r;
return color;
}


I've tried
Code: [Select]

void loop(){
createStripColor(255,0,0)
}
unsigned long createStripColor(unsigned char r, unsigned char g, unsigned char b) {
unsigned long color = 0x00;
color = color | ((unsigned long)g << 16);
color = color | ((unsigned long)b << 8);
color = color | r;
return color;
}

But the LEDs don't do anything. I'd like to just send the 0 - 256 values that I understand. Once I get that figured out I'll be golden. Or at least a way to turn the 0 - 256 into 0x00 format.

0xff0000 = bright green 0x110000 = light green 0x00ff00 = bright blue 0x001100 = light blue 0x0000ff = bright red and 0x000011 = light red

PaulS

Quote
But the LEDs don't do anything.

Well, of course not. You called a function that returned a value. You did not save that returned value. You did not do anything with the returned value.

Quote
Or at least a way to turn the 0 - 256 into 0x00 format.

That's what that function does. Now, you have to save, and do something with, that value.

Dustin

Code: [Select]

#include <avr/pgmspace.h>
#define DATA_1 (PORTC |=  0X01)    // DATA 1    // for UNO
#define DATA_0 (PORTC &=  0XFE)    // DATA 0    // for UNO
#define STRIP_PINOUT (DDRC=0xFF)    // for UNO

byte color;

void setup() {               
  STRIP_PINOUT;        // set output pin - DEBUG: should auto detect which mother board for use
  reset_strip();
  Serial.begin(9600);
}

void loop(){
  createStripColor(1, 255, 1);
  send_1M_pattern(color, 1, 70);
  Serial.println(color);
}

unsigned long createStripColor(byte r, byte g, byte b) {
byte color=0x00;
color = color | ((unsigned long)r << 16);
color = color | ((unsigned long)b << 8);
color = color | g;
return color;
}

void send_1M_pattern(const unsigned long data, int pattern_no, int frame_rate)
{
  int i=0;
  int j=0;
  uint32_t temp_data;
  for (i=0;i<pattern_no;i++)
  {
    noInterrupts();
    for (j=0;j<10;j++)
    {
      temp_data=pgm_read_dword_near(&data);
      send_strip(temp_data);
    }
    interrupts();
    delay(frame_rate);
  }
}

void send_strip(uint32_t data)
{
  int i;
  unsigned long j=0x800000;
  for (i=0;i<24;i++)
  {
    if (data & j)
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      DATA_0;
    }
    else
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      DATA_0;
    }

    j>>=1;
  }
}

void reset_strip()
{
  DATA_0;
  delayMicroseconds(20);
}


This is what I've got so far. The LED strip lights up but only with the "Serial.println(color);"  without that the colors aren't displayed or they're displayed weird.

Is this right? I googled unsigned long online and it said to use byte.
Code: [Select]

byte color=0x00;
color = color | ((unsigned long)r << 16);
color = color | ((unsigned long)b << 8);
color = color | g;


Not sure what's wrong or where to begin to fix it.

Dustin

Code: [Select]

#include <avr/pgmspace.h>

#define DATA_1 (PORTC |=  0X01)    // DATA 1    // for UNO
#define DATA_0 (PORTC &=  0XFE)    // DATA 0    // for UNO
#define STRIP_PINOUT (DDRC=0xFF)    // for UNO

unsigned long color;

void setup() {               
  reset_strip();
  Serial.begin(9600);
}

void loop(){
  send_1M_pattern(createStripColor(16, 16, 255), 1, 250);
  delay(500);
}

unsigned long createStripColor(unsigned char r, unsigned char g, unsigned char b) {
  color = color | ((unsigned long)g << 16);
  color = color | ((unsigned long)b << 8);
  color = color | r;
  Serial.print("R: ");
  Serial.println(r);
  Serial.print("G: ");
  Serial.println(g);
  Serial.print("B: ");
  Serial.println(b);
  Serial.print("Color: ");
  Serial.println(color, HEX);
  return color;
}

void send_1M_pattern(byte data, int pattern_no, int frame_rate)
{
  int i=0;
  int j=0;
  uint32_t temp_data;
  for (i=0;i<pattern_no;i++)
  {
    noInterrupts();
    for (j=0;j<10;j++)
    {
      temp_data=pgm_read_dword_near(&data);
      send_strip(temp_data);
    }
    interrupts();

    delay(frame_rate);
  }
}

void send_strip(uint32_t data)
{
  int i;
  unsigned long j=0x800000;
  for (i=0;i<24;i++)
  {
    if (data & j)
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      DATA_0;
    }
    else
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      DATA_0;
    }

    j>>=1;
  }
}

void reset_strip()
{
  DATA_0;
  delayMicroseconds(20);
}

Eoddan

Did you ever get it going?

I am a complete newbie to all the code. I have a basic electronics background and decided to learn about the Arduino and start on some basic projects.
I bought the LED Strip from Radio Shack just last night. Today, I hooked up the board and strip according to the guide with 12V AA battery pack into the DC barrel socket, Black to GND, Red to Vin, and the Green to A0. I used their sketch from the website, uploaded it and nothing. Rinse, repeat, and still nothing. Then I noticed a brownish black smudge on the first chip under the clear protector. I thought maybe the chip fried so I cut off the first LED segment (as designed) and soldered the leads onto the next contact pads, re sent the code, and no lights. Granted the segments are still together, except the first one. Not sure if this matters?
I think the Aduino works, I ran some successful projects recently and the TX and RX light flicker when loaded. Oddly, when I remove the GND the first  3 LEDs/circuit lights up very dimly.
Any help would be appreciated. A simple sketch just to make sure the lights and strip work would be a good start.
Thanks

EchelonForce

#5
Dec 31, 2012, 06:24 pm Last Edit: Dec 31, 2012, 06:26 pm by EchelonForce Reason: 1
Let me first say, The example code given by Radio Shack with this product is awful and whoever released it and/or wrote it should be fired.

Let me start responding by first commenting the bad code, and getting an understanding of it.

Originally Posted code with my comments:
Code: [Select]

/************************************************************
* LED Strip Demo Code
***********************************************************/
//Include pgmspace.h which gives us functions to directly
//access flash memory (where the array below is going to
//be stored.
#include <avr/pgmspace.h>

//DATA_1 is a macro that sets pin 1 on port C  (Arduino UNO Pin Analog 1)
// to HIGH.
#define DATA_1 (PORTC |=  0X01)
//DATA_0 is a macro that sets pin 1 on port C (Arduino UNO Pin: Analog 1)
//to low (while leaving the other pins on porct C alone.
#define DATA_0 (PORTC &=  0XFE)
//STRIP_PINOUT is a macro that sets the ENTIRE Port C
//(Arduino UNO Pins: A0-A5 to output mode) This is sloppy.
#define STRIP_PINOUT (DDRC=0xFF)

//pattern_test_red is an array of led patterns which gets stored in
//program memory (FLASH) by using the PROGMEM attribute. I suspect
//this is done because the poor implementation below has timing issues
//and they had to throw this data in flash to make accessing it
//faster/deterministic. http://arduino.cc/en/Reference/PROGMEM
PROGMEM const unsigned long pattern_test_red[10][10]={
//|--------------------------length ten, assumed below, don't change------------------------|
  {0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000}, // -
  {0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000}, // |
  {0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000}, // |
  {0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000}, // |
  {0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000}, // |-- Number of patterns = 10 assumed below, don't change.
  {0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000}, // |
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000}, // |
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000}, // |
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000}, // |
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000}, // -
};
//there are more patterns but i deleted them to save space
//Good idea. This is terrible test code :)

//}; This looks like a typo...extra curly bracket in copy pasted code I suspect.

/************************************************************
* One Time Setup. Called once.
* Sets up Pin modes, and resets LED strip.
***********************************************************/
void setup() {               
  STRIP_PINOUT;        // set output pin - DEBUG: should auto detect which mother board for use
  reset_strip();
}

/************************************************************
* Continuously called loop. When the bottom of the function
* is reached, this function is called again, repeatedly,
* until the end of time.
***********************************************************/
void loop()
{
  //Send a pattern from the array above to the chip on the LED strip.
  //This sends the red LED pattern array, says there are 10 patterns,
  //and to delay 500ms between each one.
  send_1M_pattern(pattern_test_red, 10, 500);
  //Wait a half second.
  delay(500);
  //deleted remaining code in here for clarity. Also original arrays are missing.
}

/************************************************************
* Send a pattern to the LED strip.
* Arguments:
*   data[pattern_no][10] - A 2D array of 24bit patterns.
*   pattern_no - size of first dimension of data array.
*                 Second dimension assumed to equal 10.
*   frame_rate - Delay between changing led pattern.
***********************************************************/
void send_1M_pattern(const unsigned long data[][10], int pattern_no, int frame_rate)
{
  int i=0; //loop variable.
  int j=0; //loop variable.
  uint32_t temp_data; //temporary variable.
  //Loop through first dimension of the passed in array.
  for (i=0;i<pattern_no;i++)
  {
    // Turn off interupts (timing critical I suppose).
    //I wouldn't do anything inside this like print outs...
    noInterrupts();
    //Loop through second dimension of the passed in array.
    for (j=0;j<10;j++)
    {
      //Read a double word from the passed in array.
      temp_data=pgm_read_dword_near(&data[i][j]);
      //Send the double word to the LED Strip Chip.
      send_strip(temp_data);
    }
    //Turn interupts back on so that the delay below can operate.
    interrupts();
    //delay frame_rate milliseconds between changing to the next pattern.
    delay(frame_rate);
  }
}

/************************************************************
* Send a pattern to the LED strip.
* Arguments:
*   data - color pattern to send.
*
* How on earth they expect a beginer to understand this
* is beyond me...but I'll explain it all the same.
***********************************************************/
void send_strip(uint32_t data)
{
  int i; //loop variable.
  unsigned long j=0x800000; //bit mask that gets shifted below.
// What this does:
// Loop through all 24 bits of color (8 red, 8 green, 8 blue),
// starting the bit mask: j = 0000000 10000000 00000000 00000000
// Use bit comparison ("data & j") of j with passed in data to
// see if the 24th bit is one or zero.
// If one, set output pin to 1 and wait X, then set back to zero.
// If zero, set output pin to 1 and wait Y, then set back to zero.
// Finally, bit shift j once to the right to get a new bit mask:
//                        j = 0000000 01000000 00000000 00000000
// to use in next loop iteration.
//
// __asm__("nop\n\t"); is an 'inline assembly' call of the
// nop instruction. nop = No Operation. This is done as a hacky way
// to get deterministic timing...hopefully the math below is correct...
//
// X =  18 * nop
//   =  18 * 1 instruction
//   =  18 * 1 sec/16,000,000  (16 MHz)
//   =  18 * 0.0000000625 sec
//   =  0.000001125 sec = 1.125 microseconds
//
//  Y = 9 * nop = 0.0000005625 sec = 0.5625 microseconds
//
  for (i=0;i<24;i++) // loop through all 24 bits.
  {
    if (data & j) // Is this bit a one or zero?
    {
    //Bit is a one, so set the output HIGH, and wait 1.125 microseconds
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      // Set output low again.
      DATA_0;
    }
    else
    {
    //Bit is a zero, so set the output HIGH, and wait 0.5625 microseconds
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");   
      // Set output low again.
      DATA_0;
    }
    //Bit shift j, once to the right to get a new mask.
    j>>=1;
  }
}

/************************************************************
* Reset LED Strip
***********************************************************/
void reset_strip()
{
  // set output LOW
  DATA_0;
  // Wait 20 microseconds.
  delayMicroseconds(20);
}


This code is bad for many reasons beyond those expressed in my comments. If I can I'll get my hands on one of these and write a superior sketch to use as an example.

The main issue (other than clarity for beginners) is that this code is very dependent on the speed of the arduino's processor and is not tolerant of much modification. Be very careful with print outs in this code because it can skew the timing or not work at all when interrupts get disabled.

Dustin


Did you ever get it going?

I am a complete newbie to all the code. I have a basic electronics background and decided to learn about the Arduino and start on some basic projects.
I bought the LED Strip from Radio Shack just last night. Today, I hooked up the board and strip according to the guide with 12V AA battery pack into the DC barrel socket, Black to GND, Red to Vin, and the Green to A0. I used their sketch from the website, uploaded it and nothing. Rinse, repeat, and still nothing. Then I noticed a brownish black smudge on the first chip under the clear protector. I thought maybe the chip fried so I cut off the first LED segment (as designed) and soldered the leads onto the next contact pads, re sent the code, and no lights. Granted the segments are still together, except the first one. Not sure if this matters?
I think the Aduino works, I ran some successful projects recently and the TX and RX light flicker when loaded. Oddly, when I remove the GND the first  3 LEDs/circuit lights up very dimly.
Any help would be appreciated. A simple sketch just to make sure the lights and strip work would be a good start.
Thanks



Is your DC barrel maybe backwards? I think the Arduino must be center tip negative (plug it in minus the usb cable... if it doesn't come on it's probably backwards) just flip your positive / negative wires. Green -> A0 (analog zero) red to VIN and black to GND the sketch from RadioShack should at least light them up. The brown on one of the chips might suggest it got fried (and if so probably your whole strip is fried)

As far as the code working how I'd like... no. It's not there yet but I've gotten help from a lot of very helpful people.

If you want to try again and get another strip I suggest http://adafruit.com/products/306 from Adafruit. I have both strips (just to play around with) and the Adafruit ones are way better. Code is better, too. They're both around the same price.

Dustin

EchelonForce that explains a lot about the prints... sometimes it would work with them and sometimes only half the strip would light up.

Neither of which were the color(s) expected, though. You don't have to go out and buy one of these I was just trying to play around with it. Like I said on G+ I also have the Adafruit LED strip and it's much better (and more documented) that I'm going to use for a "main" project.

These ones from RadioShack turn on and off (that's about it lol) and will work for a side project I'm going to give to a friend for her kids as a night like of some kind.

Eoddan

Thank you for all of the help. I have had no luck with the Radio Shack LED strip so I'm going to try to return it for another brand. I checked the barrel wiring and it does appear correct with a positive center. I think the burnt chip either happened when I  was hooking it up or was bad before I got it, either way I'd rather start on a known good one before I waste anymore time. Thank you very much for the suggestions and code comments.

Dustin

If you want a good set of LEDs get this strip from Adafruit.

http://adafruit.com/products/306

It's the one I'm using for my main project now that I know the RadioShack ones won't work.

Go Up