Go Down

Topic: Simple way of driving WS2812b RGB LEDs (Read 1 time) previous topic - next topic

mcnobby

I wrote this to work with ATTiny13, they dont have much flash, so I needed the smallest working WS-driver and Neo was far too large. I was running this as part of a larger program at 9.6mhz on the t13.. works perfectly, but may need adapting

Anyway, in a round about way I came up with this, its quite funny really if you look at the assembler...

Code: [Select]
#define DIGITAL_PIN   (2)         // Digital port number
#define PORT          (PORTB)     // Digital pin's port
#define PORT_PIN      (PORTB2)    // Digital pin's bit position
#define NUM_CHANS     (4)
uint8_t WSData[NUM_CHANS];

void setup(void) {
  DDRB |= 0b00000100; // set data direction for WS2812 output
}

void loop(void) {
  cli();
  WS2812();
    // do something else here
}

void WS2812(void) {
    for (volatile uint8_t y=1; y<NUM_CHANS; y++) {
      asm volatile(
          "ldi  %3, 8\n\t"      // reset number of bits
        "nextbit:\n\t"          // label                       
          "sbi  %0, %1\n\t"     // SET OUTPUT HIGH
          "sbrs %4, 7\n\t"      // Skip output low if HiBit in value is set 
            "cbi %0, %1\n\t"      // SET OUTPUT LOW, early for a low
          "sbrc %4, 7\n\t"      // Skip output low if HiBit in value is clear 
            "cbi %0, %1\n\t"      // SET OUTPUT LOW, late for a high
          "rol  %4\n\t"         // shift value left to get to next bit
          "dec  %3\n\t"         // decrement nBits
          "brne nextbit\n\t"    // branch if bits not finished
          ::
          "I" (_SFR_IO_ADDR(PORT)), // %0
          "I" (PORT_PIN),           // %1
          "e" (&PORT),              // %a2
          "r" (8),                  // %3
          "r" (WSData[y])          // %4
        ); // asm
    } // x loop
    delay(10);
}
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

mcnobby

using the Tiny13 cores, this compiles in under 300 bytes !!
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

PaulRB

Thanks mcnobby, could be useful one day.

Is the timing likely to close enough on a tiny85 @ 8MHz?

Is the data in WSdata[] preserved?

Paul

mcnobby

Well, as far as timing is concerned, I dont think I have managed 800khz, but in saying that I think the WS2812's are pretty tolerant, I had much slower routines running well before I came up with this, its so simple its almost cheeky !!

Yes, the data is preserved, each array byte is passed into the assembler and immediately goes into a register and then manipulated/bit-rolled/etc

If you ran the t85 at 16mhz you would easily achieve 800khz, although it would be best to try and scope the cycle just to check

Regards
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

mcnobby

Incidentally, the
Code: [Select]
delay(10); is just there as a simple delay, the actual delay required after the data has been loaded into the devices is 50us
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

evildave_666

Have you looked at
http://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/

There's some info there on what the actual tolerances are in the real world and there's quite a bit of difference from the datasheet.

mcnobby

Very very useful bit of information EvilDave, thanks very much !!
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

Go Up