/*
Forum: https://forum.arduino.cc/t/neopixel-serial-project-dropped-characters-on-serial-read-random-resets/1157425/7
Wokwi: https://wokwi.com/projects/372868220889578497
*/
#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(2400); // Missing characters with Bd rate 4800, 9600 and higher
//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
//unsigned long startShow = micros();
pixels.show();
//Serial.print(micros()-startShow);
//Serial.print(",");
/*
Typical (micros()-startShow) - output on Wokwi
620,1644,620,620,1640,620,1644,616,620,1648,616,1640,616,1644,620,1644,616,1640,
620,1644,616,1644,616,1648,616,1640,620,1644,620,1644,1644,620,1644,616,620,1644,
620,616,616,1640,620,616,616,1644,1640,1644,616,620,620,616,620,620,1640,1644,1644,
1644,1644,1640, ...
*/
}
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(">"));
}
}