Go Down

Topic: WS2811 and ATTiny85? (Read 5961 times) previous topic - next topic

Nico Maas

Hi there,

I wanted to start using the WS2811 Modules to control RGB Leds
( http://www.ebay.de/itm/20-Stuck-WS2811-Platine-3-Kanal-RGB-LED-Treiber-Pixel-Controller-KSQ-PWM-/370729241262?pt=Bauteile&hash=item56512f4aae#ht_1429wt_950
Handbook: http://kt-elektronic.de/wawi11/artikeldaten/pcb-ws2811smd-rita/ws2811.pdf ))

I already used the arduino-tiny ( https://code.google.com/p/arduino-tiny/ ) library to program the ATTiny85 with an simple LED Blink Program via an Arduino Uno.

Could someone help me out with using the WS2811 module correctly with an Arduino or even an ATTiny85, i.e. how to correctly change colors with this thing or control the LEDs? That would be awesome. Thanks a lot!

And - if someone knows - is it possible to control the WS2811 via the ATTiny85 and -  at the same time, add an RFM12B (http://www.hoperf.com/rf/fsk/21.htm) Transciever to control multiple combinations of this RGB Leds via an central controller unit?

Greetings,

Nico

fungus

#1
Feb 18, 2013, 04:36 am Last Edit: Feb 18, 2013, 04:48 am by fungus Reason: 1

Hi there,

I wanted to start using the WS2811 Modules to control RGB Leds


Good idea!

(I'm doing the same thing right now...)


Could someone help me out with using the WS2811 module correctly with an Arduino or even an ATTiny85, i.e. how to correctly change colors with this thing or control the LEDs? That would be awesome. Thanks a lot!


Here's a snippet of the code I'm using on an 8MHz Tiny85 (nb. it won't work at other clock frequencies - WS2811 is all about timing):

Code: [Select]

// Where the WS2811 is attached (pin B4)
#define LED_BIT (1<<4)
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define NOP __asm__("nop\n\t")

class WS2811 {
public:
 static void init() {
   LED_PORT &= ~LED_BIT;
   LED_DDR |= LED_BIT;
 }
};
WS2811 ws2811;


// A single LED in the string
class LED {
 byte r_,g_,b_;
 static void sendByte(byte b) {
   byte mask = 0x80;
   while (mask!=0) {
     if ((b&mask)==0) {
       // Send a '0'
       LED_PIN = LED_BIT;  // Hi (start)
       NOP;                // Hi
       LED_PIN = LED_BIT;  // Lo (250ns)
       NOP;                // Lo
       NOP;                // Lo (500ns)
       NOP;                // Lo (data bit here!)
       NOP;                // Lo (750ns)
       NOP;                // Lo (875ns)
     }
     else {
       // Send a '1'
       LED_PIN = LED_BIT;  // Hi (start)
       NOP;                // Hi
       NOP;                // Hi (250ns)
       NOP;                // Hi
       NOP;                // Hi (500ns)
       NOP;                // Hi (data bit here!)
       NOP;                // Hi (750ns)
       LED_PIN = LED_BIT;  // Lo (875ns)
     }
     mask >>= 1;           // Lo (1000ns)
   }
 }
public:
 // Set my color
 LED& setColor(byte r, byte g, byte b) {
   r_ = r;
   g_ = g;
   b_ = b;
 }
 // Send me to the LED
 void send() const {
   cli();   // Interrupts have to be off while we do this as they cause timing glitches
   sendByte(g_);
   sendByte(b_);
   sendByte(r_);
   sei();
 }
};

LED led;

void setup()
{
 ws2811.init();
}

void loop()
{
 byte b = 128;
 led.setColor(b,0,b);
 led.send();
 delay(300);
 led.setColor(0,b,0);
 led.send();
 delay(300);
}


The only thing you have to watch out for is not to delay for too long between sending of each LED. The WS2811 interprets transmission delays of 50us or more as a signal that you've finished sending (in that code it's the 'delay(300)' that sets the LED color).

8MHz is the minimum CPU speed you need. If you want 16MHz you'll have to put more NOPs in.

There's a bunch of info on the WS2811 here: https://www.insomnialighting.com/products/rgbpxws2811.html


And - if someone knows - is it possible to control the WS2811 via the ATTiny85 and -  at the same time, add an RFM12B (http://www.hoperf.com/rf/fsk/21.htm) Transciever to control multiple combinations of this RGB Leds via an central controller unit?


It's possible, yes... :)

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Nico Maas

#2
Feb 18, 2013, 04:16 pm Last Edit: Feb 18, 2013, 05:21 pm by Nico Maas Reason: 1

(I'm doing the same thing right now...)


Awesome! :)
Now I don't feel that alone anymore!


Code: [Select]

// Where the WS2811 is attached (pin B4)
#define LED_BIT (1<<4)
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define NOP __asm__("nop\n\t")



Is the  LED_BIT (1<<4) saying that the WS2811 is attached to PIN4?
So I could change it to Port 5 or so? (If not used for i.e. GND, RESET or Power?)


The WS2811 interprets transmission delays of 50us or more as a signal that you've finished sending (in that code it's the 'delay(300)' that sets the LED color).


So if I would change this code to:
Code: [Select]

void loop()
{
  byte b = 128;
  led.setColor(0,b,b);
  led.send();
  led.setColor(b,0,b);
  led.send();
  led.setColor(b,b,0);
  led.send();
  delay(300);
}

Could I "feed" 3 WS2811, attached after each other with their own color information?
I.e. set the first to one color, the second to another and the third to the last?
( is the 128 the max in one colour? )

Thanks, I hope to get my WS2811 module soldered soon, so that I could actually get to grips with it - testing on an live system is always more helpful than kicking dead theory ;)!



And - if someone knows - is it possible to control the WS2811 via the ATTiny85 and -  at the same time, add an RFM12B (http://www.hoperf.com/rf/fsk/21.htm) Transciever to control multiple combinations of this RGB Leds via an central controller unit?


It's possible, yes... :)


Awesome, do you have any information on that as well?

I would love to make multiple of these ATTiny85, WS2811, RFM12B combination for an art project, to remote control the colour of the leds.
Any ideas? Or should I open an new topic for that...


Thanks a lot for your help already, that really should get me started as soon as I got the stuff soldered :)!

fungus

#3
Feb 18, 2013, 05:05 pm Last Edit: Feb 18, 2013, 05:33 pm by fungus Reason: 1

Is the  LED_BIT (1<<4) saying that the WS2811 is attached to PIN4?


Yes.


So I could change it to Port 5 or so? (If not used for i.e. GND, RESET or Power?)


You can change it, yes, but there's no "pin 5" on a Tiny85. :)

(Well, there is, but you can't normally use it)


If I would change this code to:
Code: [Select]

void loop()
{
 byte b = 128;
 led.setColor(0,b,b);
 led.send();
 led.setColor(b,0,b);
 led.send();
 led.setColor(b,b,0);
 led.send();
 delay(300);
}

Could I "feed" 3 WS2811, attached after each other with their own color information?


Yes.



( is the 128 the max in one colour? )


No, brightness is 0..255




And - if someone knows - is it possible to control the WS2811 via the ATTiny85 and -  at the same time, add an RFM12B (http://www.hoperf.com/rf/fsk/21.htm) Transciever to control multiple combinations of this RGB Leds via an central controller unit?


It's possible, yes... :)


Awesome, do you have any information on that as well?
[/quote]

Nope.

But basically you can do whatever you want where the "delay(300)" is. The LEDs will look after themselves.


I'm making one of these:
http://www.instructables.com/id/IR-Remote-Controlled-Color-Changing-Cloud-Arduino/

(nb. His circuit is terrible, don't copy it if you care about your Arduino's health...)

I'm using a Tiny85 with one pin driving the LEDs, one pin for the IR remote control, one for sound effects...and I still have two pins left over for other things!

I snipped the LEDs off a light string like this one: http://www.ebay.com/itm/160907739909 . The LEDs have built-in WS2811s and they work out at about 50 cents each, which is pretty cheap when you consider the amount of work/wires they save.

Last week I found a guy who sells the WS2811 in 8-pin DIP package. I'm planning another gadget with big 12mm RGB LEDs so I'm going to use them in that. I guess I've become a WS2811 fan lately... :) Any project where the LEDs are spread out randomly is really easy to build using them.

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Nico Maas


I'm making one of these:
http://www.instructables.com/id/IR-Remote-Controlled-Color-Changing-Cloud-Arduino/
(nb. His circuit is terrible, don't copy it if you care about your Arduino's health...)

I'm using a Tiny85 with one pin driving the LEDs, one pin for the IR remote control, one for sound effects...and I still two pins left over for other things!

I snipped the LEDs off a light string like this one: http://www.ebay.com/itm/160907739909 . The LEDs have built-in WS2811s and they work out at about 50 cents each, which is pretty cheap when you consider the amount of work/wires they save.

Last week I found a guy who sells the WS2811 in 8-pin DIP package. I'm planning another gadget with big 12mm RGB LEDs so I'm going to use them in that. I guess I've become a WS2811 fan lately... :) Any project where the LEDs are spread out randomly is really easy to build using them.


Wow, that really looks awesome!
Thank you very much for your answers, I really can't wait to start with this stuff... But I think I need to wait a bit..
I will report back as soon as I got to work on it :)!
And good luck with your project, seems to me as a lot of fun and success beeing ahead of you ;)!

Nico Maas

Ok, I tried to wire it up - and failed terribly.


I used these controllers as said http://www.ebay.de/itm/20-Stuck-WS2811-Platine-3-Kanal-RGB-LED-Treiber-Pixel-Controller-KSQ-PWM-/350714431689?pt=Bauteile&hash=item51a83588c9&_uhb=1#ht_1366wt_950
and wired them up as following:
GND to GND,
VCC / VDD with 5V,
DI / (Pin 6) to the )Analog Input 2) / PIN 4 | 3 (as seen on the picture above).

I flashed my Arduino Uno with the ISP Programmer Image,
and flashed your snippet with the Board Type Tiny 85 @8Mhz, internal osc., BOD disabled, and the Arduino ISP
(which worked flawlessly for my Blink Test thing)

But after that, nothing happend, the LED stayed dark.
I only used one of these modules to just verify "it works" before moving further....

Could you help me out?

Thanks a lot!

fungus


Ok, I tried to wire it up - and failed terribly.


I used these controllers as said http://www.ebay.de/itm/20-Stuck-WS2811-Platine-3-Kanal-RGB-LED-Treiber-Pixel-Controller-KSQ-PWM-/350714431689?pt=Bauteile&hash=item51a83588c9&_uhb=1#ht_1366wt_950


Hey, those are cool! Good price, too.


and wired them up as following:
GND to GND,
VCC / VDD with 5V,
DI / (Pin 6) to the )Analog Input 2) / PIN 4 | 3 (as seen on the picture above).


