Author Topic: Digital rgb ledstrip driven by RFDuino  (Read 46998 times)

zabowsky

  • RFduino Newbie
  • *
  • Posts: 6
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #60 on: October 27, 2014, 05:06:39 PM »

I just pushed the hex file to my board and got the same result as with the standalone sketch. One LED cycling through colors at an appropriate brightness, and the others all bright white.

...and then I accidentally disconnect the ground pin from the ring and it started working perfectly!...I'm not yet sure what to make of that. I suspected a bad solder joint, but there's nothing obviously shorted when I look closely.

I cleaned up and re-soldered the ring connections and get the same behavior. It looks great when GND is disconnected. Bright white with it connected.

gcgasson

  • RFduino Newbie
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #61 on: October 27, 2014, 09:43:13 PM »
Non library sketch worked after a little tweeking. Thank you.

What did you tweak?????

Hi, I have the Neopixel Ring 24Led which uses the 4pin WS2412B which timing is slightly different. If I use your non library unit then I can run with max 20 leds but it is if the sync goes out then all hell breaks loose. So finally I remove two of the NOP lines at Zero and One and that made it better but still not perfect. So finally I reduced the voltage to about 3.6V and all started working 100%

So my findings are that VCC and datalines need to be at the same voltage. Well I will try it this morning as the RFDuino is 3V dataline and I was running the Ring at 5V so I will build a shift level converter.

tolson

  • Global Moderator
  • *****
  • Posts: 880
  • Karma: +21/-0
    • View Profile
    • Thomas Olson Consulting
Re: Digital rgb ledstrip driven by RFDuino
« Reply #62 on: October 29, 2014, 08:03:43 AM »
Non library sketch worked after a little tweeking. Thank you.

What did you tweak?????

Hi, I have the Neopixel Ring 24Led which uses the 4pin WS2412B which timing is slightly different. If I use your non library unit then I can run with max 20 leds but it is if the sync goes out then all hell breaks loose. So finally I remove two of the NOP lines at Zero and One and that made it better but still not perfect. So finally I reduced the voltage to about 3.6V and all started working 100%

So my findings are that VCC and datalines need to be at the same voltage. Well I will try it this morning as the RFDuino is 3V dataline and I was running the Ring at 5V so I will build a shift level converter.

Yes, it is good idea to have a level shifter if you are going to run the string at 5 volts while running the controller at 3.3v. I have not had any loss of  sync using 3.3 volts on long strings of 60+. Can you verify that your long string works OK if all is supplied with 3.3 volts instead of 5 volts?

gcgasson

  • RFduino Newbie
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #63 on: October 29, 2014, 09:10:01 AM »
Non library sketch worked after a little tweeking. Thank you.

What did you tweak?????

Hi, I have the Neopixel Ring 24Led which uses the 4pin WS2412B which timing is slightly different. If I use your non library unit then I can run with max 20 leds but it is if the sync goes out then all hell breaks loose. So finally I remove two of the NOP lines at Zero and One and that made it better but still not perfect. So finally I reduced the voltage to about 3.6V and all started working 100%

So my findings are that VCC and datalines need to be at the same voltage. Well I will try it this morning as the RFDuino is 3V dataline and I was running the Ring at 5V so I will build a shift level converter.

Yes, it is good idea to have a level shifter if you are going to run the string at 5 volts while running the controller at 3.3v. I have not had any loss of  sync using 3.3 volts on long strings of 60+. Can you verify that your long string works OK if all is supplied with 3.3 volts instead of 5 volts?

Hi, my 24 LED works perfect when I run it at 3.3V.

reconbot

  • RFduino Newbie
  • *
  • Posts: 1
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #64 on: November 15, 2014, 06:40:55 PM »
Any luck getting the library working on the 1.5.8 ide?

lsnyman

  • RFduino Sr. Member
  • ****
  • Posts: 145
  • Karma: +1/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #65 on: December 01, 2014, 08:02:33 PM »
I have some inventory of RGB LED strips with 144 WS2812B per/m similar to Adafruit http://www.adafruit.com/products/1507
price is $39.95 plus shipping.
PM me if anyone is interested

