WS2811 and ATTiny85?

Good idea!

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

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):

// 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

It's possible, yes... :slight_smile:

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

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

fungus:

// 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?)

fungus:
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:

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 ;)!

fungus:

[quote author=Nico Maas link=topic=149528.msg1123038#msg1123038 date=1361138467]
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... :slight_smile:
[/quote]

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 :)!

Yes.

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

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

Yes.

No, brightness is 0..255

fungus:

[quote author=Nico Maas link=topic=149528.msg1123038#msg1123038 date=1361138467]
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... :slight_smile:
[/quote]

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:

(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... :slight_smile: Any project where the LEDs are spread out randomly is really easy to build using them.

fungus:
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... :slight_smile: 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 ;)!

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!

Hey, those are cool! Good price, too.

Yep.

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'?

fungus:
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!!

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.

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.

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!

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

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

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.

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);
*/

}

plctim:
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.

Any idea how to get this working with the 800khz WS2812s?

I've got tons of them, and no matter what I try I can't get the adafruit neopixel code to compile for the tiny85, but this code works great (with the old generation pixels)

I'm trying to get it working with the new gen ones too, but can't figure out the changes that are needed for the faster timing

Hi Nico,

Did you finish this project ? I'm trying to do exactly the same thing (i.e. controlling remotely WS2811 led strips with music) but i'm not finding any informations on that. However, I'm less regarding in the cost so I could go on more expensive setups (jeenode ?)

I would be very interested to know how you did that.

I am going to combine this with nrf24l01 radio modules and make it part of my DMX tx/rx system

http://forum.arduino.cc/index.php?topic=208648.msg1817569#msg1817569

I have been looking to do this for sometime, and with using the nrf2401 with an ATTin85 there is only one pin left to use (apart from reset) it seems perfect to use it to drive WS2801's

I am thinking of putting just 3 WS2811 together wired to do the same colours etc, so that my little box becomes a completely wireless, battery operated, 24million colour RGB pixel !! I also got waterproofboxes to so I can put them outside if I want to !!

mcnobby:
I have been looking to do this for sometime, and with using the nrf2401 with an ATTin85 there is only one pin left to use

How did you connect a nrf2401 with only 4 pins?

I am trying to get a fix from this on another thread, but essentially I was going down this route...

http://cratel.wichita.edu/blogs/eecsfinalreportspr2013homeautoframework/assembly/

This person has connected CE from the nrf to ground so that it is always in receive mode - I dont know if this works or not

mcnobby:
This person has connected CE from the nrf to ground so that it is always in receive mode - I dont know if this works or not

It definitely won't work if you connect it to GND. That would lock it in standby-I mode.

It might work if you connect it HIGH and you only ever need receive mode. I never tried it ... (maybe I should)