Skip to main content
added 138 characters in body
Source Link

Edit: Basically the LEDs are placed right next to the button,(e.g. ledStage -> placed next to the buttonStage) they start to blink when the timer hits zero with a buzzer noise, and if the user presses one of the buttons, the buzzer noise stops and the LED placed next to the button they pressed turns on whereas the other turns off. I also connected the buttons without resistors. (directly to the pins)

/*
   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;

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);

// 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);

  Serial.begin(9600);
  lcd.begin(16, 2);
  while (!keypad.getKey()) ;  // wait for key press
}

void loop() {
  static enum {START, MENU, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  int stageConfirm = digitalRead(buttonStage);
  int abortConfirm = digitalRead(buttonAbort);

  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);
      digitalWrite(ledAbort, HIGH);
      digitalWrite(ledStage, HIGH);
      lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
      delay(1000);
      lcd.clear();
      digitalWrite(ledAbort, LOW);
      digitalWrite(ledStage, LOW);
      delay(500);

      stageConfirm = digitalRead(buttonStage);
      abortConfirm = digitalRead(buttonAbort);
      
      if (stageConfirm == 1 && abortConfirm == 0LOW) {
        noTone(buzzer);
        digitalWrite(ledStage, HIGH);
        digitalWrite(ledAbort, LOW);
        lcdShow("  LIFT OFF", "HAVE A SAFE FLIGHT");
        break;
        
      } else if (stageConfirm == 0 && abortConfirm == 1LOW) {

        break;
      }
      Serial.println(stageConfirm);
      Serial.println(abortConfirm);

      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;
  }
}

Edit: Basically the LEDs are placed right next to the button,(e.g. ledStage -> placed next to the buttonStage) they start to blink when the timer hits zero with a buzzer noise, and if the user presses one of the buttons, the buzzer noise stops and the LED placed next to the button they pressed turns on whereas the other turns off.

/*
   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;

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);

// 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);

  Serial.begin(9600);
  lcd.begin(16, 2);
  while (!keypad.getKey()) ;  // wait for key press
}

void loop() {
  static enum {START, MENU, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  int stageConfirm = digitalRead(buttonStage);
  int abortConfirm = digitalRead(buttonAbort);

  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);
      digitalWrite(ledAbort, HIGH);
      digitalWrite(ledStage, HIGH);
      lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
      delay(1000);
      lcd.clear();
      digitalWrite(ledAbort, LOW);
      digitalWrite(ledStage, LOW);
      delay(500);
      
      if (stageConfirm == 1 && abortConfirm == 0) {
        noTone(buzzer);
        digitalWrite(ledStage, HIGH);
        digitalWrite(ledAbort, LOW);
        lcdShow("  LIFT OFF", "HAVE A SAFE FLIGHT");
        
      } else if (stageConfirm == 0 && abortConfirm == 1) {

      }

      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;
  }
}

Edit: Basically the LEDs are placed right next to the button,(e.g. ledStage -> placed next to the buttonStage) they start to blink when the timer hits zero with a buzzer noise, and if the user presses one of the buttons, the buzzer noise stops and the LED placed next to the button they pressed turns on whereas the other turns off. I also connected the buttons without resistors. (directly to the pins)

/*
   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;

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);

// 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);

  Serial.begin(9600);
  lcd.begin(16, 2);
  while (!keypad.getKey()) ;  // wait for key press
}

void loop() {
  static enum {START, MENU, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  int stageConfirm = digitalRead(buttonStage);
  int abortConfirm = digitalRead(buttonAbort);

  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);
      digitalWrite(ledAbort, HIGH);
      digitalWrite(ledStage, HIGH);
      lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
      delay(1000);
      lcd.clear();
      digitalWrite(ledAbort, LOW);
      digitalWrite(ledStage, LOW);
      delay(500);

      stageConfirm = digitalRead(buttonStage);
      abortConfirm = digitalRead(buttonAbort);
      
      if (stageConfirm == LOW) {
        noTone(buzzer);
        digitalWrite(ledStage, HIGH);
        digitalWrite(ledAbort, LOW);
        lcdShow("  LIFT OFF", "HAVE A SAFE FLIGHT");
        break;
        
      } else if (abortConfirm == LOW) {

        break;
      }
      Serial.println(stageConfirm);
      Serial.println(abortConfirm);

      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;
  }
}
added 337 characters in body
Source Link

Edit: Basically the LEDs are placed right next to the button,(e.g. ledStage -> placed next to the buttonStage) they start to blink when the timer hits zero with a buzzer noise, and if the user presses one of the buttons, the buzzer noise stops and the LED placed next to the button they pressed turns on whereas the other turns off.

Edit: Basically the LEDs are placed right next to the button,(e.g. ledStage -> placed next to the buttonStage) they start to blink when the timer hits zero with a buzzer noise, and if the user presses one of the buttons, the buzzer noise stops and the LED placed next to the button they pressed turns on whereas the other turns off.

deleted 1314 characters in body
Source Link
/*
   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;

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};

/*
  int melody[] = {
  NOTE_F5, NOTE_D5, NOTE_AS4, NOTE_D5, NOTE_F5, NOTE_AS5, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_D5, NOTE_E5, NOTE_F5,
  NOTE_F5, NOTE_F5, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_A5, NOTE_G5, NOTE_A5, NOTE_AS5, NOTE_AS5, NOTE_F5, NOTE_D5, NOTE_AS4,
  NOTE_D6, NOTE_D6, NOTE_D6, NOTE_DS6, NOTE_F6, NOTE_F6, NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_D6, NOTE_DS6, NOTE_DS6,
  0, NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_A5, NOTE_G5, NOTE_A5, NOTE_AS5, NOTE_D5, NOTE_E5, NOTE_F5,
  NOTE_F5, NOTE_AS5, NOTE_AS5, NOTE_AS5, NOTE_A5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_C6, NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_AS5, NOTE_A5,
  NOTE_F5, NOTE_F5, NOTE_AS5, NOTE_C6, NOTE_D6, NOTE_DS6, NOTE_F6, NOTE_AS5, NOTE_C6, NOTE_D6, NOTE_DS6, NOTE_C6, NOTE_AS5
  };

  float noteDurations[] = {
  6, 12, 4, 4, 4, 2, 6, 12, 4, 4, 4, 2,
  8, 8, 8 / 2.9, 8, 4, 2, 8, 8, 4, 4, 4, 4, 4,
  6, 12, 4, 4, 4, 2, 8, 8, 4, 4, 4, 2,
  8, 8, 8 / 2.9, 8, 4, 2, 8, 8, 4, 4, 4, 2,
  4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4,
  8, 8, 8 / 2.9, 8, 8, 8, 2, 8, 8, 4, 4, 4, 2
  };

  int musicLength = sizeof(melody) / sizeof('NOTE_F5');
*/

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// 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);

  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} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  int stageConfirm = digitalRead(buttonStage);
  int abortConfirm = digitalRead(buttonAbort);

  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);
      digitalWrite(ledAbort, HIGH);
      digitalWrite(ledStage, HIGH);
      lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
      delay(1000);
      lcd.clear();
      digitalWrite(ledAbort, LOW);
      digitalWrite(ledStage, LOW);
      delay(500);
      
      if (stageConfirm == 1 ||&& abortConfirm == 0) {
        noTone(buzzer);
        digitalWrite(ledStage, HIGH);
        digitalWrite(ledAbort, LOW);
        lcdShow("  LIFT OFF", "HAVE A SAFE FLIGHT");
        
      } else if (stageConfirm == 0 ||&& abortConfirm == 1) {

      }

      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;
  }
}
/*
   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;

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};

/*
  int melody[] = {
  NOTE_F5, NOTE_D5, NOTE_AS4, NOTE_D5, NOTE_F5, NOTE_AS5, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_D5, NOTE_E5, NOTE_F5,
  NOTE_F5, NOTE_F5, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_A5, NOTE_G5, NOTE_A5, NOTE_AS5, NOTE_AS5, NOTE_F5, NOTE_D5, NOTE_AS4,
  NOTE_D6, NOTE_D6, NOTE_D6, NOTE_DS6, NOTE_F6, NOTE_F6, NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_D6, NOTE_DS6, NOTE_DS6,
  0, NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_A5, NOTE_G5, NOTE_A5, NOTE_AS5, NOTE_D5, NOTE_E5, NOTE_F5,
  NOTE_F5, NOTE_AS5, NOTE_AS5, NOTE_AS5, NOTE_A5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_C6, NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_AS5, NOTE_A5,
  NOTE_F5, NOTE_F5, NOTE_AS5, NOTE_C6, NOTE_D6, NOTE_DS6, NOTE_F6, NOTE_AS5, NOTE_C6, NOTE_D6, NOTE_DS6, NOTE_C6, NOTE_AS5
  };

  float noteDurations[] = {
  6, 12, 4, 4, 4, 2, 6, 12, 4, 4, 4, 2,
  8, 8, 8 / 2.9, 8, 4, 2, 8, 8, 4, 4, 4, 4, 4,
  6, 12, 4, 4, 4, 2, 8, 8, 4, 4, 4, 2,
  8, 8, 8 / 2.9, 8, 4, 2, 8, 8, 4, 4, 4, 2,
  4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4,
  8, 8, 8 / 2.9, 8, 8, 8, 2, 8, 8, 4, 4, 4, 2
  };

  int musicLength = sizeof(melody) / sizeof('NOTE_F5');
*/

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// 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);

  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} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  int stageConfirm = digitalRead(buttonStage);
  int abortConfirm = digitalRead(buttonAbort);

  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);
      digitalWrite(ledAbort, HIGH);
      digitalWrite(ledStage, HIGH);
      lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
      delay(1000);
      lcd.clear();
      digitalWrite(ledAbort, LOW);
      digitalWrite(ledStage, LOW);
      delay(500);
      
      if (stageConfirm == 1 || abortConfirm == 0) {
        noTone(buzzer);
        digitalWrite(ledStage, HIGH);
        digitalWrite(ledAbort, LOW);
        lcdShow("  LIFT OFF", "HAVE A SAFE FLIGHT");
        
      } else if (stageConfirm == 0 || abortConfirm == 1) {

      }

      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;
  }
}
/*
   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;

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);

// 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);

  Serial.begin(9600);
  lcd.begin(16, 2);
  while (!keypad.getKey()) ;  // wait for key press
}

void loop() {
  static enum {START, MENU, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  int stageConfirm = digitalRead(buttonStage);
  int abortConfirm = digitalRead(buttonAbort);

  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);
      digitalWrite(ledAbort, HIGH);
      digitalWrite(ledStage, HIGH);
      lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
      delay(1000);
      lcd.clear();
      digitalWrite(ledAbort, LOW);
      digitalWrite(ledStage, LOW);
      delay(500);
      
      if (stageConfirm == 1 && abortConfirm == 0) {
        noTone(buzzer);
        digitalWrite(ledStage, HIGH);
        digitalWrite(ledAbort, LOW);
        lcdShow("  LIFT OFF", "HAVE A SAFE FLIGHT");
        
      } else if (stageConfirm == 0 && abortConfirm == 1) {

      }

      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;
  }
}
Source Link
Loading