tolson

  • Global Moderator
  • *****
  • Posts: 880
  • Karma: +21/-0
    • View Profile
    • Thomas Olson Consulting
Re: Digital rgb ledstrip driven by RFDuino
« Reply #66 on: December 02, 2014, 03:08:53 PM »
Any luck getting the library working on the 1.5.8 ide?

Do you really need the library?  For a dedicated application and the simplicity of the RFduino I find the subroutine function good enough. And takes up less storage, if that is an issue. and less interfering with other sensors / libraries.

How are you planning to use the LEDs?


lemonade

  • RFduino Newbie
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #67 on: December 18, 2014, 03:22:42 PM »
I recently updated my Arduino IDE to 1.5.7 and my RFDuino library to the latest 2.2.2.

I am using a single Adafruit NeoPixel.  When I upload my code the LED remains at half brightness and never turns off.  I have seen this issue mentioned before, but could not find a solution to the problem.

I'm using the Tolson mod of Adafruit_NeoPixel.h.

It still works fine if I use Arduino 1.5.6-r2, but I need the newer version of the IDe.

Anyone experience this and have a solution?

tolson

  • Global Moderator
  • *****
  • Posts: 880
  • Karma: +21/-0
    • View Profile
    • Thomas Olson Consulting
Re: Digital rgb ledstrip driven by RFDuino
« Reply #68 on: December 18, 2014, 10:11:04 PM »
I recently updated my Arduino IDE to 1.5.7 and my RFDuino library to the latest 2.2.2.

I am using a single Adafruit NeoPixel.  When I upload my code the LED remains at half brightness and never turns off.  I have seen this issue mentioned before, but could not find a solution to the problem.

I'm using the Tolson mod of Adafruit_NeoPixel.h.

It still works fine if I use Arduino 1.5.6-r2, but I need the newer version of the IDe.

Anyone experience this and have a solution?
The Tolson mod is only for 1.5.6-r2.
No library needed. Especially for just 1 pixel.
Try this and adapt it to your needs.

Code: [Select]
// WS2812_RFduino_Test
// By Thomas Olson
// teo20140220.01
// teo20140719.01 Modified for Arduino 1.5.7
// 20141022.. verified works with Arduino 1.5.8
// No complicated Pixel Library needed.
// Tested with WS2812B 4 pin versions.

int ws2812pin = 2; // WS2812B bus is pin 2

const int nPIXELS = 1; // The dongle has 1 WS2812B

const int nLEDs = nPIXELS * 3;
uint8_t ledBar[nLEDs];


void setup() {

  pinMode(ws2812pin, OUTPUT);
  digitalWrite(ws2812pin, LOW);
  // Initialize the ledBar array - all LEDs OFF.
  // W.C. clear 60 pixels
//  nLEDs = 180;
 
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0x00;
  }
  loadWS2812();
 
  delay(1);
}

void loop() {

//  timetest0s();   
  chaser();
 
}

void timetest0s(void){
 for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0x00;
  }
  loadWS2812();
}

void timetest1s(void){
 for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0xFF;
  }
  loadWS2812();
}


void chaser(void){
   
 for(int wsOut = 0; wsOut < nLEDs; wsOut+=3){ // green
    ledBar[wsOut] = 0x3c;
    loadWS2812();
   
    delay(10 * 60/nPIXELS);
   
    ledBar[wsOut] = 0x00;
    loadWS2812();
  }

  delay(10 * 60/nPIXELS);
 
 for(int wsOut = 1; wsOut < nLEDs; wsOut+=3){ // red
    ledBar[wsOut] = 0x3c;
    loadWS2812();
   
    delay(10 * 60/nPIXELS);
   
    ledBar[wsOut] = 0x00;
    loadWS2812();
  }
 
  delay(10 * 60/nPIXELS);
 
   for(int wsOut = 2; wsOut < nLEDs; wsOut+=3){ // blue
    ledBar[wsOut] = 0x3c;
    loadWS2812();
   
    delay(10 * 60/nPIXELS);
   
    ledBar[wsOut] = 0x00;
    loadWS2812();
  }

  delay(10 * 60/nPIXELS);
 
}

void loadWS2812(){
 
  noInterrupts();

  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    for(int x=7; x>=0; x--){
      NRF_GPIO->OUTSET = (1UL << ws2812pin);
      if(ledBar[wsOut] & (0x01 << x)) {
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
     
      }else{
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );     
      }
    }
  }
  delayMicroseconds(50); // latch and reset WS2812.
  interrupts(); 
}

lemonade

  • RFduino Newbie
  • *
  • Posts: 7
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #69 on: December 22, 2014, 04:16:17 PM »
Great!  Thank you.  I modified your sketch a bit to accommodate a fading animation.  I've included it here in case anyone is interested.

I hope this will also solve timing issues that were forcing the BLE radio to time out when connected to an iOS app.  I had to make heavy use of while(RFduinoBLE.radioActive) when using the Adafruit library.

Code: [Select]
//PAIRING
const uint8_t amb_PR[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const uint8_t amb_PG[] = { 255, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 247, 246, 244, 243, 241, 240, 238, 236,
                           234, 232, 230, 228, 226, 223, 221, 218, 216, 213, 210, 207, 204, 201, 198, 194, 191, 187, 184, 180,
                           176, 173, 169, 164, 160, 156, 152, 147, 143, 138, 133, 129, 124, 119, 114, 108, 103, 98, 92, 87, 81,
                           75, 69, 64, 57, 51, 45, 39, 32, 26, 19, 13, 6, 0, 6, 12, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 78,
                           84, 89, 94, 100, 105, 110, 115, 120, 124, 129, 134, 138, 143, 147, 151, 156, 160, 164, 168, 171, 175,
                           179, 182, 186, 189, 193, 196, 199, 202, 205, 208, 211, 214, 216, 219, 221, 224, 226, 228, 230, 232,
                           234, 236, 238, 239, 241, 243, 244, 245, 247, 248, 249, 250, 251, 252, 252, 253, 253, 254, 254, 255,
                           255, 255, 255 };
const uint8_t amb_PB[] = { 255, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 247, 246, 244, 243, 241, 240, 238, 236,
                           234, 232, 230, 228, 226, 223, 221, 218, 216, 213, 210, 207, 204, 201, 198, 194, 191, 187, 184, 180,
                           176, 173, 169, 164, 160, 156, 152, 147, 143, 138, 133, 129, 124, 119, 114, 108, 103, 98, 92, 87, 81,
                           75, 69, 64, 57, 51, 45, 39, 32, 26, 19, 13, 6, 0, 6, 12, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 78,
                           84, 89, 94, 100, 105, 110, 115, 120, 124, 129, 134, 138, 143, 147, 151, 156, 160, 164, 168, 171, 175,
                           179, 182, 186, 189, 193, 196, 199, 202, 205, 208, 211, 214, 216, 219, 221, 224, 226, 228, 230, 232,
                           234, 236, 238, 239, 241, 243, 244, 245, 247, 248, 249, 250, 251, 252, 252, 253, 253, 254, 254, 255,
                           255, 255, 255 };

//LED lighitng
uint8_t REDS[255];
uint8_t GREENS[255];
uint8_t BLUES[255];
uint8_t TABLE_SIZE;
uint16_t UPDATE;

uint8_t red;
uint8_t green;
uint8_t blue;

//STATES
const int OFF = 0; 
uint8_t state = OFF;

//TIMING
const int AMBIENT_PAIRING_TABLE_SIZE = (sizeof(amb_PR));
const int AMBIENT_PAIRING_CYCLE    = 5067;
const int AMBIENT_PAIRING_UPDATE    = (AMBIENT_PAIRING_CYCLE / AMBIENT_PAIRING_TABLE_SIZE);

//ANIMATION VARIABLES
uint32_t lastUpdate = 0;
uint8_t animIndex = 0;

//WS2812
int ws2812pin = 2; // WS2812B bus is pin 2
const int nPIXELS = 2; // The dongle has 1 WS2812B
const int nLEDs = nPIXELS * 3;
uint8_t ledBar[nLEDs];


void setup()
{
  pinMode(ws2812pin, OUTPUT);
  digitalWrite(ws2812pin, LOW);
  // Initialize the ledBar array - all LEDs OFF.
  // W.C. clear 60 pixels
//  nLEDs = 180;
 
  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0x00;
  }
  loadWS2812();
 
  //SETUP ANIMATION TABLES AND INFO
  TABLE_SIZE = AMBIENT_PAIRING_TABLE_SIZE;
  UPDATE = AMBIENT_PAIRING_UPDATE;
 
  REDS[TABLE_SIZE] = {}; 
  memcpy( REDS, amb_PR, TABLE_SIZE );
 
  GREENS[TABLE_SIZE] = {}; 
  memcpy( GREENS, amb_PG, TABLE_SIZE );
 
  BLUES[TABLE_SIZE] = {}; 
  memcpy( BLUES, amb_PB, TABLE_SIZE );
 
  delay(1);
}

void loop()
{
  //timetest0s();   
  //chaser();
  animate();
}

void animate()
{
  int i;
 
  if ((millis() - lastUpdate) > UPDATE)
  {
    lastUpdate = millis();

    //WS2812
    for (i = 0; i < nLEDs; i++)
    {
      red = (127 * REDS[animIndex]) / 256;
      green = (127 * GREENS[animIndex]) / 256;
      blue = (127 * BLUES[animIndex]) / 256;
     
      for(int wsOut = 0; wsOut < nLEDs; wsOut+=3)
      {
        ledBar[wsOut] = green;
        ledBar[wsOut+1] = red;
        ledBar[wsOut+2] = blue;
      }
    }
   
    loadWS2812();
     
    animIndex++;
    if (animIndex >= TABLE_SIZE)
    {
      animIndex = 0;
    }
  }
}

void timetest0s(void){
 for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0x00;
  }
  loadWS2812();
}

void timetest1s(void){
 for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    ledBar[wsOut] = 0xFF;
  }
  loadWS2812();
}


void chaser(void){
 for(int wsOut = 0; wsOut < nLEDs; wsOut+=3){ // red
    ledBar[wsOut] = 0;
    ledBar[wsOut+1] = 255;
    ledBar[wsOut+2] = 0;
    loadWS2812();
   
    delay(10 * 60/nPIXELS);
   
    ledBar[wsOut] = 0;
    ledBar[wsOut+1] = 0;
    ledBar[wsOut+2] = 0;
    loadWS2812();
  }

  delay(10 * 60/nPIXELS);
 
 for(int wsOut = 0; wsOut < nLEDs; wsOut+=3){ // green
    ledBar[wsOut] = 255;
    ledBar[wsOut+1] = 0;
    ledBar[wsOut+2] = 0;
    loadWS2812();
   
    delay(10 * 60/nPIXELS);
   
    ledBar[wsOut] = 0;
    ledBar[wsOut+1] = 0;
    ledBar[wsOut+2] = 0;
    loadWS2812();
  }
 
  delay(10 * 60/nPIXELS);
 
  for(int wsOut = 0; wsOut < nLEDs; wsOut+=3){ // blue
    ledBar[wsOut] = 0;
    ledBar[wsOut+1] = 0;
    ledBar[wsOut+2] = 255;
    loadWS2812();
   
    delay(10 * 60/nPIXELS);
   
    ledBar[wsOut] = 0;
    ledBar[wsOut+1] = 0;
    ledBar[wsOut+2] = 0;
    loadWS2812();
  }

  delay(10 * 60/nPIXELS);
 
}

void loadWS2812(){
 
  noInterrupts();

  for(int wsOut = 0; wsOut < nLEDs; wsOut++){
    for(int x=7; x>=0; x--){
      NRF_GPIO->OUTSET = (1UL << ws2812pin);
      if(ledBar[wsOut] & (0x01 << x)) {
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
     
      }else{
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );     
      }
    }
  }
  delayMicroseconds(50); // latch and reset WS2812.
  interrupts(); 
}
« Last Edit: December 22, 2014, 05:20:41 PM by lemonade »

cromas

  • RFduino Jr. Member
  • **
  • Posts: 26
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #70 on: January 09, 2015, 01:07:02 PM »
No library needed. Especially for just 1 pixel.
Try this and adapt it to your needs.

Thank you thank you thank you! This is so fantastic, and way better than the huge, LGPL-chained Adafruit library. This worked on the first try for me (w/ Arudino 1.5.8 + RFDuino 2.2.2). That happens approximately NEVER in engineering. I am so pleased! :D

