Hi everyone! Im brand new to the forum and fairly new to programming. I've been working on an "infinity table" for some time now and I am about done but running into some programming issues that I cannot figure out for the life of me.
The table has a one momentary push button and a sliding potentiometer.
My desired functions are as follows:
Single Press: cycle through a switch-case menu of different LED modes (i.e. strobe, rainbow, pulsing, etc) and each menu option possibly having a different function for the potentiometer.... I haven't gotten that far yet.
Press+Hold: Toggle LED strip on and off
My Press+Hold and Single Press work but not as desired... for example sometimes the single click wont register at all, sometimes my hold event takes way longer than it should.
To handle the button events I've adapted this code: Jeff's Arduino Blog: 4-Way Button: Click, Double-Click, Hold, Long Hold
Here is my full program.. Ive implemented some serial outputs to track my button events.
#include <FastLED.h>
#define NUM_LEDS 50
#define BUTTON_PIN 3
#define LED_DATA_PIN 2
#define POT_PIN 0
//Prototypes:
int checkButton();
void potIncrease();
void triColorShift();
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT);
digitalWrite(BUTTON_PIN, HIGH);
FastLED.addLeds<WS2811, LED_DATA_PIN, RGB>(leds, NUM_LEDS);
}
void loop() {
int buttonEvent = checkButton();
static int menuScroll = 1;
if (buttonEvent == 1){
menuScroll++;
Serial.println("menuScroll++");
}
if (buttonEvent == 3){
Serial.println("hold");
if(FastLED.getBrightness() == 0)
FastLED.setBrightness(255);
else if(FastLED.getBrightness() == 255)
FastLED.setBrightness(0);
}
switch (menuScroll) {
case 1:
triColorShift();
break;
case 2:
potIncrease();
break;
default:
menuScroll = 1;
break;
}
FastLED.show();
}
void triColorShift() {
int count = 1;
for (int i = 0; i < NUM_LEDS; i++){
if (count == 1)
leds[i] = CRGB::Red;
else if (count == 2)
leds[i] = CRGB::Green ;
else if (count == 3)
leds[i] = CRGB::Blue;
count++;
if (count > 3)
count = 1;
}
FastLED.show();
delay(1000);
for (int i = 0; i < NUM_LEDS; i++){
if (count == 1)
leds[i] = CRGB::Blue;
else if (count == 2)
leds[i] = CRGB::Red;
else if (count == 3)
leds[i] = CRGB::Green;
count++;
if (count > 3)
count = 1;
}
FastLED.show();
delay(1000);
for (int i = 0; i < NUM_LEDS; i++){
if (count == 1)
leds[i] = CRGB::Green;
else if (count == 2)
leds[i] = CRGB::Blue;
else if (count == 3)
leds[i] = CRGB::Red;
count++;
if (count > 3)
count = 1;
}
FastLED.show();
delay(1000);
}
void potIncrease() {
int val = analogRead(POT_PIN);
int numLedsToLight = map(val, 0, 1000, 0, NUM_LEDS);
// First, clear the existing led values
FastLED.clear();
for(int led = 0; led < numLedsToLight; led++) {
leds[led] = CRGB::Blue;
}
FastLED.show();
}
// Button timing variables
int debounce = 40; // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250; // max ms between clicks for a double click event
int holdTime = 1000; // ms hold period: how long to wait for press+hold event
// Other button variables
boolean buttonVal = HIGH; // value read from button
boolean buttonLast = HIGH; // buffered value of the button's previous state
boolean DCwaiting = false; // whether we're waiting for a double click (down)
boolean DConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true; // whether it's OK to do a single click
long downTime = -1; // time the button was pressed down
long upTime = -1; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false; // when held, whether to wait for the up event
boolean holdEventPast = false; // whether or not the hold event happened already
int checkButton(){
int event = 0;
// Read the state of the button
buttonVal = digitalRead(BUTTON_PIN);
// Button pressed down
if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce){
downTime = millis();
ignoreUp = false;
waitForUp = false;
singleOK = true;
holdEventPast = false;
if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)
DConUp = true;
else DConUp = false;
DCwaiting = false;
}
// Button released
else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce) {
if (!ignoreUp) {
upTime = millis();
if (DConUp == false)
DCwaiting = true;
else {
event = 2;
Serial.println("Event 2");
DConUp = false;
DCwaiting = false;
singleOK = false;
}
}
}
// Test for normal click event: DCgap expired
if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true){
event = 1;
Serial.println("Event 1");
DCwaiting = false;
}
// Test for hold
if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
// Trigger "normal" hold
if (!holdEventPast) {
event = 3;
Serial.println("Event 3");
waitForUp = true;
ignoreUp = true;
DConUp = false;
DCwaiting = false;
//downTime = millis();
holdEventPast = true;
}
}
buttonLast = buttonVal;
return event;
}
Thanks in advance!! I'll post pictures of the table when its finished if you guys want to see it!