Hi all,
I'm (relatively) new to Arduino and am working on a "calculator" project for an electronics class. Specifically, I'm trying to use two buttons to control 1) the values being calculated and the operation and 2) switching the state of the Arduino, between accepting value inputs and performing calculations. An 8x8 matrix scrolls the result of the calculation as well as the values being input.
I'm having two possibly related problems:
The first is that in my switch statements, when my calculator is in the right "state" it won't always accept a button press (actually, less than 10% of the time).
The second is that it will switch from idle to firstNum just fine, but switching to operation essentially kills it. It doesn't print the statements that it's in that case, nor will the matrix display the operations value (which should be zero). Instead it prints "398", bizarrely. I'm attaching the code below:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
//libraries provided by Adafruit for the LED Matrix/Backpack and the compatible graphics drawing routines found on github
//https://github.com/adafruit/Adafruit_LED_Backpack.git
//https://github.com/adafruit/Adafruit-GFX-Library.git
const int BUTTON = 2; //define the pins used for the value incrementer and the input switcher
const int SWITCH = 3; //
enum CalcState { //enumerate the states possible for the calculator
idle,
firstNum,
operation,
secondNum,
calculate,
};
CalcState printstate = idle; //calculator starts in idle
Adafruit_8x8matrix matrix = Adafruit_8x8matrix(); //initialize the LED matrix
int firstNumber[] = {0}; //store the values in arrays so they'll be accessible to the switch case method
int secondNumber[] = {0};
int operations[] = {0};
//the following four lines of code adapted from the Arduino reference website on button debouncing: https://www.arduino.cc/en/Tutorial/Debounce
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
int switchState;
int lastSwitchState = LOW;
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long lastDebounceSwitchTime = 0;
unsigned long debounceDelay = 100; // the debounce time; increase if the output flickers
void setup() {
Serial.begin(9600);
// pinMode(OPERATION, INPUT);
pinMode(BUTTON, INPUT);
pinMode(SWITCH, INPUT);
matrix.begin(0x70);
}
static const uint8_t PROGMEM
test_bmp[] =
{ B11111111,
B10000001,
B10000001,
B01000010,
B01000010,
B00100100,
B00011000,
B11111111
};
void loop() {
printstate = nextState(printstate, firstNumber, secondNumber, operations); //check the state and if the buttons have been pressed
delay(100); //sanity preserver
}
CalcState nextState (CalcState state, int firstNumber[], int secondNumber[], int operations[]) {
switch (state) {
case idle:
Serial.print("idle");
Serial.print(stateSwitch());
if (stateSwitch() == 0) { //if the state switching button hasn't been pressed, don't do anything
state = idle; //
} else if (stateSwitch() == 1) { //otherwise, switch to accepting the first number
state = firstNum;
}
break;
case firstNum:
Serial.print("firstNum");
if (stateSwitch() == 0) {
if (buttonPress() == 1) { //if the value incrementing button is being pressed....increment the value.
firstNumber[0]++;
} state = firstNum; //keep accepting value incrementing until the state switches
matrixPrint(firstNumber[0]);
}
else if (stateSwitch() == 1) {
state = operation;
Serial.print("switching to operation mode");
matrixPrint("1 ok");
}
break;
case operation:
Serial.print("operation");
if (stateSwitch() == 0) {
if (buttonPress() == 1) {
operations[0]++;
} state = operation;
matrixPrint("operation[0]");
}
else if (stateSwitch() == 1) {
state = secondNum;
matrixPrint("O ok");
}
break;
case secondNum:
Serial.print("secondNum");
if (stateSwitch() == 0) {
if (buttonPress() == 1) {
secondNumber[0]++;
} state = secondNum;
matrixPrint(secondNumber[0]);
}
else if (stateSwitch() == 1) {
state = calculate;
matrixPrint("2 ok");
}
break;
case calculate:
Serial.print("calculate");
if (operations[0] % 4 == 0) { //only four operations on this calculator, you can use it on a gen chem exam
matrixPrint(firstNumber[0] + secondNumber[0]);
} else if (operations[0] % 4 == 1) {
matrixPrint(firstNumber[0] - secondNumber[0]);
} else if (operations[0] % 4 == 2) {
matrixPrint(firstNumber[0] * secondNumber[0]);
} else matrixPrint(firstNumber[0] / secondNumber[0]);
if (stateSwitch() == 0) {
state = calculate;
} else if (stateSwitch() == 1) {
state = firstNum;
}
break;
}
return state;
}
bool buttonPress() {
int button = digitalRead(BUTTON);
if (button == 1){
Serial.println("pressed");
return true;
} else return false;
// int buttonHigh = 0;
//
// if (button != lastButtonState) {
// // reset the debouncing timer
// lastDebounceTime = millis();
// }
//
// if ((millis() - lastDebounceTime) > debounceDelay) {
// // whatever the reading is at, it's been there for longer than the debounce
// // delay, so take it as the actual current state:
//
// // if the button state has changed:
// if (button != buttonState) {
// buttonState = button;
//
// // only switch cases if the new button state is HIGH
// if (buttonState == HIGH) {
// Serial.println("pressed");
// buttonHigh = 1;
// }
// }
// }
//
// // save the reading. Next time through the loop, it'll be the lastButtonState:
// lastButtonState = button;
// return buttonHigh;
}
bool stateSwitch() {
int switching = digitalRead(SWITCH);
if (switching == 1){
Serial.println("switched");
return true;
} else return false;
// int buttonHigh = 0;
//
// if (switching != lastSwitchState) {
// lastDebounceSwitchTime = millis();
// }
//
// if ((millis() - lastDebounceSwitchTime) > debounceDelay) {
// if (switching != switchState) {
// switchState = switching;
// if (switchState == HIGH) {
// Serial.println("state switched");
// buttonHigh = 1;
// }
// }
// }
//
// lastSwitchState = switching;
// return buttonHigh;
}
void matrixPrint(int value) {
matrix.clear(); //the following lines of code in this method have been adapted from one of the example sketches provided by the LED Matrix Library
matrix.setTextSize(1);
matrix.setTextWrap(false); // we dont want text to wrap so it scrolls nicely
int length = 16;
if (value != 0) {
length = value * 8;
}
for (int8_t x = 0; x >= -length; x--) { //to avoid waiting forever for a single digit to scroll, but also allow for longer strings to loop
matrix.clear();
matrix.setCursor(x, 0);
matrix.print(value);
matrix.writeDisplay();
delay(100);
}
}
I'm using this matrix 8x8 matrix, and an Uno board, if that helps. The buttons are wired with pull-down resistors to pins 2 and 3.
My theory is that I've bungled something about the switch case statement, possible where I'm not humanly able to slam the button fast enough for the case to read it, but any other errors you can point out would also be helpful.
Thanks guys!