Open Bouni opened 4 months ago
I figured it out 🥳
uint16_t CarBlinkerEffect(void) { // random chase
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
WS2812FX::Segment_runtime* segrt = ws2812fx.getSegmentRuntime(); // get current segment runtime
int seglen = seg->stop - seg->start + 1;
bool isReverse = (seg->options & REVERSE) == REVERSE;
if(segrt->counter_mode_step < seglen-1) {
if(isReverse) {
ws2812fx.setPixelColor(segrt->counter_mode_step, ORANGE);
} else {
ws2812fx.setPixelColor(seg->stop - segrt->counter_mode_step, ORANGE);
}
segrt->counter_mode_step = (segrt->counter_mode_step + 1) % seglen;
}
else {
ws2812fx.fill(BLACK, seg->start, seglen);
segrt->counter_mode_step = 0;
}
if(segrt->counter_mode_step == 0) ws2812fx.setCycle();
return seg->speed;
}
Yay! Good for you. Nice debug work.
However, I did notice that the first LED (or the last LED if REVERSE is enabled) does not illuminate. I think one more tweak is needed. Maybe this:
uint16_t CarBlinkerEffect(void) { // random chase
WS2812FX::Segment* seg = ws2812fx.getSegment(); // get the current segment
WS2812FX::Segment_runtime* segrt = ws2812fx.getSegmentRuntime(); // get current segment runtime
int seglen = seg->stop - seg->start + 1;
bool isReverse = (seg->options & REVERSE) == REVERSE;
//if(segrt->counter_mode_step < seglen - 1) {
if(segrt->counter_mode_step < seglen) {
if(isReverse) {
ws2812fx.setPixelColor(segrt->counter_mode_step, ORANGE);
} else {
ws2812fx.setPixelColor(seg->stop - segrt->counter_mode_step, ORANGE);
}
// segrt->counter_mode_step = (segrt->counter_mode_step + 1) % seglen;
segrt->counter_mode_step++;
} else {
ws2812fx.fill(BLACK, seg->start, seglen);
segrt->counter_mode_step = 0;
}
if(segrt->counter_mode_step == 0) ws2812fx.setCycle();
return seg->speed;
}
But you probably already figured it out. :)
Actually I didn't even notice 😅
But I added your tweaks anyway as they are probably correct.
I have one more question, heres my complete code:
#include <WS2812FX.h>
#define LED_COUNT 300
#define LED_PIN 3
#define LEFT 0
#define CENTER 1
#define RIGHT 2
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
uint16_t CarBlinkerEffect(void) { // Car blinker effect (Audi & co)
WS2812FX::Segment* seg = ws2812fx.getSegment();
WS2812FX::Segment_runtime* segrt = ws2812fx.getSegmentRuntime();
int seglen = seg->stop - seg->start + 1;
bool isReverse = (seg->options & REVERSE) == REVERSE;
if(segrt->counter_mode_step < seglen) {
if(isReverse) {
ws2812fx.setPixelColor(seg->start + segrt->counter_mode_step, ORANGE);
} else {
ws2812fx.setPixelColor(seg->stop - segrt->counter_mode_step, ORANGE);
}
segrt->counter_mode_step++;
}
else {
ws2812fx.fill(BLACK, seg->start, seglen);
segrt->counter_mode_step = 0;
}
if(segrt->counter_mode_step == 0) ws2812fx.setCycle();
return seg->speed;
}
void blink_left() {
ws2812fx.resetSegments();
ws2812fx.resetSegmentRuntimes();
ws2812fx.strip_off();
ws2812fx.setSegment(0, 0, 9, FX_MODE_CUSTOM, BLACK, 60, false);
}
void blink_right() {
ws2812fx.resetSegments();
ws2812fx.resetSegmentRuntimes();
ws2812fx.strip_off();
ws2812fx.setSegment(0, 20, 29, FX_MODE_CUSTOM, BLACK, 60, true);
}
void full_color(int color) {
ws2812fx.resetSegments();
ws2812fx.resetSegmentRuntimes();
ws2812fx.strip_off();
ws2812fx.setSegment(0, 0, 29, FX_MODE_STATIC, color, 60, false);
}
void full_blink(int color) {
ws2812fx.resetSegments();
ws2812fx.resetSegmentRuntimes();
ws2812fx.strip_off();
ws2812fx.setSegment(0, 0, 29, FX_MODE_BLINK, color, 1000, false);
}
void off() {
ws2812fx.resetSegments();
ws2812fx.resetSegmentRuntimes();
ws2812fx.strip_off();
}
void setup() {
Serial.begin(115200);
ws2812fx.init();
ws2812fx.setCustomMode(CarBlinkerEffect);
ws2812fx.start();
off();
}
void loop() {
while (Serial.available() > 0) {
String cmd;
cmd = Serial.readString();
cmd.trim();
if(cmd == "bll") {
blink_left();
Serial.println("Start Left");
}
if(cmd == "blr") {
blink_right();
Serial.println("Start Right");
}
if(cmd == "g") {
full_color(GREEN);
Serial.println("Green");
}
if(cmd == "r") {
full_color(RED);
Serial.println("Red");
}
if(cmd == "b") {
full_color(BLUE);
Serial.println("Blue");
}
if(cmd == "y") {
full_color(YELLOW);
Serial.println("Yellow");
}
if(cmd == "bg") {
full_blink(GREEN);
Serial.println("Green");
}
if(cmd == "br") {
full_blink(RED);
Serial.println("Red");
}
if(cmd == "bb") {
full_blink(BLUE);
Serial.println("Blue");
}
if(cmd == "by") {
full_blink(YELLOW);
Serial.println("Yellow");
}
if(cmd == "0") {
off();
Serial.println("Off");
}
}
ws2812fx.service();
}
This works as expected but maybe can be done better. The only thing that bothers me is that when I switch between the effects, it takes like half a scond until the next effect starts.
Is there something I can do about that?
I'm an idiot. After writing my answer I realized that readString
amkes use of the Serial timeout which defaults to 1000ms.
Setting that to 100ms with Serial.setTimeout(100);
makes it respond as expected 🤦🏽♂️
Yeah, those blocking Serial I/O statements are a pain. Setting the Serial timeout to 100 works, but it still blocks for 100ms. To up your Arduino mojo, the Serial Input Basics tutorial has some nice examples of non-blocking Serial I/O.
Hi,
I want to create a custom effect that looks like one of those fancy nw car blinkers where the length fills up with orange and then altogether turns off. Its almsot what the color_whipe effect does but that "empties" the length instead of turning it of at once.
I looked into the source of the color whipe effect, here: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/modes_funcs.cpp#L84-L106
I also looked at a lot of custom effects and came up with this:
The segment of 10 LEDs fills up as expected, but then nothing more happens and I don't understand why.
Can somebody help me figuring out where I made a mistake?