cromas

  • RFduino Jr. Member
  • **
  • Posts: 26
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #71 on: January 09, 2015, 05:28:57 PM »
Code: [Select]
    for(int x=7; x>=0; x--){
      NRF_GPIO->OUTSET = (1UL << ws2812pin);
      if(ledBar[wsOut] & (0x01 << x)) {
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
     
      }else{
        NRF_GPIO->OUTCLR = (1UL << ws2812pin);
        __ASM ( \
              " NOP\n\t" \
              " NOP\n\t" \
              " NOP\n\t" \
              );     
      }
    }

I'm seeing behavior where a sequence flashing (255,0,0)->delay(4656µs)->(0,0,0)->delay(4656µs) is coming out with uneven timing -- every sixth (I think) red flash is ~2x longer than it should be. I've eliminated all other possibilities from my code:

  • I ran the same pattern on a normal PWM RGB LED and it displayed correctly,
  • at the end of every loop() I dump getMicros() to serial, and observe only a +/- 30µs variance, which would not be visible given that its ~0.3% of the total on/off cycle,
  • updating every 4656µs corresponds to updating at ~215Hz -- I understand this to be orders of magnitude lower than the maximum write rate of the chip, and safely within the ~328Hz that Adafruit quotes for the LED controller
So I'm down to wondering if the serial protocol is occasionally failing to update and thus the LED is "sticking" on for a cycle.

Could you help me understand what's going on in the code here? I'm assuming the NOPs here are for the µs-critical timing for the serial waveform. But I'm confused why you're setting the pin high before you check if the next bit is high. And I'd like to understand how you determined 5 NOPs and 3 NOPs to be appropriate, especially because the duty cycle is supposed to be different between a 1 and a 0.
« Last Edit: January 09, 2015, 05:54:18 PM by cromas »

tolson

  • Global Moderator
  • *****
  • Posts: 880
  • Karma: +21/-0
    • View Profile
    • Thomas Olson Consulting
Re: Digital rgb ledstrip driven by RFDuino
« Reply #72 on: January 09, 2015, 05:46:47 PM »
The whole routine is involved in the critical timing. Setting the pin high before testing is because it has to be set high anyways and it is a way to get a head start on it while the test is happening to decide when to set it low. It also depends on how the compiler creates assembler. Changing optimizations flags on the compiler will also affect the timing. The subroutine works with the default RFduino compiler settings.

cromas

  • RFduino Jr. Member
  • **
  • Posts: 26
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #73 on: January 09, 2015, 06:00:04 PM »
The whole routine is involved in the critical timing. Setting the pin high before testing is because it has to be set high anyways and it is a way to get a head start on it while the test is happening to decide when to set it low. It also depends on how the compiler creates assembler. Changing optimizations flags on the compiler will also affect the timing. The subroutine works with the default RFduino compiler settings.

It seems then that we ought to remove the compiler from the equation and put the whole routine into assembly. I believe the guide at http://www.instructables.com/id/Bitbanging-step-by-step-Arduino-control-of-WS2811-/ covers this pretty well (just found it). I'm going to work on it a little and see if I can get it working exactly, because I think I've exhausted other potential locations of the problem (see my edit on my last reply). However, I'm not very familiar with pins/ports and assembly yet, so please let me know if you have any advice on this or think the code there isn't portable for some reason.

EDIT: nevermind, this is a Cortex M0, which (please correct me if I'm wrong) is an entirely different instruction set. My understanding then is that this article can be applied to RFDuino, but the assembly code will be totally different.
« Last Edit: January 09, 2015, 06:22:39 PM by cromas »

cromas

  • RFduino Jr. Member
  • **
  • Posts: 26
  • Karma: +0/-0
    • View Profile
Re: Digital rgb ledstrip driven by RFDuino
« Reply #74 on: January 09, 2015, 06:33:56 PM »
Also, while I agree that the routine works until a certain threshold, I have the strong suspicion that it's "only just" working and that the tolerances may need to be improved for the speed I'm updating at. 215 updates/sec should be well-within the capabilities of the board and LED controller.