Advertisement
Guest User

05.05.2016 WS2811 / Arduino PoC - working!

a guest
May 5th, 2016
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.20 KB | None | 0 0
  1. ///////////////////////////////////////
  2. //
  3. //  WS2811 Test Sketch
  4. //
  5. //  04.05.2016: First Version
  6. //  05.05.2016: Manual timing via NOP doesn't work.
  7. //              Switching to timer2 (PD3)
  8. //              Finally works! https://youtu.be/hwUaI-tJ2UE
  9. //
  10. ///////////////////////////////////////
  11.  
  12. /* Description of the WS2811 protocol:
  13.  *
  14.  * https://cdn-shop.adafruit.com/datasheets/WS2811.pdf
  15.  *  
  16.  *  0 is 0.5µs high, 2µs low
  17.  *  1 is 1.2µs high, 1.3µs low
  18.  *  half of those values for the 800kHz modules
  19.  *  
  20.  *  Timing between bits is less critical - 3µs are ok.
  21.  *  >6-9µs leads to reset=latching the data to the LEDs
  22.  *  
  23.  *  Thus trying bitbang on PD3
  24.  *  
  25.  */
  26.  
  27. #define LEDNO 50
  28. #define OFF 4
  29. #define ON 9
  30. #define BITLENGTH 20
  31.  
  32. uint8_t red = 0;
  33. uint8_t green = 85;
  34. uint8_t blue = 170;
  35. uint8_t leds = 0;
  36.  
  37. void setup() {
  38.   DDRD |= (1<<PD3);  // set PD3 as Output
  39.   PORTD &= ~(1<<PD3);  // set PD3 low
  40.   // disable Arduino lib timer 0
  41.   TCCR0A = 0;
  42.   TCCR0B = 0;
  43.  
  44.   TCCR2B = 0;  // reset TIMER2
  45.   TCCR2A = 0;
  46.   OCR2A = BITLENGTH;  // Total length of a bit for WS2811
  47.   for (int i=0; i<LEDNO; i++) {
  48.     send_bits(0, 0, 0);
  49.   }
  50.   delay_us(50);
  51. }
  52.  
  53. inline void set_timer() {
  54.   TIFR2 |= (1<<TOV2);  // Alternatively, TOV2 is cleared by writing a logic one to the flag
  55.   while (!(TIFR2 & (1 << TOV2)));  // Wait for overflow to occur
  56.   TCNT2 = 0;
  57. }
  58.  
  59. void send_bits(byte red, byte green, byte blue) {
  60.   cli();  // stop interrupts
  61.   TCCR2A = (1 << COM2B1) | (1 << WGM21) | (1 << WGM20);  // FastPWM to OCR2A
  62.   // COM2B1: Clear OC2B on Compare Match, set OC2B at BOTTOM
  63.   // WGM21, WGM20: Fast PWM ...
  64.   TCCR2B = (1 << WGM22) | (1 << CS20);  // No prescaling; starts PWM
  65.   // WGM22: ... Fast PWM Top OCR2A; CS20 = No prescaler
  66.  
  67. // manual unrolling - ugly!
  68. // red ...
  69.   TCNT2 = 0;
  70.   (red & (1<<7)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  71.   set_timer();
  72.   (red & (1<<6)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  73.   set_timer();
  74.   (red & (1<<5)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  75.   set_timer();
  76.   (red & (1<<4)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  77.   set_timer();
  78.   (red & (1<<3)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  79.   set_timer();
  80.   (red & (1<<2)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  81.   set_timer();
  82.   (red & (1<<1)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  83.   set_timer();
  84.   (red & (1<<0)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  85.   set_timer();
  86.  
  87. // green ...
  88.   (green & (1<<7)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  89.   set_timer();
  90.   (green & (1<<6)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  91.   set_timer();
  92.   (green & (1<<5)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  93.   set_timer();
  94.   (green & (1<<4)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  95.   set_timer();
  96.   (green & (1<<3)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  97.   set_timer();
  98.   (green & (1<<2)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  99.   set_timer();
  100.   (green & (1<<1)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  101.   set_timer();
  102.   (green & (1<<0)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  103.   set_timer();
  104.  
  105. // blue ...
  106.   (blue & (1<<7)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  107.   set_timer();
  108.   (blue & (1<<6)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  109.   set_timer();
  110.   (blue & (1<<5)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  111.   set_timer();
  112.   (blue & (1<<4)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  113.   set_timer();
  114.   (blue & (1<<3)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  115.   set_timer();
  116.   (blue & (1<<2)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  117.   set_timer();
  118.   (blue & (1<<1)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  119.   set_timer();
  120.   (blue & (1<<0)) ? OCR2B = ON : OCR2B = OFF;  // set timer for bit on or off
  121.   TIFR2 |= (1<<TOV2);  // Alternatively, TOV2 is cleared by writing a logic one to the flag
  122.   while (!(TIFR2 & (1 << TOV2)));  // Wait for overflow to occur
  123.  
  124.   sei();  // start interrupts
  125.   while (TCNT2 < ON);
  126.   TCCR2B = 0;  // Reset TIMER2 again
  127.   TCCR2A = 0;  // and switching it off.
  128.   PORTD &= ~(1<<PD3);  // set PD3 low
  129. }
  130.  
  131. // --- some weirdo delay function --------------------------------------------
  132. void delay_us (int16_t us) {
  133.   for (uint16_t i=0; i<us; i++) {
  134.       for (int j=0; j<16; j++) {
  135.         asm volatile ("nop");
  136.       }
  137.   }
  138. }
  139.  
  140. void loop() {
  141. /*
  142.   for (int i=0; i<LEDNO; i++) {
  143.     red++;
  144.     green++;
  145.     blue++;
  146.     send_bits(red, green, blue);
  147.   }
  148.   delay_us(50);
  149.   delay_us(30000);
  150. */
  151.  
  152. // /*
  153.   for (int k=0; k<3; k++) {
  154.     switch (k) {
  155.      case 0: red = 255; green = 0; blue = 0; break;
  156.      case 1: red = 0; green = 255; blue = 0; break;
  157.      case 2: red = 0; green = 0; blue = 255; break;
  158.     }
  159.     for (int i=0; i<LEDNO; i++) {
  160.       for (int j=0; j<LEDNO; j++) {
  161.         (i==j) ? send_bits(red, green, blue) : send_bits(0, 0, 0);
  162.       }
  163.       delay_us(50);
  164.       delay_us(10000);
  165.     }
  166.   }
  167. //  */
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement