Alan Wang
Published © CC BY-NC-SA

A Simple Kerbal Space Program Arduino Leonardo Controller

Just as the title says - with a 20-min gameplay video as proof.

BeginnerShowcase (no instructions)7,936
A Simple Kerbal Space Program Arduino Leonardo Controller

Things used in this project

Hardware components

Arduino Leonardo
Arduino Leonardo
×1
Breadboard (generic)
Breadboard (generic)
×1
Rotary Encoder with Push-Button
Rotary Encoder with Push-Button
×1
Big Red Dome Button
SparkFun Big Red Dome Button
×1
Slide Switch
Slide Switch
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Code

Kerbal Controller

Arduino
#include "Keyboard.h"
#include "Talkie.h"
#include "Vocab_US_Large.h"

#define JOYSTICK_UP_KEY 'W'
#define JOYSTICK_DW_KEY 'S'
#define JOYSTICK_LT_KEY 'A'
#define JOYSTICK_RT_KEY 'D'
#define JOYSTICK_SW_KEY KEY_DELETE
#define BUTTON_1_KEY    'M'
#define BUTTON_2_KEY    'H'
#define BUTTON_3_KEY    'N'
#define BUTTON_4_KEY    'Q'
#define BUTTON_5_KEY    'E'
#define STAGE_KEY       ' '
#define ENGINE_ON_KEY   'Z'
#define ENGINE_OFF_KEY  'X'
#define ROTARY_UP_KEY   KEY_LEFT_CTRL // change throttle up key in the game
#define ROTARY_DW_KEY   KEY_RIGHT_CTRL // change throttle down key in the game
#define ROTARY_SW_KEY   'G'
#define SAS_KEY         'T'
#define RCS_KEY         'R'

#define JOYSTICK_X      A0
#define JOYSTICK_Y      A1
#define JOYSTICK_SW     A2
#define BUTTONS         A3
#define ENGINE          A4
#define POWER           A5
#define ROTARY_CLK      2
#define ROTARY_DTA      3
#define ROTARY_SW       4
#define STAGE           5
#define SAS             6
#define RCS             7
#define POWER_LED       8
#define ENGINE_LED      11
#define RCS_LED         12
#define SAS_LED         13
// the speaker is connected to pin 9 (+) and 10 (-)

#define BUTTON_G_V      4400
#define BUTTON_R_V      1000
#define BUTTON_W_V      1500
#define BUTTON_Y_V      500
#define BUTTON_B_V      2500

int joystick_x;
int joystick_y;
int joystick_sw;
int buttons;
int button_pressed;
int buttons_v[5] = {BUTTON_G_V, BUTTON_R_V, BUTTON_W_V, BUTTON_Y_V, BUTTON_B_V};
int rotary_clk = 1;
int rotary_clk_prev = 1;
int rotary_dta = 1;
int rotary_sw;
int rotary_dir;
int stage;
int enabled = 1;
int enabled_prev = 1;
int engine_on = 1;
int engine_on_prev = 1;
int rcs_on = 0;
int rcs_on_prev = 0;
int rcs = 0;
int rcs_prev = 0;
int sas_on = 0;
int sas_on_prev = 0;
int sas = 0;
int sas_prev = 0;

Talkie voice;

void setup() {

  Serial.begin(9600);
  Keyboard.begin();
  pinMode(JOYSTICK_SW, INPUT_PULLUP);
  pinMode(BUTTONS, INPUT_PULLUP);
  pinMode(POWER, INPUT_PULLUP);
  pinMode(ENGINE, INPUT_PULLUP);
  pinMode(ROTARY_CLK, INPUT_PULLUP);
  pinMode(ROTARY_DTA, INPUT_PULLUP);
  pinMode(ROTARY_SW, INPUT_PULLUP);
  pinMode(STAGE, INPUT_PULLUP);
  pinMode(SAS, INPUT_PULLUP);
  pinMode(RCS, INPUT_PULLUP);
  pinMode(POWER_LED, OUTPUT);
  pinMode(ENGINE_LED, OUTPUT);
  pinMode(RCS_LED, OUTPUT);
  pinMode(SAS_LED, OUTPUT);
  digitalWrite(POWER_LED, LOW);
  digitalWrite(ENGINE_LED, LOW);
  digitalWrite(RCS_LED, LOW);
  digitalWrite(SAS_LED, LOW);
  enabled = digitalRead(POWER);
  engine_on = digitalRead(ENGINE);
  rcs = digitalRead(RCS);
  sas = digitalRead(SAS);
  enabled_prev = enabled;
  engine_on_prev = engine_on;
  rcs_prev = rcs;
  sas_prev = sas;

  voice.say(sp5_FLIGHT_1);
  voice.say(sp4_CONTROL);
  voice.say(sp5_INSTRUMENTS);
  voice.say(sp3_START);
  voice.say(sp2_UP);
  voice.say(sp4_AND);
  voice.say(sp4_READY);

  delay(500);

}

