jibbity
December 7, 2021, 10:30am
1
I've got an interesting issue, where when a button is held for a short time the switch case progresses as expected.
However, if the button is continuously held instead of the switch case continuing to progress as expected and instead gets stuck on a single case.
Serial Monitor readout
Start Solid
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Start Mode 2
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Start Mode 3
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Start Solid
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Start Mode 2
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Start Mode 3
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Start Solid
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Solid Mode = 1
Start Mode 2
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Mode 2 = 1
Start Mode 3
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Mode 3 = 1
Start Solid
Solid Mode = 1
Start Solid
Solid Mode = 1
Start Solid
Solid Mode = 1
Start Solid
Solid Mode = 1
Start Solid
Solid Mode = 1
Start Solid
Solid Mode = 1
Start Solid
Solid Mode = 1
#include "FastLED.h"
#define NUM_LEDS 110
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define DATA_PIN 12
#define VOLTS 5
#define MAX_MA 1325 //Dont exceed for stability reasons.
const int buttonPin = 4;
int SolidColourCount = 0;
int ColourMode = 0;
int CurrentButtonState;
int PreviousButtonState = LOW;
int ButtonState;
unsigned long CurrentMillis = 0;
unsigned long PreviousMillis = 0;
unsigned long HoldMillis = 0;
bool HomeMode = true;
bool SolidMode = false;
bool Mode2 = false;
bool Mode3 = false;
CRGBArray<NUM_LEDS> leds;
void setup() {
FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
Serial.begin(9600);
pinMode(buttonPin, INPUT);
leds = CRGB::Black;
FastLED.show();
}
void loop() {
MainLoop();
}
void MainLoop() {
HomeMode = true;
while (HomeMode == true) {
int CurrentMillis = millis();
int CurrentButtonState = digitalRead(buttonPin);
if (CurrentButtonState == HIGH && (CurrentMillis - PreviousMillis >1000)) {
ColourMode++;
PreviousMillis = CurrentMillis;
}
if (ColourMode > 3) {
ColourMode = 1;
}
switch (ColourMode) {
case 1:
PreviousMillis = CurrentMillis;
Serial.println("Start Solid");
HomeMode = false;
SolidMode = true;
SolidLightingMode();
break;
case 2:
PreviousMillis = CurrentMillis;
Serial.println("Start Mode 2");
HomeMode = false;
Mode2 = true;
Mode2LightingMode();
break;
case 3:
PreviousMillis = CurrentMillis;
Serial.println("Start Mode 3");
HomeMode = false;
Mode3 = true;
Mode3LightingMode();
break;
}
}
}
void SolidLightingMode() {
while (SolidMode == true) {
CurrentMillis = millis();
int CurrentButtonState = digitalRead(buttonPin);
Serial.print("Solid Mode = ");
Serial.print(SolidMode);
Serial.println();
leds = CRGB::Green;
FastLED.show();
delay(300);
leds = CRGB::Blue;
FastLED.show();
delay(300);
if (CurrentButtonState == LOW) {
PreviousMillis = CurrentMillis;
}
if (CurrentButtonState == HIGH && (CurrentMillis - PreviousMillis > 3000)) {
SolidMode = false;
HomeMode = true;
MainLoop();
}
}
}
void Mode2LightingMode() {
while (Mode2 == true) {
CurrentMillis = millis();
int CurrentButtonState = digitalRead(buttonPin);
Serial.print("Mode 2 = ");
Serial.print(Mode2);
Serial.println();
leds = CRGB::Red;
FastLED.show();
delay(300);
leds = CRGB::Blue;
FastLED.show();
delay(300);
if (CurrentButtonState == LOW) {
PreviousMillis = CurrentMillis;
}
if (CurrentButtonState == HIGH && (CurrentMillis - PreviousMillis > 3000)) {
Mode2 = false;
HomeMode = true;
MainLoop();
}
}
}
void Mode3LightingMode() {
while (Mode3 == true) {
CurrentMillis = millis();
int CurrentButtonState = digitalRead(buttonPin);
Serial.print("Mode 3 = ");
Serial.print(Mode3);
Serial.println();
leds = CRGB::Green;
FastLED.show();
delay(300);
leds = CRGB::Red;
FastLED.show();
delay(300);
if (CurrentButtonState == LOW) {
PreviousMillis = CurrentMillis;
}
if (CurrentButtonState == HIGH && (CurrentMillis - PreviousMillis > 3000)) {
Mode3 = false;
HomeMode = true;
MainLoop();
}
}
}
A10_Global.zip (2.9 KB)
There’s quite a bit of duplication & redundancy in the code…
Walk through the logic with your finger, and you might see some opportunities… like -
Solid mode, Mode 1,2,3 could all be squished into a single ‘mode’ variable…
Likewise within each mode in the switch(), you could pull all the common code rather than duplicate it both before and inside the switch statement.
jibbity
December 7, 2021, 11:31am
3
It is overly simplistic for now at least.
I've purposefully set each lighting mode to be in it's own function and class on purpose.
I've removed some of the redundant code as you mentioned but, the issue still continues.
gcjr
December 7, 2021, 11:43am
4
looks like the ColourMode is only advanced after the button is released
The point was to strip down and simplify the code so fault-finding would be easier.
Are the leds lighting properly? Setting leds = CRGB::color does not seem to be a proper way to set the strip color.
jibbity
December 7, 2021, 11:55am
7
I checked this and but the ColourMode does increase even if the button is held, and not released.
Be careful calling mainloop from within the functions, recursive functions can quickly use up all the memory
jibbity
December 7, 2021, 11:57am
9
It does all light up correctly, just one of the many ways available in FastLED
jibbity
December 7, 2021, 11:59am
10
Actually, you might be onto something, if the memory is filled up this could explain it.
gcjr
December 7, 2021, 12:09pm
11
not sure how that is possible
should the pin be configured as INPUT_PULLUP?
jibbity
December 7, 2021, 12:16pm
12
Could be due to who I've wired the button, but I've got no answer on that sorry.
jibbity
December 7, 2021, 12:25pm
13
Absolutely right a simply reset function and that bug's squashed.
I don't see any unexpected behaviour. If the button is held down, colourMode increments and SolidLightingMode is called. It loops and prints "Solid Mode = 1" several times until the 3 second timeout expires and MainLoop is called (recursively) again.
The code is confusing though, especially having shadow copies of currentMillis and as noted above, will likely eventually run out of stack and crash.
gfvalvo
December 7, 2021, 1:01pm
15
I don't think so. You can't assign a CRGB::HTMLColorCode enum value (which is just an integer type) to an entire array:
#include "Arduino.h"
#include "FastLED.h"
CRGB leds[10];
void setup() {
leds = CRGB::Green;
}
void loop() {
}
C:\Users\TR001221\AppData\Local\Temp\arduino_modified_sketch_248320\sketch_dec06a.ino: In function 'void setup()':
sketch_dec06a:7:16: error: incompatible types in assignment of 'CRGB::HTMLColorCode' to 'CRGB [10]'
leds = CRGB::Green;
^~~~~
exit status 1
incompatible types in assignment of 'CRGB::HTMLColorCode' to 'CRGB [10]'
jibbity
December 7, 2021, 1:31pm
16
Just check out the Blink example in the FastLED library.
#include <FastLED.h>
#define NUM_LEDS 10
#define DATA_PIN 3
CRGB leds[NUM_LEDS];
void setup() {
FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
}
void loop() {
// Turn the LED on, then pause
leds[0] = CRGB::Red;
FastLED.show();
delay(500);
// Now turn the LED off, then pause
leds[0] = CRGB::Black;
FastLED.show();
delay(500);
}
gfvalvo
December 7, 2021, 1:46pm
17
Well ..... it turns out this:
leds[0] = CRGB::Red;
is not the same as this:
leds = CRGB::Red;
You're trying to do the latter and it's invalid.
EDIT:
Now I see. Your original code is using the CRGBArray class which does overload the assignment operator.
The Blink example in the FastLED library uses an array of CRGB objects. Assignment to the entire array won't work for that case.
Here is a version that might work better. It uses only one "Mode" variable to keep track of the mode.
#include "FastLED.h"
#define NUM_LEDS 110
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define DATA_PIN 12
#define VOLTS 5
#define MAX_MA 1325 //Dont exceed for stability reasons.
const byte ButtonPin = 4;
enum {HOME, SOLID, MODE2, MODE3} Mode = HOME;
unsigned long PreviousButtonMillis = 0;
CRGBArray<NUM_LEDS> leds;
void setup()
{
FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
Serial.begin(9600);
pinMode(ButtonPin, INPUT);
leds = CRGB::Black;
FastLED.show();
}
void loop()
{
unsigned long currentMillis = millis();
int currentButtonState = digitalRead(ButtonPin);
if (currentButtonState == LOW) // Not pressed?
{
PreviousButtonMillis = currentMillis;
}
boolean switchState = (currentButtonState == HIGH && (currentMillis - PreviousButtonMillis > 3000));
if (switchState)
{
PreviousButtonMillis = millis();
}
switch (Mode)
{
case HOME:
// Do Nothing
if (switchState)
{
Mode = SOLID;
Serial.println("Switched to Mode = SOLID");
}
break;
case SOLID:
if (switchState)
{
Mode = MODE2;
Serial.println("Switched to Mode = MODE2");
}
SolidLightingMode();
break;
case MODE2:
if (switchState)
{
Mode = MODE3;
Serial.println("Switched to Mode = MODE3");
}
Mode2LightingMode();
break;
case MODE3:
if (switchState)
{
Mode = HOME;
Serial.println("Switched to Mode = HOME");
}
Mode3LightingMode();
break;
}
}
void SolidLightingMode()
{
// Alternating Green and Blue
leds = CRGB::Green;
FastLED.show();
delay(300);
leds = CRGB::Blue;
FastLED.show();
delay(300);
}
void Mode2LightingMode()
{
// Alternating Red and Blue
leds = CRGB::Red;
FastLED.show();
delay(300);
leds = CRGB::Blue;
FastLED.show();
delay(300);
}
void Mode3LightingMode()
{
// Alternating Green and Red
leds = CRGB::Green;
FastLED.show();
delay(300);
leds = CRGB::Red;
FastLED.show();
delay(300);
}
jibbity
December 7, 2021, 10:37pm
19
johnwasser:
include "FastLED.h"
#define NUM_LEDS 110
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define DATA_PIN 12
#define VOLTS 5
#define MAX_MA 1325 //Dont exceed for stability reasons.
const byte ButtonPin = 4;
enum {HOME, SOLID, MODE2, MODE3} Mode = HOME;
unsigned long PreviousButtonMillis = 0;
CRGBArray<NUM_LEDS> leds;
void setup()
{
FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
Serial.begin(9600);
pinMode(ButtonPin, INPUT);
leds = CRGB::Black;
FastLED.show();
}
void loop()
{
unsigned long currentMillis = millis();
int currentButtonState = digitalRead(ButtonPin);
if (currentButtonState == LOW) // Not pressed?
{
PreviousButtonMillis = currentMillis;
}
boolean switchState = (currentButtonState == HIGH && (currentMillis - PreviousButtonMillis > 3000));
if (switchState)
{
PreviousButtonMillis = millis();
}
switch (Mode)
{
case HOME:
// Do Nothing
if (switchState)
{
Mode = SOLID;
Serial.println("Switched to Mode = SOLID");
}
break;
case SOLID:
if (switchState)
{
Mode = MODE2;
Serial.println("Switched to Mode = MODE2");
}
SolidLightingMode();
break;
case MODE2:
if (switchState)
{
Mode = MODE3;
Serial.println("Switched to Mode = MODE3");
}
Mode2LightingMode();
break;
case MODE3:
if (switchState)
{
Mode = HOME;
Serial.println("Switched to Mode = HOME");
}
Mode3LightingMode();
break;
}
}
void SolidLightingMode()
{
// Alternating Green and Blue
leds = CRGB::Green;
FastLED.show();
delay(300);
leds = CRGB::Blue;
FastLED.show();
delay(300);
}
void Mode2LightingMode()
{
// Alternating Red and Blue
leds = CRGB::Red;
FastLED.show();
delay(300);
leds = CRGB::Blue;
FastLED.show();
delay(300);
}
void Mode3LightingMode()
{
// Alternating Green and Red
leds = CRGB::Green;
FastLED.show();
delay(300);
leds = CRGB::Red;
FastLED.show();
delay(300);
}
I'll admit that is a fair bit more elegant.
system
Closed
June 5, 2022, 10:38pm
20
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.