LED strip (LPD8806 Library ) Blocking

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
scrubbl3r
 
Posts: 21
Joined: Sat Jul 13, 2013 6:26 pm

LED strip (LPD8806 Library ) Blocking

Post by scrubbl3r »

Hello,

I've got an LPD 8806 LED strip being controlled by the LPD 8806 library for Arduino.
The strip is great and the library works well but when i try to run the strip at the same time that I'm controlling my stepper motor (AccelStepper library) the motor lugs. Through trial and error I've come to believe that this is because the LPD8806 library is 'Blocking'.

Does anyone have any experience with this? Is there a workaround or another LPD8806 library which is non-blocking?

If there is no simple solution to using the LPD8806 with the AccelStepper library, is there another LED strip or array which has a robust non-blocking library to support it?

Thanks :)

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: LED strip (LPD8806 Library ) Blocking

Post by adafruit_support_mike »

Sounds like one of those issues where the devil is in the details.

Post a photo of your hardware (800x600 images usually work best, with enough light and focus to see the soldering and connections) and your code (between CODE tags please), and we'll take a look.

scrubbl3r
 
Posts: 21
Joined: Sat Jul 13, 2013 6:26 pm

Re: LED strip (LPD8806 Library ) Blocking

Post by scrubbl3r »

Hi Mike,

thanks for looking into this with me. To give a little more context, I'm positive that it's not a wiring issue. I've got the LEDs and the stepper motor wired up properly and they run just fine with the code posted below.. both work just fine individually, it's when i try to run them simultaneously that the motor lugs.

I've posted an image of my hardware setup just to show you what this all looks like. The setup is a MindWave mobile EEG headset which talks to a bluetooth dongle attached to a Raspberry Pi.. the Pi then takes the mindwave data packets being transmitted from the MindWave mobile headset and parses them and does a little math to make their values more friendly for the motor and the LEDs on the other end.

Next, the parsed values are sent through the serial port to a Raspberry Pi Alamode (an arduino shield with a RTC embeded). The bytes are then parsed and recompiled back into a function call and arguments.. these are what control the motor and LEDs.

Anyways, its a lot of steps and quite a bit of complexity but it a certainty that all of this stuff is wired properly, connecting and parsing etc.. all the way up to the point where both devices try to operate simultaneously.

In the code below you'll notice one line in the function called "control()" that is commented out. Uncomment this and the motor lugs. This leads me to believe that the problem is not within any of my code, but that the LPD8806 library is "blocking".. using delays (or something) behind the scenes to control the LEDs.

Anyhow, have a look and let me know what you think. If there's anything i can do to make things more clear, let me know.

This is the Arduino code..

Code: Select all

#include "LPD8806.h"
#include "SPI.h"
#include <Wire.h>
#include <string.h>
#include <AccelStepper.h>

const int BAUD = 9600;

// led strip
int nLEDs = 32;
int dataPin  = 8;
int clockPin = 9;
LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);
int ledOn = 0;
float ledR = 0;
float ledRTarget = 0;
float ledG = 0;
float ledGTarget = 0;
float ledB = 0;
float ledBTarget = 0;
float easeRate = 25;

// serial in <<--
const int BUFFLEN=100;
char serialBuffer[BUFFLEN+1] ="";
int  serInIndx=0;
char inChar;
// split strings
char INBOUND[BUFFLEN+1];
char stringBuff[BUFFLEN+1];
int tCount=0;
// function pointers
char* FUNC[7];
// stepper args
AccelStepper stepper(AccelStepper::DRIVER); // pin2= Step, pin3= direction

// stepper vars
int stepOn = 1;
float m1_easeRate = 125;
float m1_maxSpeed = 10000;
float m1_targetSpeed = 0;
float m1_speed = 0;


void setup(){
  Serial.begin(BAUD);
  strip.begin();
  strip.show();
  stepper.setEnablePin(4);
  stepper.setMaxSpeed(m1_maxSpeed);
}

void loop(){
  readSerialString();
  setFunctions(FUNC[0], FUNC[1], FUNC[2], FUNC[3], FUNC[4], FUNC[5], FUNC[6]);
  FUNC[0] = "__"; // this should set the functions vars one time only
  control();
}

