Hi, I'm using an Arduino UNO R3 with a Adafruit NeoPixel LED Side Light Strip (122 LEDs, despite it being advertised as 120). Adafruit NeoPixel LED Side Light Strip - Black 120 LED | The Pi Hut
I've adapted the demo Neopixel strip example and added some code of my own to perform Serial comms with a host computer that I want to control it.
I've followed the Neopixel guidance. I have a 1000uF 16V capacitor to even out the power to the strip, and a 470ohm resistor to the data in on the strip. I'm not running at 100% brightness nor using pure white so I don't try drawing 7.3amps over my USB power lol. It seems to work just fine. My code animates the light strip and there's no apparent problem. Currently I'm using a breadboard for the resistor/capacitor and I could shorten the leads, but it's not the NeoPixels I'm having a problem with.
The problem comes when I try to send Serial data (even at 9600 baud) to my Arduino. Characters are randomly dropping, and the Arduino sometimes appears to reset. I can't figure out where my bug would be as I think I've caught most eventualities (obviously I'm wrong on that). My guess is that my code is leaking or I've done something really dumb.
Here's a typical session from my Serial Monitor. Even though I definitely sent the right commands each time, sometimes a random character is dropped causing the code to think I've mistyped. Not every time, just sometimes. I can't figure out the behaviour. Note - the first command "hello" was sent on purpose to demonstrate it responds to commands it doesn't recognise, but every other time I definitely typed "value ".
INIT
hello
UNKNOWN COMMAND <hello>
valu 0.5
UNKNOWN COMMAND <valu 0.5>
value
LIGHT VALUE 0.00
value 0
LIGHT VALUE 0.00
vaue 0.5
UNKNOWN COMMAND <vaue 0.5>
value 0.7
LIGHT VALUE 0.70
value 0.5
LIGHT VALUE 0.50
valu 0.5
UNKNOWN COMMAND <valu 0.5>
Sketch below - any suggestions or advice would be warmly welcomed!
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN 5
#define NUMPIXELS 122
#define BRIGHTNESS 128
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
String input;
float value = 0.0;
float valueSmooth = 0.0;
float valueDelta = 0.002;
void setup() {
Serial.begin(9600);
//if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) // Not needed
// clock_prescale_set(clock_div_1);
//endif
pixels.begin();
Serial.println(F("INIT"));
}
void loop() {
// Serial input processing
while (Serial.available()) {
char c = Serial.read(); // Read a character from the serial input
Serial.print(c); // Echo it back
if ((c == '\n') || (c == '\r')) {
// Complete line received
processInput(input); // Process the complete line of input
input = ""; // Clear the input buffer for the next line
} else {
// Add character to the input buffer
if (c != 0)
input += c;
}
}
// Neopixel lighting processing
// Smoothly bounce value between 0..1
value = value + valueDelta;
if (value >= 1) {
value = 1;
valueDelta = -valueDelta;
}
if (value < 0) {
value = 0;
valueDelta = -valueDelta;
}
// De-zip value
valueSmooth = (valueSmooth * 0.9) + (value * 0.1);
// Work out how many neopixels should be lit
int val = valueSmooth * NUMPIXELS;
// Create a nice blue..red gradient across all neopixels, only lighting those that are under val (so when val=1, all neopixels are lit)
for (int i = 0; i < NUMPIXELS; i++) {
if (i < val) {
pixels.setPixelColor(i, BRIGHTNESS * ((float)i/(float)NUMPIXELS),0,BRIGHTNESS * (1-((float)i/(float)NUMPIXELS)));
} else {
pixels.setPixelColor(i, 0,0,0);
}
}
// Boom
pixels.show();
}
void processInput(const String& input) {
// Process the received input - just respond to commands like "value 0.5" for now
if (input.startsWith(F("value "))) {
value = input.substring(5).toFloat();
Serial.print(F("LIGHT VALUE "));
Serial.println(value);
} else {
Serial.print(F("UNKNOWN COMMAND <"));
Serial.print(input);
Serial.println(F(">"));
}
}
