|
|
Valencia, Spain
Offline
Edison Member
Karma: 65
Posts: 2226
|
 |
« Reply #1 on: February 17, 2013, 10:36:58 pm » |
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): // 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.htmlAnd - 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... 
|
|
|
|
« Last Edit: February 17, 2013, 10:48:11 pm by fungus »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #2 on: February 18, 2013, 10:16:54 am » |
(I'm doing the same thing right now...)
Awesome!  Now I don't feel that alone anymore! // 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: 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  !
|
|
|
|
« Last Edit: February 18, 2013, 11:21:22 am by Nico Maas »
|
Logged
|
|
|
|
|
Valencia, Spain
Offline
Edison Member
Karma: 65
Posts: 2226
|
 |
« Reply #3 on: February 18, 2013, 11:05:55 am » |
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: 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.
|
|
|
|
« Last Edit: February 18, 2013, 11:33:27 am by fungus »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #4 on: February 18, 2013, 11:25:14 am » |
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  !
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #5 on: February 20, 2013, 02:46:46 pm » |
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_950and 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!
|
|
|
|
|
Logged
|
|
|
|
|
Valencia, Spain
Offline
Edison Member
Karma: 65
Posts: 2226
|
 |
« Reply #6 on: February 20, 2013, 03:10:02 pm » |
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'?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #7 on: February 20, 2013, 03:28:48 pm » |
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!!
|
|
|
|
« Last Edit: February 20, 2013, 03:44:11 pm by Nico Maas »
|
Logged
|
|
|
|
|
Valencia, Spain
Offline
Edison Member
Karma: 65
Posts: 2226
|
 |
« Reply #8 on: February 20, 2013, 03:56:17 pm » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 12
|
 |
« Reply #9 on: February 20, 2013, 04:03:02 pm » |
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!
|
|
|
|
|
Logged
|
|
|
|
|
Valencia, Spain
Offline
Edison Member
Karma: 65
Posts: 2226
|
 |
« Reply #10 on: February 20, 2013, 04:43:08 pm » |
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 2
|
 |
« Reply #11 on: March 23, 2013, 11:15:57 pm » |
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
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 2
|
 |
« Reply #12 on: March 23, 2013, 11:18:58 pm » |
I did have to use the Burn Bootloader under the Tools Menu for whatever reason when programming with the Arduino as ISP.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 2
|
 |
« Reply #13 on: April 27, 2013, 12:10:48 am » |
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); */ }
|
|
|
|
|
Logged
|
|
|
|
|
Valencia, Spain
Offline
Edison Member
Karma: 65
Posts: 2226
|
 |
« Reply #14 on: April 27, 2013, 04:31:43 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
|