void setFunctions (String argA, String argB, String argC, String argD, String argE, String argF, String argG) {
  ledOn = atol(FUNC[1]);
  ledRTarget = atol(FUNC[2]);
  ledGTarget = atol(FUNC[3]);
  ledBTarget = atol(FUNC[4]);
  stepOn = atol(FUNC[5]);
  m1_targetSpeed = atol(FUNC[6]);
}


void control(){
  if (ledOn == 1){
    ledR = ledR + (ledRTarget - ledR) / easeRate;
    ledG = ledG + (ledGTarget - ledG) / easeRate;
    ledB = ledB + (ledBTarget - ledB) / easeRate;
    // colorWipe(strip.Color(ledR, ledG, ledB), 0);  <--- Mike, this is the line that lugs the motor
  }
  if (stepOn == 1){
    m1_speed = m1_speed + (m1_targetSpeed - m1_speed) /m1_easeRate;
    
    if (m1_speed > m1_maxSpeed) {
      m1_speed = m1_maxSpeed;
    } else if (m1_speed < (m1_maxSpeed*-1)) {
      m1_speed = (m1_maxSpeed*-1);
    }
    
    stepper.setSpeed(m1_speed);
    stepper.runSpeed();
  }
}


// CONTROL THE LED STRIP
void colorWipe(uint32_t c, uint8_t wait) {
  int i;
  for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
  }
}



// READ THE SERIAL PORT - RECOMPILE FUNCTION CALL AND ARGUMENTS
void readSerialString () {
       while (Serial.available()){ 
         inChar = Serial.read();
         if (inChar=='\n') {
           char *str;
           char *p;
           for(str=strtok_r(serialBuffer, "," , &p); str; str=strtok_r(NULL, "," , &p)) {
             FUNC[tCount++] = str;
             //tCount++;
           }
           //memset(serialBuffer, 0, sizeof(BUFFLEN));
           tCount = 0;    
           serInIndx = 0;
          } else {
            serialBuffer[serInIndx] = inChar;
            serInIndx++;
          }
       }
}

The hardware..
Image

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: LED strip (LPD8806 Library ) Blocking

Post by adafruit_support_mike »

Okay, I see the trouble..

Neither the AccelStepper library nor the LPD8806 library use interrupts or play games with the microcontroller's timers.

AccelStepper uses an elegant extension of the BlinkWithoutDelay strategy, keeping track of what the motor should do on its next step and when that step should happen. To run the motors, you call .run() on each pass through loop(). Every time you call .run(), it checks to see if that motor needs to take its next step yet. If so, it steps the motor and calculates the type and time of the next step. If the next step isn't due yet, .run() simply returns.

The LPD8806 library blasts lots of bytes out on the microcontroller's hardware SPI pins, and each update of the strip happens quickly.

The trouble is that your colorWipe() function blocks while it does multiple updates of the LED strip.

Try this:

Code: Select all

// CONTROL THE LED STRIP
void colorWipe(uint32_t c, uint8_t wait) {
  int i;
  for (i=0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      stepper.run();  // <-- give the motor a chance to update
  }
}

scrubbl3r
 
Posts: 21
Joined: Sat Jul 13, 2013 6:26 pm

Re: LED strip (LPD8806 Library ) Blocking

Post by scrubbl3r »

Thanks a lot, Mike! This helped a lot!

Unfortunately, building on your hunch and doing some further testing I've isolated the real show stopper - the ".show()" method inside of the LPD8806 library. The ".show()" method is crushingly slow - reducing the updating of my motor steps by approximately 80%. The for loop calling .setPixelColor() is creating very little overhead. Even when i pull the ".show()" method out of the for loop int the "colorWipe()" method and call it only once each time the for loop ends, it still totally stomps the motor step update (huge speed loss).

Without altering the actual LPD8806 library, i believe we've run out of options for making this run fast enough for my project :(

Any ideas for optimizing the LPD8806 library or suggestions for a more efficient LED setup would be really appreciated.

Thanks a ton for your help, Mike. It's people like you that make this stuff a lot less aggravating ;)

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”