Any help would be greatly appreciated!
/*
Jebediah's Launch Control System for Kerbal Space Program
Alpha Build 2.00
An Open-Source Project by John Seong
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
const byte ROWS = 4;
const byte COLS = 3;
const int buzzer = A3;
const int ledAbort = 5;
const int ledStage = A5;
const int buttonAbort = 4;
const int buttonStage = A4;
int ledAbortState = LOW;
int ledStageState = LOW;
char keys[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
byte rowPins[ROWS] = {12, 11, 10, 9};
byte colPins[COLS] = {8, 7, 6};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
unsigned long previousMillis = 0;
const long interval = 1000;
// Show a two-line message on the LCD.
void lcdShow(const char line0, const char line1) {
lcd.clear();
lcd.print(line0);
lcd.setCursor(0, 1);
lcd.print(line1);
}
void lcdShowResult(float result) {
lcd.print(result);
}
void setup() {
pinMode(buzzer, OUTPUT);
pinMode(ledAbort, OUTPUT);
pinMode(ledStage, OUTPUT);
pinMode(buttonAbort, INPUT_PULLUP);
pinMode(buttonStage, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
Serial.begin(9600);
lcd.begin(16, 2);
lcdShow(" JEB'S LAUNCH", " CONTROL SYSTEM");
delay(3000);
lcdShow("ALPHA BUILD 2.00", " STUDIO HORIZON");
delay(3000);
lcdShow("WELCOME, KERMAN.", "PRESS ANY KEY...");
while (!keypad.getKey()) ; // wait for key press
}
void loop() {
static enum {START, MENU, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT, TWR_COMPUTE} state = START;
static uint32_t last_second; // millis() value on last full second
static int count;
static float thrust, weight, ratio;
char key = keypad.getKey();
switch (state) {
case START: // transitional state
lcdShow("1. LAUNCH SEQ", "2. TWR CALC");
state = MENU;
/* fallthrough */
case MENU:
if (key == '1') { // Countdown
lcdShow("COUNTDOWN TIMER", "SECONDS: ");
count = 0;
state = SET_COUNT;
} else if (key == '2') { // TWR
lcdShow("TWR CALCULATOR", "THRUST: ");
thrust = 0, weight = 0, ratio = 0;
state = SET_THRUST;
}
break;
case SET_COUNT:
if (key >= '0' && key <= '9' && count <= 99) {
lcd.print(key);
count = 10 * count + (key - '0');
} else if (key == '#') {
lcdShow(" T-MINUS", " SECONDS");
// Force a refresh on entering COUNT_DOWN:
last_second = millis() - 1000;
count++;
state = COUNT_DOWN;
} else if (key == '*') {
state = START;
}
break;
case COUNT_DOWN:
if (millis() - last_second >= 1000) {
last_second += 1000;
count--;
if (count <= 10) {
tone(buzzer, 500);
delay(500);
noTone(buzzer);
}
if (count == 0) {
Serial.println("Lift off!");
} else if (count < 0) {
state = LAUNCH;
break;
}
lcd.setCursor(1, 1);
lcd.print(count < 10 ? " " : count < 100 ? " " : ""); // pad
lcd.print(count);
} else if (key == '*') {
state = START;
}
break;
case LAUNCH:
tone(buzzer, 3000);
int stageConfirm = digitalRead(buttonStage);
int abortConfirm = digitalRead(buttonAbort);
unsigned long currentMillis = millis;
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (ledAbortState == LOW) {
ledAbortState = HIGH;
lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
} else if (ledAbortState == HIGH) {
ledAbortState = LOW;
lcd.clear();
}
if (ledStageState == LOW) {
ledAbortState = HIGH;
} else if (ledAbortState == HIGH) {
ledAbortState = LOW;
}
digitalWrite(ledAbort, ledAbortState);
digitalWrite(ledStage, ledStageState);
}
break;
case SET_THRUST:
if (key >= '0' && key <= '9' && thrust <= 9999) {
lcd.print(key);
thrust = 10 * thrust + (key - '0');
} else if (key == '#') {
lcdShow("TWR CALCULATOR", "WEIGHT: ");
state = SET_WEIGHT;
} else if (key == '*') {
state = START;
}
break;
case SET_WEIGHT:
if (key >= '0' && key <= '9' && weight <= 9999) {
lcd.print(key);
weight = 10 * weight + (key - '0');
} else if (key == '#') {
lcdShow("THRUST-TO-WEIGHT", "RATIO: ");
if (thrust != 0 || weight != 0) {
ratio = thrust / weight;
lcdShowResult(ratio);
}
} else if (key == '*') {
state = START;
}
break;
}
}
delay()within a state machine. This is something you usually want to avoid. In fact, the whole point of a state machine is to avoid callingdelay()in order to keep the system responsive. – Edgar Bonet Jul 26 '20 at 18:40