Yep.


I flashed my Arduino Uno with the ISP Programmer Image,
and flashed your snippet with the Board Type Tiny 85 @8Mhz, internal osc., BOD disabled, and the Arduino ISP
(which worked flawlessly for my Blink Test thing)


I know the code works, I just copy-pasted it from above and ran it.

The only obvious thing I can think of is you're not running at 8MHz. Did you do a 'burn bootloader'?
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Nico Maas

#7
Feb 20, 2013, 09:28 pm Last Edit: Feb 20, 2013, 09:44 pm by Nico Maas Reason: 1

I know the code works, I just copy-pasted it from above and ran it.

The only obvious thing I can think of is you're not running at 8MHz. Did you do a 'burn bootloader'?


To be truthful: No, I forgot about that, and tried it.
But sadly, the LED did not light a bit... :/..

Update: IT DID! It does work, I did had a problem with the polarity of the LED.
Yeah, that is really an dumb error - but now it does seem to work for one LED - I will try to work from that...
Thanks a lot!!

fungus

Can you measure the voltage on pin 7 of the WS2811 on your board?

According to the datasheet that pin sets the clock speed, if it's been pulled high the data timing changes.
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Nico Maas


Can you measure the voltage on pin 7 of the WS2811 on your board?

According to the datasheet that pin sets the clock speed, if it's been pulled high the data timing changes.



