Components and supplies
1
Arduino Micro
1
RGB LCD Shield Kit, 16x2 Character Display
1
5 mm LED: Green
1
5 mm LED: Red
Tools and machines
1
PCB, For DMB-4775
1
Soldering iron (generic)
1
Solder Wire, Lead Free
Project description
Code
HoustonOS
c_cpp
1/* 2 Jebediah's Launch Control System for Kerbal Space Program 3 4 Version 2.0 5 An Open-Source Project by John Seong 6*/ 7 8#include 9 <Wire.h> 10#include <LiquidCrystal_I2C.h> 11#include <Keypad.h> 12#include <Keyboard.h> 13 14#define 15 NOTE_C4 262 16#define NOTE_CS4 277 17#define NOTE_D4 294 18#define NOTE_DS4 19 311 20#define NOTE_E4 330 21#define NOTE_F4 349 22#define NOTE_FS4 370 23#define 24 NOTE_G4 392 25#define NOTE_GS4 415 26#define NOTE_A4 440 27#define NOTE_AS4 28 466 29#define NOTE_B4 494 30#define NOTE_C5 523 31#define NOTE_CS5 554 32#define 33 NOTE_D5 587 34#define NOTE_DS5 622 35#define NOTE_E5 659 36#define NOTE_F5 37 698 38#define NOTE_FS5 740 39#define NOTE_G5 784 40 41int melody[] = { 42 43 NOTE_G4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5, NOTE_E5, NOTE_D5, NOTE_C5, 44 NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, 45 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, NOTE_G4, NOTE_E4, NOTE_C4, 46 NOTE_G4, NOTE_E4, 47 NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_E4, NOTE_FS4, 48 NOTE_G4, NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, 49 NOTE_C5, NOTE_C5, NOTE_G4, NOTE_E4, NOTE_C4, 50 NOTE_E5, NOTE_E5, NOTE_E5, NOTE_F5, 51 NOTE_G5, NOTE_G5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, NOTE_F5, 52 NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_E4, NOTE_FS4, 53 NOTE_G4, 54 NOTE_G4, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_A4, NOTE_A4, 55 NOTE_D5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_C5, NOTE_B4, NOTE_G4, NOTE_G4, 56 NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, 57 NOTE_D5, NOTE_C5 58}; 59 60int noteDurations[] = { 61 6, 8, 4, 4, 4, 2, 6, 62 8, 4, 4, 4, 2, 8, 8, 3, 8, 4, 2, 6, 8, 4, 4, 4, 4, 4, 63 6, 8, 4, 4, 4, 2, 6, 64 8, 4, 4, 4, 2, 8, 8, 3, 8, 4, 2, 6, 8, 4, 4, 4, 4, 4, 65 8, 8, 4, 4, 4, 2, 8, 66 8, 4, 4, 4, 2, 4, 3, 8, 4, 2, 6, 8, 4, 4, 4, 2, 67 4, 4, 4, 8, 8, 4, 4, 4, 4, 68 8, 8, 8, 8, 4, 4, 8, 8, 3, 8, 8, 8, 2, 8, 8, 3, 8, 4, 2 69}; 70 71const byte 72 ROWS = 4; 73const byte COLS = 3; 74 75const int buzzer = A3; 76 77const int 78 ledAbort = A5; 79const int ledStage = 5; 80 81const int buttonAbort = 4; 82const 83 int buttonStage = A4; 84 85char keys[ROWS][COLS] = { 86 {'1', '2', '3'}, 87 88 {'4', '5', '6'}, 89 {'7', '8', '9'}, 90 {'*', '0', '#'} 91}; 92 93byte 94 rowPins[ROWS] = {12, 11, 10, 9}; 95byte colPins[COLS] = {8, 7, 6}; 96 97Keypad 98 keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); 99 100LiquidCrystal_I2C 101 lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 102 103// Show a two-line message on 104 the LCD. 105void lcdShow(const char *line0, const char *line1) { 106 lcd.clear(); 107 108 lcd.print(line0); 109 lcd.setCursor(0, 1); 110 lcd.print(line1); 111} 112 113void 114 lcdShowResult(float result) { 115 lcd.print(result); 116} 117 118void setup() { 119 120 pinMode(buzzer, OUTPUT); 121 122 pinMode(ledAbort, OUTPUT); 123 pinMode(ledStage, 124 OUTPUT); 125 126 pinMode(buttonAbort, INPUT_PULLUP); 127 pinMode(buttonStage, 128 INPUT_PULLUP); 129 130 pinMode(buzzer, OUTPUT); 131 Serial.begin(9600); 132 lcd.begin(16, 133 2); 134 Keyboard.begin(); 135 lcdShow("JEB'S LAUNCH", "CONTROL SYSTEM"); 136 137 delay(3000); 138 lcdShow("VERSION 2.0", "STUDIO HORIZON"); 139 delay(3000); 140 141 lcdShow("WELCOME, KERMAN.", "PRESS ANY KEY..."); 142 while (!keypad.getKey()) 143 ; // wait for key press 144} 145 146void loop() { 147 static enum {START, MENU, 148 START2, MENU2, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT, LAUNCH_CONFIRMED, 149 LAUNCH_CONFIRMED_FN, VEHICLE_CONTROLS, RCS_CONTROLS, RCS_CONTROLS_FN, ENGINE_CONTROLS, 150 ENGINE_CONTROLS_FN} state = START; 151 static uint32_t last_second, preMillis; 152 // millis() value on last full second 153 static int count; 154 static float 155 thrust, weight, ratio; 156 157 char key = keypad.getKey(); 158 159 switch (state) 160 { 161 case START: // transitional state 162 lcdShow("1. LAUNCH SEQ.", 163 "2. VEHICLE CTRL."); 164 noTone(buzzer); 165 state = MENU; 166 /* 167 fallthrough */ 168 169 case MENU: 170 if (key == '1') { // Countdown 171 172 lcdShow("COUNTDOWN TIMER", "SECONDS: "); 173 count = 0; 174 state 175 = SET_COUNT; 176 177 } else if (key == '2') { // Controls 178 lcdShow("VEHICLE", 179 "CONTROL MODE"); 180 delay(1000); 181 lcdShow("1. RCS CONTROLS", 182 "2. ENG CONTROLS"); 183 state = VEHICLE_CONTROLS; 184 185 } else if 186 (key == '8') { 187 state = START2; 188 } 189 break; 190 191 case 192 START2: 193 lcdShow("2. VEHICLE CTRL.", "3. TWR CALC."); 194 state 195 = MENU2; 196 /* fallthrough */ 197 198 case MENU2: 199 if (key == '2') 200 { // Controls 201 lcdShow("VEHICLE", "CONTROL MODE"); 202 delay(1000); 203 204 lcdShow("1. RCS CONTROLS", "2. ENG CONTROLS"); 205 state = VEHICLE_CONTROLS; 206 207 208 } else if (key == '3') { // TWR 209 lcdShow("TWR CALCULATOR", "THRUST: 210 "); 211 thrust = 0, weight = 0, ratio = 0; 212 state = SET_THRUST; 213 214 215 216 } else if (key == '5') { 217 state = START; 218 } 219 break; 220 221 222 case SET_COUNT: 223 if (key >= '0' && key <= '9' && count <= 99) { 224 225 lcd.print(key); 226 count = 10 * count + (key - '0'); 227 228 } 229 else if (key == '#') { 230 lcdShow(" T-MINUS", " SECONDS"); 231 232 // Force a refresh on entering COUNT_DOWN: 233 last_second = millis() 234 - 1000; 235 count++; 236 state = COUNT_DOWN; 237 238 } else if 239 (key == '*') { 240 state = START; 241 } 242 break; 243 244 case 245 COUNT_DOWN: 246 if (millis() - last_second >= 1000) { 247 last_second 248 += 1000; 249 count--; 250 251 if (count <= 10) { 252 tone(buzzer, 253 500); 254 delay(500); 255 noTone(buzzer); 256 } 257 258 259 if (count == 0) { 260 Serial.println("Lift off!"); 261 262 } 263 else if (count < 0) { 264 preMillis = millis() - 500; 265 state 266 = LAUNCH; 267 } 268 lcd.setCursor(1, 1); 269 lcd.print(count 270 < 10 ? " " : count < 100 ? " " : ""); // pad 271 lcd.print(count); 272 273 } else if (key == '*') { 274 state = START; 275 } 276 break; 277 278 279 case LAUNCH: 280 tone(buzzer, 3000); 281 if (millis() - preMillis 282 >= 500) { 283 preMillis += 500; 284 285 if (digitalRead(ledAbort) 286 == LOW && digitalRead(ledStage) == LOW) { 287 lcdShow(" T-ZERO WARNING", 288 "CONFIRM IGNITION"); 289 digitalWrite(ledAbort, HIGH); 290 digitalWrite(ledStage, 291 HIGH); 292 293 } else if (digitalRead(ledAbort) == HIGH && digitalRead(ledStage) 294 == HIGH) { 295 lcd.clear(); 296 digitalWrite(ledAbort, LOW); 297 298 digitalWrite(ledStage, LOW); 299 } 300 301 } else if (key 302 == '*' || (digitalRead(buttonAbort == HIGH) && digitalRead(buttonStage) == LOW)) 303 { 304 lcdShow("LAUNCH ABORT", "SELECTED!"); 305 digitalWrite(ledAbort, 306 HIGH); 307 digitalWrite(ledStage, LOW); 308 Keyboard.write('x'); // 309 MECO 310 delay(500); 311 Keyboard.write(0xB2); // for Mac users 312 313 Keyboard.write(0xD4); // for Windows users 314 Keyboard.write('z'); 315 // Abort motors full throttle 316 delay(2000); 317 digitalWrite(ledAbort, 318 LOW); 319 state = START; 320 321 } else if (key == '#' || (digitalRead(buttonStage 322 == HIGH) && digitalRead(buttonAbort) == LOW)) { 323 lcdShow("KERBIN, WE 324 ARE", "GO FOR LAUNCH!"); 325 digitalWrite(ledAbort, LOW); 326 digitalWrite(ledStage, 327 HIGH); 328 delay(2000); 329 digitalWrite(ledStage, LOW); 330 state 331 = LAUNCH_CONFIRMED; 332 } 333 break; 334 335 case SET_THRUST: 336 if 337 (key >= '0' && key <= '9' && thrust <= 9999) { 338 lcd.print(key); 339 thrust 340 = 10 * thrust + (key - '0'); 341 342 } else if (key == '#') { 343 lcdShow("TWR 344 CALCULATOR", "WEIGHT: "); 345 state = SET_WEIGHT; 346 347 } else 348 if (key == '*') { 349 state = START; 350 } 351 break; 352 353 case 354 SET_WEIGHT: 355 if (key >= '0' && key <= '9' && weight <= 9999) { 356 lcd.print(key); 357 358 weight = 10 * weight + (key - '0'); 359 360 } else if (key == '#') 361 { 362 lcdShow("THRUST-TO-WEIGHT", "RATIO: "); 363 if (thrust != 364 0 || weight != 0) { 365 ratio = thrust / weight; 366 lcdShowResult(ratio); 367 368 } 369 370 } else if (key == '*') { 371 state = START; 372 } 373 374 break; 375 376 case LAUNCH_CONFIRMED: 377 tone(buzzer, 1000); 378 379 lcdShow("MAIN ENGINE", "IGNITION!"); 380 Keyboard.write((char) 32); 381 382 Keyboard.write('z'); // Ignition 383 delay(1500); 384 Keyboard.write((char) 385 32); // Press space bar 386 lcdShow("KRAKEN BLESS", "AMERIKA!"); 387 for 388 (int thisNote = 0; thisNote < 101; thisNote++) { 389 int noteDuration = 1000 390 / noteDurations[thisNote]; 391 tone(buzzer, melody[thisNote], noteDuration); 392 393 int pauseBetweenNotes = noteDuration * 1.40; 394 delay(pauseBetweenNotes); 395 396 noTone(buzzer); 397 } 398 lcdShow("PRESS *", "TO PAY RESPECTS"); 399 400 state = LAUNCH_CONFIRMED_FN; 401 /* fallthrough */ 402 403 case LAUNCH_CONFIRMED_FN: 404 405 if (key == '*') { 406 lcdShow("VEHICLE", "CONTROL MODE"); 407 delay(1000); 408 409 lcdShow("1. RCS CONTROLS", "2. ENG CONTROLS"); 410 state = VEHICLE_CONTROLS; 411 412 } 413 break; 414 415 case VEHICLE_CONTROLS: 416 if (key == '1') 417 { 418 state = RCS_CONTROLS; 419 420 } else if (key == '2') { 421 lcdShow("THROTTLE", 422 "PRESS ARROW KEYS"); 423 state = ENGINE_CONTROLS; 424 425 } else if 426 (key == '*') { 427 state = START; 428 } 429 break; 430 431 case 432 RCS_CONTROLS: 433 lcdShow("REACTION CONTROL", "PRESS ARROW KEYS"); 434 435 noTone(buzzer); 436 state = RCS_CONTROLS_FN; 437 /* fallthrough */ 438 439 440 case RCS_CONTROLS_FN: 441 if (key == '1') { 442 lcdShow("REACTION 443 CONTROL", "[FORWARD]"); 444 Keyboard.write('H'); 445 tone(buzzer, 446 500); 447 delay(500); 448 state = RCS_CONTROLS; 449 450 } else 451 if (key == '3') { 452 lcdShow("REACTION CONTROL", "[BACKWARD]"); 453 454 Keyboard.write('N'); 455 tone(buzzer, 500); 456 delay(500); 457 458 state = RCS_CONTROLS; 459 460 } else if (key == '4') { 461 lcdShow("REACTION 462 CONTROL", "[ROLL LEFT]"); 463 Keyboard.write('Q'); 464 tone(buzzer, 465 500); 466 delay(500); 467 state = RCS_CONTROLS; 468 469 } else 470 if (key == '5') { 471 lcdShow("REACTION CONTROL", "[PITCH DOWN]"); 472 473 Keyboard.write('W'); 474 tone(buzzer, 500); 475 delay(500); 476 477 state = RCS_CONTROLS; 478 479 } else if (key == '6') { 480 lcdShow("REACTION 481 CONTROL", "[ROLL RIGHT]"); 482 Keyboard.write('E'); 483 tone(buzzer, 484 500); 485 delay(500); 486 state = RCS_CONTROLS; 487 488 } else 489 if (key == '7') { 490 lcdShow("REACTION CONTROL", "[YAW LEFT]"); 491 492 Keyboard.write('A'); 493 tone(buzzer, 500); 494 delay(500); 495 496 state = RCS_CONTROLS; 497 498 } else if (key == '8') { 499 lcdShow("REACTION 500 CONTROL", "[PITCH UP]"); 501 Keyboard.write('S'); 502 tone(buzzer, 503 500); 504 delay(500); 505 state = RCS_CONTROLS; 506 507 } else 508 if (key == '9') { 509 lcdShow("REACTION CONTROL", "[YAW RIGHT]"); 510 511 Keyboard.write('D'); 512 tone(buzzer, 500); 513 delay(500); 514 515 state = RCS_CONTROLS; 516 517 } else if (key == '*') { 518 state 519 = START; 520 521 } else if (digitalRead(buttonAbort == HIGH) && digitalRead(buttonStage) 522 == LOW) { 523 lcdShow("LAUNCH ABORT", "SELECTED!"); 524 tone(buzzer, 525 500); 526 digitalWrite(ledAbort, HIGH); 527 digitalWrite(ledStage, 528 LOW); 529 Keyboard.write('x'); // MECO 530 delay(500); 531 Keyboard.write(0xB2); 532 // for Mac users 533 Keyboard.write(0xD4); // for Windows users 534 Keyboard.write('z'); 535 // Abort motors full throttle 536 delay(2000); 537 digitalWrite(ledAbort, 538 LOW); 539 state = RCS_CONTROLS; 540 541 } else if (digitalRead(buttonStage 542 == HIGH) && digitalRead(buttonAbort) == LOW) { 543 lcdShow("STAGE SEPARATION", 544 "CONFIRMED!"); 545 Keyboard.write((char) 32); 546 tone(buzzer, 500); 547 548 digitalWrite(ledAbort, LOW); 549 digitalWrite(ledStage, HIGH); 550 551 delay(2000); 552 digitalWrite(ledStage, LOW); 553 state = 554 RCS_CONTROLS; 555 } 556 break; 557 558 case ENGINE_CONTROLS: 559 lcdShow("FUEL 560 CONTROL", "PRESS ARROW KEYS"); 561 noTone(buzzer); 562 state = ENGINE_CONTROLS_FN; 563 564 /* fallthrough */ 565 566 case ENGINE_CONTROLS_FN: 567 if (key == '5') 568 { 569 lcdShow("FUEL CONTROL", "[THROTTLE 100 %]"); 570 Keyboard.write('z'); 571 572 tone(buzzer, 500); 573 delay(500); 574 state = ENGINE_CONTROLS; 575 576 577 } else if (key == '8') { 578 lcdShow("FUEL CONTROL", "[THROTTLE 579 0 %]"); 580 Keyboard.write('x'); 581 tone(buzzer, 500); 582 delay(500); 583 584 state = ENGINE_CONTROLS; 585 586 } else if (key == '*') { 587 state 588 = START; 589 590 } else if (digitalRead(buttonAbort == HIGH) && digitalRead(buttonStage) 591 == LOW) { 592 lcdShow("LAUNCH ABORT", "SELECTED!"); 593 tone(buzzer, 594 500); 595 digitalWrite(ledAbort, HIGH); 596 digitalWrite(ledStage, 597 LOW); 598 Keyboard.write('x'); // MECO 599 delay(500); 600 Keyboard.write(0xB2); 601 // for Mac users 602 Keyboard.write(0xD4); // for Windows users 603 Keyboard.write('z'); 604 // Abort motors full throttle 605 delay(2000); 606 digitalWrite(ledAbort, 607 LOW); 608 state = ENGINE_CONTROLS; 609 610 } else if (digitalRead(buttonStage 611 == HIGH) && digitalRead(buttonAbort) == LOW) { 612 lcdShow("STAGE SEPARATION", 613 "CONFIRMED!"); 614 Keyboard.write((char) 32); 615 tone(buzzer, 500); 616 617 digitalWrite(ledAbort, LOW); 618 digitalWrite(ledStage, HIGH); 619 620 delay(2000); 621 digitalWrite(ledStage, LOW); 622 state = 623 ENGINE_CONTROLS; 624 } 625 break; 626 } 627}
GitHub
HoustonOS
c_cpp
1/* 2 Jebediah's Launch Control System for Kerbal Space Program 3 Version 2.0 4 An Open-Source Project by John Seong 5*/ 6 7#include <Wire.h> 8#include <LiquidCrystal_I2C.h> 9#include <Keypad.h> 10#include <Keyboard.h> 11 12#define NOTE_C4 262 13#define NOTE_CS4 277 14#define NOTE_D4 294 15#define NOTE_DS4 311 16#define NOTE_E4 330 17#define NOTE_F4 349 18#define NOTE_FS4 370 19#define NOTE_G4 392 20#define NOTE_GS4 415 21#define NOTE_A4 440 22#define NOTE_AS4 466 23#define NOTE_B4 494 24#define NOTE_C5 523 25#define NOTE_CS5 554 26#define NOTE_D5 587 27#define NOTE_DS5 622 28#define NOTE_E5 659 29#define NOTE_F5 698 30#define NOTE_FS5 740 31#define NOTE_G5 784 32 33int melody[] = { 34 NOTE_G4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, NOTE_G4, NOTE_E4, NOTE_C4, 35 NOTE_G4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_G4, NOTE_C5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, NOTE_G4, NOTE_E4, NOTE_C4, 36 NOTE_E5, NOTE_E5, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_G5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_E4, NOTE_FS4, NOTE_G4, 37 NOTE_G4, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_A4, NOTE_A4, NOTE_D5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_C5, NOTE_B4, NOTE_G4, NOTE_G4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_G5, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_F5, NOTE_D5, NOTE_C5 38}; 39 40int noteDurations[] = { 41 6, 8, 4, 4, 4, 2, 6, 8, 4, 4, 4, 2, 8, 8, 3, 8, 4, 2, 6, 8, 4, 4, 4, 4, 4, 42 6, 8, 4, 4, 4, 2, 6, 8, 4, 4, 4, 2, 8, 8, 3, 8, 4, 2, 6, 8, 4, 4, 4, 4, 4, 43 8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4, 2, 4, 3, 8, 4, 2, 6, 8, 4, 4, 4, 2, 44 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 8, 8, 3, 8, 8, 8, 2, 8, 8, 3, 8, 4, 2 45}; 46 47const byte ROWS = 4; 48const byte COLS = 3; 49 50const int buzzer = A3; 51 52const int ledAbort = A5; 53const int ledStage = 5; 54 55const int buttonAbort = 4; 56const int buttonStage = A4; 57 58char keys[ROWS][COLS] = { 59 {'1', '2', '3'}, 60 {'4', '5', '6'}, 61 {'7', '8', '9'}, 62 {'*', '0', '#'} 63}; 64 65byte rowPins[ROWS] = {12, 11, 10, 9}; 66byte colPins[COLS] = {8, 7, 6}; 67 68Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); 69 70LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 71 72// Show a two-line message on the LCD. 73void lcdShow(const char *line0, const char *line1) { 74 lcd.clear(); 75 lcd.print(line0); 76 lcd.setCursor(0, 1); 77 lcd.print(line1); 78} 79 80void lcdShowResult(float result) { 81 lcd.print(result); 82} 83 84void setup() { 85 pinMode(buzzer, OUTPUT); 86 87 pinMode(ledAbort, OUTPUT); 88 pinMode(ledStage, OUTPUT); 89 90 pinMode(buttonAbort, INPUT_PULLUP); 91 pinMode(buttonStage, INPUT_PULLUP); 92 93 pinMode(buzzer, OUTPUT); 94 Serial.begin(9600); 95 lcd.begin(16, 2); 96 Keyboard.begin(); 97 lcdShow("JEB'S LAUNCH", "CONTROL SYSTEM"); 98 delay(3000); 99 lcdShow("VERSION 2.0", "STUDIO HORIZON"); 100 delay(3000); 101 lcdShow("WELCOME, KERMAN.", "PRESS ANY KEY..."); 102 while (!keypad.getKey()) ; // wait for key press 103} 104 105void loop() { 106 static enum {START, MENU, START2, MENU2, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT, LAUNCH_CONFIRMED, LAUNCH_CONFIRMED_FN, VEHICLE_CONTROLS, RCS_CONTROLS, RCS_CONTROLS_FN, ENGINE_CONTROLS, ENGINE_CONTROLS_FN} state = START; 107 static uint32_t last_second, preMillis; // millis() value on last full second 108 static int count; 109 static float thrust, weight, ratio; 110 111 char key = keypad.getKey(); 112 113 switch (state) { 114 case START: // transitional state 115 lcdShow("1. LAUNCH SEQ.", "2. VEHICLE CTRL."); 116 noTone(buzzer); 117 state = MENU; 118 /* fallthrough */ 119 120 case MENU: 121 if (key == '1') { // Countdown 122 lcdShow("COUNTDOWN TIMER", "SECONDS: "); 123 count = 0; 124 state = SET_COUNT; 125 126 } else if (key == '2') { // Controls 127 lcdShow("VEHICLE", "CONTROL MODE"); 128 delay(1000); 129 lcdShow("1. RCS CONTROLS", "2. ENG CONTROLS"); 130 state = VEHICLE_CONTROLS; 131 132 } else if (key == '8') { 133 state = START2; 134 } 135 break; 136 137 case START2: 138 lcdShow("2. VEHICLE CTRL.", "3. TWR CALC."); 139 state = MENU2; 140 /* fallthrough */ 141 142 case MENU2: 143 if (key == '2') { // Controls 144 lcdShow("VEHICLE", "CONTROL MODE"); 145 delay(1000); 146 lcdShow("1. RCS CONTROLS", "2. ENG CONTROLS"); 147 state = VEHICLE_CONTROLS; 148 149 } else if (key == '3') { // TWR 150 lcdShow("TWR CALCULATOR", "THRUST: "); 151 thrust = 0, weight = 0, ratio = 0; 152 state = SET_THRUST; 153 154 155 } else if (key == '5') { 156 state = START; 157 } 158 break; 159 160 case SET_COUNT: 161 if (key >= '0' && key <= '9' && count <= 99) { 162 lcd.print(key); 163 count = 10 * count + (key - '0'); 164 165 } else if (key == '#') { 166 lcdShow(" T-MINUS", " SECONDS"); 167 // Force a refresh on entering COUNT_DOWN: 168 last_second = millis() - 1000; 169 count++; 170 state = COUNT_DOWN; 171 172 } else if (key == '*') { 173 state = START; 174 } 175 break; 176 177 case COUNT_DOWN: 178 if (millis() - last_second >= 1000) { 179 last_second += 1000; 180 count--; 181 182 if (count <= 10) { 183 tone(buzzer, 500); 184 delay(500); 185 noTone(buzzer); 186 } 187 188 if (count == 0) { 189 Serial.println("Lift off!"); 190 191 } else if (count < 0) { 192 preMillis = millis() - 500; 193 state = LAUNCH; 194 } 195 lcd.setCursor(1, 1); 196 lcd.print(count < 10 ? " " : count < 100 ? " " : ""); // pad 197 lcd.print(count); 198 } else if (key == '*') { 199 state = START; 200 } 201 break; 202 203 case LAUNCH: 204 tone(buzzer, 3000); 205 if (millis() - preMillis >= 500) { 206 preMillis += 500; 207 208 if (digitalRead(ledAbort) == LOW && digitalRead(ledStage) == LOW) { 209 lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION"); 210 digitalWrite(ledAbort, HIGH); 211 digitalWrite(ledStage, HIGH); 212 213 } else if (digitalRead(ledAbort) == HIGH && digitalRead(ledStage) == HIGH) { 214 lcd.clear(); 215 digitalWrite(ledAbort, LOW); 216 digitalWrite(ledStage, LOW); 217 } 218 219 } else if (key == '*' || (digitalRead(buttonAbort == HIGH) && digitalRead(buttonStage) == LOW)) { 220 lcdShow("LAUNCH ABORT", "SELECTED!"); 221 digitalWrite(ledAbort, HIGH); 222 digitalWrite(ledStage, LOW); 223 Keyboard.write('x'); // MECO 224 delay(500); 225 Keyboard.write(0xB2); // for Mac users 226 Keyboard.write(0xD4); // for Windows users 227 Keyboard.write('z'); // Abort motors full throttle 228 delay(2000); 229 digitalWrite(ledAbort, LOW); 230 state = START; 231 232 } else if (key == '#' || (digitalRead(buttonStage == HIGH) && digitalRead(buttonAbort) == LOW)) { 233 lcdShow("KERBIN, WE ARE", "GO FOR LAUNCH!"); 234 digitalWrite(ledAbort, LOW); 235 digitalWrite(ledStage, HIGH); 236 delay(2000); 237 digitalWrite(ledStage, LOW); 238 state = LAUNCH_CONFIRMED; 239 } 240 break; 241 242 case SET_THRUST: 243 if (key >= '0' && key <= '9' && thrust <= 9999) { 244 lcd.print(key); 245 thrust = 10 * thrust + (key - '0'); 246 247 } else if (key == '#') { 248 lcdShow("TWR CALCULATOR", "WEIGHT: "); 249 state = SET_WEIGHT; 250 251 } else if (key == '*') { 252 state = START; 253 } 254 break; 255 256 case SET_WEIGHT: 257 if (key >= '0' && key <= '9' && weight <= 9999) { 258 lcd.print(key); 259 weight = 10 * weight + (key - '0'); 260 261 } else if (key == '#') { 262 lcdShow("THRUST-TO-WEIGHT", "RATIO: "); 263 if (thrust != 0 || weight != 0) { 264 ratio = thrust / weight; 265 lcdShowResult(ratio); 266 } 267 268 } else if (key == '*') { 269 state = START; 270 } 271 break; 272 273 case LAUNCH_CONFIRMED: 274 tone(buzzer, 1000); 275 lcdShow("MAIN ENGINE", "IGNITION!"); 276 Keyboard.write((char) 32); 277 Keyboard.write('z'); // Ignition 278 delay(1500); 279 Keyboard.write((char) 32); // Press space bar 280 lcdShow("KRAKEN BLESS", "AMERIKA!"); 281 for (int thisNote = 0; thisNote < 101; thisNote++) { 282 int noteDuration = 1000 / noteDurations[thisNote]; 283 tone(buzzer, melody[thisNote], noteDuration); 284 int pauseBetweenNotes = noteDuration * 1.40; 285 delay(pauseBetweenNotes); 286 noTone(buzzer); 287 } 288 lcdShow("PRESS *", "TO PAY RESPECTS"); 289 state = LAUNCH_CONFIRMED_FN; 290 /* fallthrough */ 291 292 case LAUNCH_CONFIRMED_FN: 293 if (key == '*') { 294 lcdShow("VEHICLE", "CONTROL MODE"); 295 delay(1000); 296 lcdShow("1. RCS CONTROLS", "2. ENG CONTROLS"); 297 state = VEHICLE_CONTROLS; 298 } 299 break; 300 301 case VEHICLE_CONTROLS: 302 if (key == '1') { 303 state = RCS_CONTROLS; 304 305 } else if (key == '2') { 306 lcdShow("THROTTLE", "PRESS ARROW KEYS"); 307 state = ENGINE_CONTROLS; 308 309 } else if (key == '*') { 310 state = START; 311 } 312 break; 313 314 case RCS_CONTROLS: 315 lcdShow("REACTION CONTROL", "PRESS ARROW KEYS"); 316 noTone(buzzer); 317 state = RCS_CONTROLS_FN; 318 /* fallthrough */ 319 320 case RCS_CONTROLS_FN: 321 if (key == '1') { 322 lcdShow("REACTION CONTROL", "[FORWARD]"); 323 Keyboard.write('H'); 324 tone(buzzer, 500); 325 delay(500); 326 state = RCS_CONTROLS; 327 328 } else if (key == '3') { 329 lcdShow("REACTION CONTROL", "[BACKWARD]"); 330 Keyboard.write('N'); 331 tone(buzzer, 500); 332 delay(500); 333 state = RCS_CONTROLS; 334 335 } else if (key == '4') { 336 lcdShow("REACTION CONTROL", "[ROLL LEFT]"); 337 Keyboard.write('Q'); 338 tone(buzzer, 500); 339 delay(500); 340 state = RCS_CONTROLS; 341 342 } else if (key == '5') { 343 lcdShow("REACTION CONTROL", "[PITCH DOWN]"); 344 Keyboard.write('W'); 345 tone(buzzer, 500); 346 delay(500); 347 state = RCS_CONTROLS; 348 349 } else if (key == '6') { 350 lcdShow("REACTION CONTROL", "[ROLL RIGHT]"); 351 Keyboard.write('E'); 352 tone(buzzer, 500); 353 delay(500); 354 state = RCS_CONTROLS; 355 356 } else if (key == '7') { 357 lcdShow("REACTION CONTROL", "[YAW LEFT]"); 358 Keyboard.write('A'); 359 tone(buzzer, 500); 360 delay(500); 361 state = RCS_CONTROLS; 362 363 } else if (key == '8') { 364 lcdShow("REACTION CONTROL", "[PITCH UP]"); 365 Keyboard.write('S'); 366 tone(buzzer, 500); 367 delay(500); 368 state = RCS_CONTROLS; 369 370 } else if (key == '9') { 371 lcdShow("REACTION CONTROL", "[YAW RIGHT]"); 372 Keyboard.write('D'); 373 tone(buzzer, 500); 374 delay(500); 375 state = RCS_CONTROLS; 376 377 } else if (key == '*') { 378 state = START; 379 380 } else if (digitalRead(buttonAbort == HIGH) && digitalRead(buttonStage) == LOW) { 381 lcdShow("LAUNCH ABORT", "SELECTED!"); 382 tone(buzzer, 500); 383 digitalWrite(ledAbort, HIGH); 384 digitalWrite(ledStage, LOW); 385 Keyboard.write('x'); // MECO 386 delay(500); 387 Keyboard.write(0xB2); // for Mac users 388 Keyboard.write(0xD4); // for Windows users 389 Keyboard.write('z'); // Abort motors full throttle 390 delay(2000); 391 digitalWrite(ledAbort, LOW); 392 state = RCS_CONTROLS; 393 394 } else if (digitalRead(buttonStage == HIGH) && digitalRead(buttonAbort) == LOW) { 395 lcdShow("STAGE SEPARATION", "CONFIRMED!"); 396 Keyboard.write((char) 32); 397 tone(buzzer, 500); 398 digitalWrite(ledAbort, LOW); 399 digitalWrite(ledStage, HIGH); 400 delay(2000); 401 digitalWrite(ledStage, LOW); 402 state = RCS_CONTROLS; 403 } 404 break; 405 406 case ENGINE_CONTROLS: 407 lcdShow("FUEL CONTROL", "PRESS ARROW KEYS"); 408 noTone(buzzer); 409 state = ENGINE_CONTROLS_FN; 410 /* fallthrough */ 411 412 case ENGINE_CONTROLS_FN: 413 if (key == '5') { 414 lcdShow("FUEL CONTROL", "[THROTTLE 100 %]"); 415 Keyboard.write('z'); 416 tone(buzzer, 500); 417 delay(500); 418 state = ENGINE_CONTROLS; 419 420 } else if (key == '8') { 421 lcdShow("FUEL CONTROL", "[THROTTLE 0 %]"); 422 Keyboard.write('x'); 423 tone(buzzer, 500); 424 delay(500); 425 state = ENGINE_CONTROLS; 426 427 } else if (key == '*') { 428 state = START; 429 430 } else if (digitalRead(buttonAbort == HIGH) && digitalRead(buttonStage) == LOW) { 431 lcdShow("LAUNCH ABORT", "SELECTED!"); 432 tone(buzzer, 500); 433 digitalWrite(ledAbort, HIGH); 434 digitalWrite(ledStage, LOW); 435 Keyboard.write('x'); // MECO 436 delay(500); 437 Keyboard.write(0xB2); // for Mac users 438 Keyboard.write(0xD4); // for Windows users 439 Keyboard.write('z'); // Abort motors full throttle 440 delay(2000); 441 digitalWrite(ledAbort, LOW); 442 state = ENGINE_CONTROLS; 443 444 } else if (digitalRead(buttonStage == HIGH) && digitalRead(buttonAbort) == LOW) { 445 lcdShow("STAGE SEPARATION", "CONFIRMED!"); 446 Keyboard.write((char) 32); 447 tone(buzzer, 500); 448 digitalWrite(ledAbort, LOW); 449 digitalWrite(ledStage, HIGH); 450 delay(2000); 451 digitalWrite(ledStage, LOW); 452 state = ENGINE_CONTROLS; 453 } 454 break; 455 } 456}
Comments
Only logged in users can leave comments