I'm working on consolidating stepper motor control to the same board I'm using to blink NeoPixels randomly (colour & timing) but see a BIG problem when the Neos come on they affect the constant speed rotation of the stepper. Looking at the two libraries (Adafruit_NeoPixel.h & AccelStepper.h) I can't see why that would be. The power is supplied by a 12V/600mA wallwart and the board has a 5V/500mA voltage regulator to power the Neos (and the TMC2208 SilentStepstick stepper motor board, a drop-in replacement for A4988).
In the video, you can see the stepper drop in speed at roughly the 6.5 second mark: https://youtu.be/JG9Y_WNESVo
The code for the blinking Neos is from post #6 here: https://forum.arduino.cc/t/im-want-to-make-pixels-on-a-string-blink-independently-and-randomly/497172/5
#define DEBUG_MODE
#include <AccelStepper.h> // https://github.com/waspinator/AccelStepper
#include <Adafruit_NeoPixel.h> // https://github.com/adafruit/Adafruit_NeoPixel
// Define pins for stepper motor control, and others
#define DIR_PIN 8 // Req'd for AccelStepper
#define STEP_PIN 12 // Step on rising edge
#define EN_PIN 18 // LOW: Driver enabled. HIGH: Driver disabled
#define MS1_PIN 11 // To set step mode
#define MS2_PIN 10 // To set step mode
// Set up accelStepper intance
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
// Set up stepper speed details
// For NMB stepper with gear box reduction ratio of 1:41.66666:
// Motor step angle 15 deg
// Output shaft step angle 0.36 deg
// 1000 pulse output = 360 deg
float motorRPM = 660.0; // default # of steps per second (1/2 step mode) [first power on, before saved to EEPROM]
float maxRPM = motorRPM*2.0;
float minRPM = motorRPM/3.0; // previous: 2.0
float adjFactor = 15.0;
// Set up variables with for ramping up in loop()
bool motorStartup = true;
unsigned long timeStamp1;
unsigned long previousAccel = 0;
int interval = 10; // # of milliseconds between speed increases (1/2 step)
bool motorRPMAdj = false;
int eeAddress = 0; // EEPROM address to start reading
// 4) Blinking NEOPixel LEDs
// =========================
/*
The NeoPixel data pin does ** NOT *** need to be a PWM-enabled pin
as there is no realistic way to fade RGB LEDs. Hence, any digital
pin can be used.
For optimum randomness between the port & starboard lights the
DATA_OUT pin from one couild connect to the DATA_IN on the other
with NEO_COUNT = 20.
*/
#define NEO_PIN 4 // NeoPixel pin
#define NEO_COUNT 10 // Number of NePixels connected in a string (could be 10 or 20)
uint8_t NEO_BRIGHTNESS = 3; // NeoPixel brightness
uint32_t MIN_RANDOM_NUM = 250; // lower random blink time
uint32_t MAX_RANDOM_NUM = 1000; // upper random blink time
// State variables to determine when to start showing NecPixel blinkies
bool waitForAmberLEDStartup = true;
bool showNeoPixelBlinkies = false;
uint32_t colors[] = {
0x00990000, // Darkest red
0x00CC0000, // Dark red
0x00FF0000, // Red
0x00FF6666, // Lt. Red
0x0000FF00, // Green
0x0066FF66, // Lt. Green
0x000000FF, // Blue
0x0099CCFF, // Lt. Blue
0x00FFFFFF, // White
0x00FFFF00, // Yellow
0x00FFFF99, // Lt. Yellow
0x00FF66FF, // Pink
0x00FFCCFF // Lt. Pink
};
class BlinkyPixel : public Adafruit_NeoPixel {
public:
BlinkyPixel(int numLeds, int pin, int type) : (numLeds, pin, type)
{
timer = new Timer[numLeds];
};
void update(void);
void init();
private:
struct Timer{
uint32_t nextUpdateMillis;
bool state;
};
Timer* timer;
};
void BlinkyPixel::init()
{
begin();
setBrightness(NEO_BRIGHTNESS);
for (size_t i = 0; i < numPixels(); i++)
{
timer[i].state = 0;
setPixelColor(i, 0, 0, 0);
timer[i].nextUpdateMillis = millis() + random(MIN_RANDOM_NUM, MAX_RANDOM_NUM);
}
show();
}
void BlinkyPixel::update()
{
for (size_t i = 0; i < numPixels(); i++)
{
if (millis() >= timer[i].nextUpdateMillis)
{
if (timer[i].state)
{
setPixelColor(i, 0, 0, 0); // off
}
else
{
setPixelColor(i, colors[random(sizeof(colors)/sizeof(uint32_t))]); // random colour
//setPixelColor(i, random(0xFF), random(0xFF), random(0xFF));
}
timer[i].state = !timer[i].state;
timer[i].nextUpdateMillis = millis() + random(MIN_RANDOM_NUM, MAX_RANDOM_NUM);
}
show();
}
}
BlinkyPixel strip(NEO_COUNT, NEO_PIN, NEO_RGB + NEO_KHZ800);
// ===================================================================================================
void setup()
{
#ifdef DEBUG_MODE
Serial.begin(9600);
delay(100);
#endif
#ifdef DEBUG_MODE
Serial.println("-----------");
Serial.println("DEBUG_MODE ON");
Serial.println("-----------");
#endif
// // Get the saved motor RPM float data from the EEPROM at position 'eeAddress'
// float f = 0.00f; // Variable to store data read from EEPROM.
// EEPROM.get( eeAddress, f );
//
//#ifdef DEBUG_MODE
// Serial.print("EEPROM f val: ");
// Serial.println( f, 3 ); // This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.
//#endif
//
// if (!isnan(f)) {
// // EEPROM read yields numerical value, so set motorRPM to this if it's within min/max
// if ((f >= minRPM) && (f <= maxRPM)) {
// motorRPM = f;
// }
// }
#ifdef DEBUG_MODE
Serial.print("motorRPM: ");
Serial.println(motorRPM); // This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.
#endif
// Initialize TMC2208 SilentStepstick
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, HIGH); // Disable driver in hardware until remaining config is done
pinMode(MS1_PIN, OUTPUT);
pinMode(MS2_PIN, OUTPUT);
// Set up SilentStepStick in 1/2 step mode for this particular stepper motor
digitalWrite(MS1_PIN, HIGH);
digitalWrite(MS2_PIN, LOW);
digitalWrite(EN_PIN, LOW); // Enable stepper driver
stepper.setMaxSpeed(motorRPM);// This is the speed which code in loop() will ramp up to
stepper.setSpeed(10); // Set to a really low value in anticipation of ramping up to
// motorRPM
// if analog input pin 1 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(A1));
// Initialize NEOPixel LEDs
strip.init();
}
// ===================================================================================================
void loop()
{
// 6) Stepper motor
// ================
if ( motorStartup == true ) {
// Ramp up motor speed to set value, then continue at that speed continuously
#ifdef DEBUG_MODE
Serial.print("motorStartup: ");
Serial.println(motorStartup);
Serial.print("stepper.speed(): ");
Serial.println(stepper.speed());
Serial.print("motorRPM: ");
Serial.println(motorRPM);
#endif
if ( stepper.speed() < motorRPM ) {
timeStamp1 = millis();
if (timeStamp1 > previousAccel + interval) {
previousAccel = timeStamp1;
stepper.setSpeed(stepper.speed() + 2);
}
} else {
motorStartup = false;
}
}
stepper.runSpeed();
unsigned long currentTimeMS = millis();
// 4) NEOPixel warp engine blinkies
// ================================
if ( (currentTimeMS >= (8000)) && (waitForAmberLEDStartup == true) ) {
waitForAmberLEDStartup = false;
showNeoPixelBlinkies = true;
}
if ( showNeoPixelBlinkies == true ) {
strip.update();
}
}