Yeah, I read that too, but - sorry, I think I really missed that out, that baby is now glowing :)!
I think the leason learned here would be:
a) Burn the bootloader to get it to 8 MHz. Do it two times if you're unsure
b) Watch out for the polarity of your LEDs. It is quite easy in dark rooms to mess with the "thought-to-be-longest" pin (it was bend, and therefore I missed the correct one... I'm so damn stupid ~.~!)

Thank you for your time, I think it should work out from here :)!
You were an awesome help!

fungus

OK, now you need some of these... :)

http://arduino.cc/forum/index.php/topic,148155.0.html

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

thanks a lot! this saved my butt!

Adafruit's neoPixel code suggests an attiny85 running at 16.5Mhz... but it didn't work for me after a few hours of learning about boards.txt...

ws2811

I did have to use the Burn Bootloader under the Tools Menu for whatever reason when programming with the Arduino as ISP.

plctim

I was testing with 2 LEDS and found the flashing of the first LED.  I moved the cli / sei... Example..
// Where the WS2811 is attached (pin B4)
#define LED_BIT (1<<4)
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define NOP __asm__("nop\n\t")
int maxColorArr = 256;
int maxColorValue = 255;

class WS2811 {
public:
  static void init() {
    LED_PORT &= ~LED_BIT;
    LED_DDR |= LED_BIT;
  }
};
WS2811 ws2811;