void press_key(uint8_t key, int ms) {
  Serial.println("Pressed key: " + String(key));
  if (enabled) {
    Keyboard.write(key);
  }
  delay(ms);
}

void update_led() {
  digitalWrite(POWER_LED, enabled);
  digitalWrite(ENGINE_LED, engine_on);
  digitalWrite(RCS_LED, rcs_on);
  digitalWrite(SAS_LED, sas_on);
}

void loop() {

  joystick_x = analogRead(JOYSTICK_X);
  joystick_y = analogRead(JOYSTICK_Y);
  joystick_sw = !digitalRead(JOYSTICK_SW);
  buttons = analogRead(BUTTONS) * 10;
  button_pressed = -1;
  for (int i = 0; i < 5; i++) {
    if (abs(buttons - buttons_v[i]) < 250) {
      button_pressed = i;
      break;
    }
  }
  rotary_clk = digitalRead(ROTARY_CLK);
  rotary_dta = digitalRead(ROTARY_DTA);
  rotary_sw = !digitalRead(ROTARY_SW);
  rotary_dir = 0;
  if (rotary_clk_prev == 0 && rotary_clk == 1) {
    if (rotary_dta == 0) {
      rotary_dir = -1;
    } else {
      rotary_dir = 1;
    }
  }
  rotary_clk_prev = rotary_clk;

  enabled = !digitalRead(POWER);
  engine_on = !digitalRead(ENGINE);
  stage = !digitalRead(STAGE);
  rcs = digitalRead(RCS);
  sas = digitalRead(SAS);
  rcs_on = (rcs != rcs_prev) ? 1 - rcs_on : rcs_on;
  sas_on = (sas != sas_prev) ? 1 - sas_on : sas_on;

  update_led();

  if (joystick_x < 256) {
    press_key(JOYSTICK_LT_KEY, 5);
  } else if (joystick_x > 767) {
    press_key(JOYSTICK_RT_KEY, 5);
  }
  if (joystick_y < 256) {
    press_key(JOYSTICK_UP_KEY, 5);
  } else if (joystick_y > 767) {
    press_key(JOYSTICK_DW_KEY, 5);
  }
  if (joystick_sw) {
    press_key(JOYSTICK_SW_KEY, 5);
    voice.say(sp2_CONNECT);
    voice.say(sp5_LOCALIZER);
  }

  switch (button_pressed) {
    case 0:
      press_key(BUTTON_1_KEY, 5);
      voice.say(sp5_INFLIGHT);
      voice.say(sp4_AREA);
      voice.say(sp2_DISPLAY);
      break;
    case 1:
      press_key(BUTTON_2_KEY, 5);
      break;
    case 2:
      press_key(BUTTON_3_KEY, 5);
      break;
    case 3:
      press_key(BUTTON_4_KEY, 5);
      break;
    case 4:
      press_key(BUTTON_5_KEY, 5);
      break;
  }

  if (enabled && !enabled_prev) {
    voice.say(sp4_POWER);
    voice.say(sp4_ON);
  } else if (!enabled && enabled_prev) {
    voice.say(sp4_POWER);
    voice.say(sp4_OFF);
  }
  if (engine_on && !engine_on_prev) {
    press_key(ENGINE_ON_KEY, 5);
    voice.say(sp5_ENGINE);
    voice.say(sp5_IGNITE);
  } else if (engine_on_prev && !engine_on) {
    press_key(ENGINE_OFF_KEY, 5);
    voice.say(sp5_ENGINE);
    voice.say(sp3_STOP);
  }
  if (rotary_dir == -1) {
    digitalWrite(ENGINE_LED, !engine_on);
    press_key(ROTARY_UP_KEY, 5);
    digitalWrite(ENGINE_LED, !engine_on);
  } else if (rotary_dir == 1) {
    digitalWrite(ENGINE_LED, !engine_on);
    press_key(ROTARY_DW_KEY, 5);
    digitalWrite(ENGINE_LED, !engine_on);
  }
  if (rotary_sw) {
    press_key(ROTARY_SW_KEY, 5);
    voice.say(sp5_LANDING_GEAR);
  }
  if (stage) {
    press_key(STAGE_KEY, 5);
    voice.say(sp5_LAUNCH);
    voice.say(sp4_SEQUENCE);
  }
  if (rcs_on != rcs_on_prev) {
    press_key(RCS_KEY, 5);
    voice.say(sp4_VECTORS);
    voice.say(sp4_CONTROL);
  }
  if (sas_on != sas_on_prev) {
    press_key(SAS_KEY, 5);
    voice.say(sp5_AUTOPILOT);
  }

  enabled_prev = enabled;
  engine_on_prev = engine_on;
  rcs_on_prev = rcs_on;
  sas_on_prev = sas_on;
  rcs_prev = rcs;
  sas_prev = sas;
}

Credits

Alan Wang
31 projects • 103 followers
Please do not ask me for free help for school or company projects. My time is not open sourced and you cannot buy it with free compliments.
Contact

Comments

Please log in or sign up to comment.