Full disclosure that I am not very familiar with C++, which will be clear after review of the sample below.
I am using an Arduino based light controller to toggle sequences of lights, and am making use of the RX/TX pins due to the board's lack of I/O pins. Info on the specific board here.
In loop()
there is a static variable declared to keep track of the number of button presses. In the simple example below, everything works as expected and the appropriate lights turn on with each subsequent button press. This tells me that the counter pressCount
is working as expected.
// this works and will light up the correct lights (pins 2-7) with subsequent button presses
debounceReadButton(TX_PIN, buttonState, buttonHistory);
if (!lastButtonState && buttonState) {
++pressCount;
digitalWrite(
pressCount + 1,
HIGH
);
}
lastButtonState = buttonState;
However, as shown below, once pressCount
is used as an index to reference an array value on SEQUENCES
; the loop()
function seems to ignore value changes on pressCount
. As pressCount
changes, it would seem that each time loop()
runs it would be referencing a new light sequence. This is not the case, however.
#define RX_PIN 0
#define TX_PIN 1
#define RED_A 7
#define YELLOW_A 6
#define GREEN_A 5
#define RED_B 4
#define YELLOW_B 3
#define GREEN_B 2
const int LIGHTS[] = {
RED_A, YELLOW_A, GREEN_A,
RED_B, YELLOW_B, GREEN_B
};
/*
LIGHT MAP
[ ] RED_A
[ ] YELLOW_A
[ ] GREEN_A
[ ] YELLOW_B
[ ] RED_B
LIGHT SEQUENCE STRUCT
[0] = lights
[1] = level
[2] = duration
*/
struct instruction {
int lights[6];
int level;
int duration;
};
// TURN OFF ALL LIGHTS
void lightsOut() {
// cite: forum.arduino.cc/t/understanding-sizeof-question/574698/4
const size_t lightCount = sizeof(LIGHTS) / sizeof(*LIGHTS);
for (int i = 0; i < lightCount; i++) {
pinMode(LIGHTS[i], OUTPUT);
digitalWrite(LIGHTS[i], LOW);
} // for lightCount
} // initializeLights
// START TRACKING BUTTON PRESSES
void initializeButtons() {
pinMode(RX_PIN, INPUT_PULLUP);
// pinMode(TX_PIN, INPUT_PULLUP);
}
void setup() {
delay(500);
initializeButtons();
} // setup
void loop() {
const instruction SEQUENCES[][20] = {
// BLINK
{
{
{ RED_A, RED_B, YELLOW_A, YELLOW_B, GREEN_A },
HIGH,
1000
}, {
{ RED_A, RED_B, YELLOW_A, YELLOW_B, GREEN_A },
LOW,
1000
},
/* PADDING */ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
},
// LEFT TO RIGHT BLINK
{
{
{ RED_A, RED_B },
HIGH,
1000
}, {
{ RED_A, RED_B },
LOW,
100
}, {
{ YELLOW_A, YELLOW_B },
HIGH,
1000
}, {
{ YELLOW_A, YELLOW_B },
LOW,
100
}, {
{ GREEN_A },
HIGH,
1000
}, {
{ GREEN_A },
LOW,
100
},
/* PADDING */ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
},
// LEFT TO RIGHT FILL
{
{
{ RED_A, RED_B },
HIGH,
1250
}, {
{ YELLOW_A, YELLOW_B },
HIGH,
1250
}, {
{ GREEN_A },
HIGH,
1875
}, {
{ RED_A, RED_B, YELLOW_A, YELLOW_B, GREEN_A },
LOW,
1250
},
/* PADDING */ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
},
// TOP TO BOTTOM BLINK
{
{
{ RED_A },
HIGH,
1000
}, {
{ RED_A },
LOW,
100
}, {
{ YELLOW_A },
HIGH,
1000
}, {
{ YELLOW_A },
LOW,
100
}, {
{ GREEN_A },
HIGH,
1000
}, {
{ GREEN_A },
LOW,
100
}, {
{ YELLOW_B },
HIGH,
1000
}, {
{ YELLOW_B },
LOW,
100
}, {
{ RED_B },
HIGH,
1000
}, {
{ RED_B },
LOW,
100
},
/* PADDING */ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
},
// TOP TO BOTTOM FILL
{
{
{ RED_A },
HIGH,
1000
}, {
{ YELLOW_A },
HIGH,
1000
}, {
{ GREEN_A },
HIGH,
1000
}, {
{ YELLOW_B },
HIGH,
1000
}, {
{ RED_B },
HIGH,
1000
}, {
{ RED_A, RED_B, YELLOW_A, YELLOW_B, GREEN_A },
LOW,
1000
},
/* PADDING */ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
}
}; // SEQUENCES
// cite: forum.arduino.cc/t/is-it-possible-to-add-a-push-button-switch-in-arduino-port-0-or-1/427968/15
// default state for N.O switch with pullup
static bool buttonHistory[3] = { true, true, true };
static bool buttonState = true;
static bool lastButtonState = true;
// counts button presses
static int pressCount = 0;
// read button input state
debounceReadButton(TX_PIN, buttonState, buttonHistory);
if (!lastButtonState && buttonState) {
++pressCount;
digitalWrite(
pressCount + 1,
HIGH
);
}
lastButtonState = buttonState;
// NOTE: the code within the for loop does not seem to ever use the updated value of `pressCount`
// cite: forum.arduino.cc/t/understanding-sizeof-question/574698/4
size_t stepCount = sizeof(SEQUENCES[pressCount]) / sizeof(*SEQUENCES[pressCount]);
for (int i = 0; i < stepCount; i++) {
size_t lightCount = sizeof(SEQUENCES[pressCount][i].lights) / sizeof(*SEQUENCES[pressCount][i].lights);
if (lightCount > 0) {
for (int j = 0; j < lightCount; j++) {
digitalWrite(
SEQUENCES[pressCount][i].lights[j],
SEQUENCES[pressCount][i].level
);
delay(SEQUENCES[pressCount][i].duration);
} // for lightCount
}
} // for stepCount
// limit loop rate for sake of the debouncer
delay(20);
} // loop
void debounceReadButton(byte pin, bool ¤tState, bool history[]) {
history[2] = history[1];
history[1] = history[0];
history[0] = digitalRead(pin);
// return new state if history aligns
// otherwise leave state unchanged
if (
(history[0] == history[1]) &&
(history[1] == history[2])
) {
currentState = history[0];
} // if
} // debounceReadButton
It seems there is some fundamental understanding I am missing here either about Arduino or C++ development.