Adafruit_NeoPixel and Servo.h

Hello, I am new to Arduino, I have read several tutorials and documentation about all of this but I am not really understanding it all. I have an issue where my servos work great so long as I am not using the LEDs (Which are controlled by Neopixel). As soon as I introduce the LED code it causes the LEDs to jitter uncontrollably.

Here is the code I am currently using. I read an article that suggested that these 2 libraries are not compatible but it was over my head from a coding standpoint as I am trying to learn. Also, it was from 2014 so I was hopeful that this was fixed since then or there was a better way to handle it.

//========================================
// ---------------LIBRARIES---------------
//========================================
#include <Servo.h>                // Get Servo library
#include <Adafruit_NeoPixel.h>    // Get NeoPixel library for WS2812B LEDs

//========================================
// ---------------CONSTANTS---------------
//========================================
// Assign arduino pins for Servos
const int servoPin_Neck = 5;                           // Lowest Neck Segment pan servo is on this pin (FS5103R Continuous Rotation Servo)
const int servoPin_DrivePlate = 6;                     // Drive Plate (Eye Segment) pan servo is on this pin (FS5103R Continuous Rotation Servo)
const int servoPin_EyeTilt = 7;                        // Eye Tilt pan servo is on this pin (9 gram SG90 180 Deg rotation Servo)
const int servoPin_SensorSegment = 8;                  // Sensor Segment pan servo is on this pin (FS5103R Continuous Rotation Servo)

// Assign arduino pins for LEDs
#define LED_Pin 4                                     // Pixels are on this pin
#define LED_Num 11                                    // Number of LEDs
//======================================

unsigned long currentMicros = 0;                    // Current Time

// Create Objects to attach servos and LEDs to.
Servo servo_Neck;  
Servo servo_DrivePlate;
Servo servo_EyeTilt;
Servo servo_SensorSegment;
Adafruit_NeoPixel LEDs(LED_Num, LED_Pin, NEO_GRB + NEO_KHZ800);

//======================================
//======================================
void setup() {
  servo_Neck.write(85);           //85 or 86
  servo_Neck.attach(servoPin_Neck);                       // Attach the servo to the pin
  
  servo_DrivePlate.write(85);     //85
  servo_DrivePlate.attach(servoPin_DrivePlate);           // Attach the servo to the pin
  
  servo_EyeTilt.write(90);
  servo_EyeTilt.attach(servoPin_EyeTilt);                 // Attach the servo to the pin
  
  servo_SensorSegment.write(85);  //84 or 85
  servo_SensorSegment.attach(servoPin_SensorSegment);     // Attach the servo to the pin
  
  // LED setup
  LEDs.begin();            // INITIALIZE NeoPixel pixels object
  LEDs.show();             // Turn OFF all pixels
}
//======================================
//======================================
void loop() {
  // IdleState_LEDs();                           
  IdleState_Neck();
  IdleState_DrivePlate();
  IdleState_SensorSegment();
  
}
//======================================

//==================================================================================================================
//------- IDLE STATE FUNCTIONS ---------
//==================================================================================================================
void IdleState_LEDs() {
  uint32_t reddim = LEDs.Color(255, 0, 0);                             // create color "reddim"
  LEDs.fill(reddim, 0, LED_Num);                                      // Change all LED values to reddim
  LEDs.setBrightness(5);
  LEDs.show();                                                      // Change LEDs
}
//=====================
void IdleState_Neck() {
    servo_Neck.write(85);                //
 }
//=====================
void IdleState_DrivePlate() {
    servo_DrivePlate.write(85);                //
}
//=====================
void IdleState_SensorSegment() {
    servo_SensorSegment.write(85);                //
}

The servo library uses interrupts to generate the servo control signal. Adafruit_Neopixel (as well as FastLED) has to disable interrupts in order to generate the control signal for the LEDs. This makes the libraries incompatible with each other.

The millis() counter will also run slow with Adafruit_Neopixel because of missed interrupts.

Ok thats what I have been reading...but what I cant find is how to get around this? I need one sketch that will drive my LEDs and my Servos so that they can all work together as one. I can't seem to find any info on how to work around this. I find it hard to believe noone has ever had LEDs and servos working together from a single sketch.

1 Like

FYI I have already looked at the TiCoServo library which is designed to get around this. But I am using an Uno and according to the documentation if I use this library I can only use pins 9 and 10 for servos. But my project has 4 servos in them that need to run independently. So this isnt an option either.

First of all..

Don't update your neopixles on every iteration of the loop. That's WAY more than you need. Try maybe 15..30 changes per second. 15 should be plenty for your typical human. Secondly, you can run servos without using interrupts if you are careful to never use delay(). Just every about 15 milliseconds put out a 1..2 ms pulse to set their position. Actually, you can cheat and use delay() for the 1..2 ms pulse and it'll probably work fine.

-jim lee

OK so jimLee, thanks for the response. I am 1000% sure you are right. I am going to reveal my level of noob by saying I have NO IDEA what you just said!! HAHA

So I just started learning about arduino code, and from what I can tell I can either put code in my setup function (where it only gets run once), or I can put it in my loop function (where it gets run constantly). And I can make separate functions but they only run from what I can tell if they are in the setup or loop functions.

How do I tell it to only update x number of times per second? Or how do I put out a pulse every x milliseconds?

And please I learn best from examples. Just explaining it to me is likely going to confuse me even more.

Here's an example for your LED timer..

#include <timeObj.h>


timeObj LEDTimer(200);  // Create a 200ms timer.

void setup(void) {

   // Do youe LED setup stuff..
}


void loop(void) {

   if (LEDTimer.ding()) {     // If the timer has expired..
                              // Do your LED update/drawing here.
      LEDTimer.start();       // Restart your LED timer.
   }
   // DO other loop stuff you want.
}

Look in the library manager for LC_baseTools, install that and this will compile for you.

Hope this helps.

-jim lee

You'll never get satisfactory NeoPixel / Servo performance using an Uno. If you must stick with an Uno, then switch to an APA102-type LED strip. Adafruit calls these DotStar. They use a dedicated clock signal along with the data signal. This relaxes the tight data timing requirement of NeoPixels meaning that interrupts can be left enabled, allowing the Servo library to work properly.

If you can't switch to APA102, then switch to a Teensy 3.x or ESP8266-based board. There are libraries available for both of these that run NeoPixels using DMA techniques (the Uno and other AVR-based boards don't offer DMA). This again allows interrupts to remain enabled and the Servos operating properly.

Another option would be to use a servo driver board, most of which use the PCA9685 PWM driver chip which is controller over the I2C bus. That would allow you to control up to 16 servos.