// A single LED in the string
class LED {
  byte r_,g_,b_;
  static void sendByte(byte b) {
    byte mask = 0x80;
    while (mask!=0) {
      if ((b&mask)==0) {
        // Send a '0'
        LED_PIN = LED_BIT;  // Hi (start)
        NOP;                // Hi
        LED_PIN = LED_BIT;  // Lo (250ns)
        NOP;                // Lo
        NOP;                // Lo (500ns)
        NOP;                // Lo (data bit here!)
        NOP;                // Lo (750ns)
        NOP;                // Lo (875ns)
      }
      else {
        // Send a '1'
        LED_PIN = LED_BIT;  // Hi (start)
        NOP;                // Hi
        NOP;                // Hi (250ns)
        NOP;                // Hi
        NOP;                // Hi (500ns)
        NOP;                // Hi (data bit here!)
        NOP;                // Hi (750ns)
        LED_PIN = LED_BIT;  // Lo (875ns)
      }
      mask >>= 1;           // Lo (1000ns)
    }
  }
public:
  // Set my color
  LED& setColor(byte r, byte g, byte b) {
    r_ = r;
    g_ = g;
    b_ = b;
  }
  // Send me to the LED
  void send() const {
    sendByte(g_);
    sendByte(b_);
    sendByte(r_);
  }
};

LED led1;
LED led2;

void setup()
{
  ws2811.init();
}

void getRGBFromIndex(byte colorIndex,byte *ValueR,byte *ValueG,byte *ValueB)
{
  if (colorIndex < 43)
    *ValueR = 255;
  else
  if (colorIndex < 86)
    *ValueR = 255-(colorIndex * 6);
  else
  if (colorIndex < 171)
    *ValueR = 0;
  else
  if (colorIndex < 214)
    *ValueR = colorIndex * 6;
  else
    *ValueR = 255;

  if (colorIndex < 43)
    *ValueG = colorIndex * 6;
  else
  if (colorIndex < 129)
    *ValueG = 255;
  else
  if (colorIndex < 171)
    *ValueG = 255-(colorIndex * 6);
  else
    *ValueG = 0;

  if (colorIndex < 86)
    *ValueB = 0;
  else
  if (colorIndex < 128)
    *ValueB = colorIndex * 6;
  else
  if (colorIndex < 214)
    *ValueB = 255;
  else
    *ValueB = 255-(colorIndex * 6);
}

byte AutoColorIndex1 = 0;
byte AutoColorIndex2 = 128;
  // The current RGB color values for mode 3 fade
  static byte ValueR1;
  static byte ValueG1;
  static byte ValueB1;
  static byte ValueR2;
  static byte ValueG2;
  static byte ValueB2;

void loop()
{
 
    getRGBFromIndex(AutoColorIndex1,&ValueR1,&ValueG1,&ValueB1);
    AutoColorIndex1++;
    if (AutoColorIndex1 == maxColorArr)
      AutoColorIndex1 = 0;

    getRGBFromIndex(AutoColorIndex2,&ValueR2,&ValueG2,&ValueB2);
    AutoColorIndex2++;
    if (AutoColorIndex2 == maxColorArr)
      AutoColorIndex2 = 0;

  led1.setColor(ValueR1,ValueG1,ValueB1);
  led2.setColor(ValueR2,ValueG2,ValueB2);

        LED_PIN = 0;  // Hi (start)

    cli();   // Interrupts have to be off while we do this as they cause timing glitches
  led1.send();
  led2.send();
    sei();

  delay(100);



  /*
  byte b = 128;
  led.setColor(b,0,b);
  led.send();
  led.setColor(0,b,0);
  led.send();
  delay(500);

  led.setColor(0,b,0);
  led.send();
  led.setColor(b,0,b);
  led.send();
  delay(500);
  */
 
}

fungus


I was testing with 2 LEDS and found the flashing of the first LED.  I moved the cli / sei... Example..


Yes. Since I wrote that I found out it's best to disable interrupts for the entire send.
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Go Up