Introduction: Kerbal Controller - the Basics
The goal of this tutorial is not to show how to build a specific KSP controller, but to show many of the common design choices and their pros and cons. The idea is to guide you to make your own controller rather than showing you how to make one without explaining the 'why' behind it. For several subjects, this tutorial will only provide pointers to other resources dedicated to each topic (especially Sparkfun tutorials as I find them quite complete).
What is KSP?
Kerbal Space Program is a game where you build rockets and they fly them. If you don't know it, you may want to go look it up before continuing here.
What is a Kerbal Controller?
Here is a list of controllers for KSP if you want some examples:
- A thread on the KSP forum listing several controllers
- An instructable by hugopeeters
- An instructable by niko1499
- The Kerbal Controllers subreddit
The basic architecture consists of a computer running KSP as well as a controller that can send inputs to KSP (to launch the rocket, increase the throttle, retract the landing gear, etc.) and receive information from KSP to be displayed (speed, altitude, etc.). The controller is usually controlled by an Arduino that is connected to the computer on one side and to a bunch of electronics devices on the other side (switches, potentiometers, LEDs, etc.). The whole controller is enclosed in a case that holds everything together.
This guide is not about using a pre-built off the shelf controller for KSP, but about designing your own custom controller.
Why make a KSP controller?
There are several reasons to make a controller:
- Because it is cool
- Because you want to learn new skills, mostly related to electronics or laser cutting/3D printing
- Because there is nothing like launching a kerbal into space by pressing a big red button
- But mostly because it is freaking cool!
What are the contents of this guide ?
The first part of this guide is about high level choices to guide the initial design of your controller (some examples of what you can do with a controller, what library and what board to use). It ends with a guide for an optional step, where you can use some basic electronics supplies to build a first proof of concept of a controller.
The second part is about the content of the controller: what kind of switches to use for specific inputs, what it can display, and various tips and tricks for designing. The goal is to be able to draw a rough schematic of the controller you want by the end of this part.
The third part is how to actually built it, including the enclosure, the electronics, etc.
Who is writing this guide?
This is a joint work from rogor (one of the main developers behind Kerbal Simpit Revamped) and Codapop (the developer of one of the largest and most complete KSP controllers). The idea is to make a living guide to help others create a controller, so feel free to suggest any improvements to this guide!
Step 1: The KSP/Arduino Connection - Microcontroller Basics
The first decision you must make is what type of controller you want to build, since that will decide what libraries you will be able to use. There are two main categories of controllers.
These are controllers that can only send inputs to KSP, similar to a computer peripheral like a joystick, a mouse, or a keyboard.
For these controllers, the easiest solution is to act as a joystick or a keyboard for the computer. You can for instance have a 'Map' button that simply emulates a key press of the 'm' key. The big red button to launch the rocket emulates a 'space' press. Etc.
In this case, the best solution is probably to use a 32u4-based microcontroller (such as the Arduino Leonardo or Arduino Due) and use the official keyboard library and Joystick.h library. More information from the creator of the Joystick.h library here.
You will probably need to map the KSP commands to the keyboard/joystick in the KSP settings for it to work.
If you want to actually display some information on your controller that comes from KSP (for instance current speed and altitude, fuel levels, etc.), you'll need to use another library. The easiest way (if you don't want to implement your own protocol) is to use an existing mod to communicate between KSP and an Arduino.
This mod was an alternative to SerialIO created in 2017 by Stibbons. The idea was to have a richer set of possibilities compared to SerialIO.
The main difference with SerialIO is that there are a lot of messages available, each dedicated to a specific piece of data. The Arduino can subscribe to different 'channels' to get an update on all the desired information for itself and ignore other unnecessary information. It can also send inputs back to KSP using the relevant channels. This allows it to have a lot more functionality by only using what you need (at the price of a little bit more complexity).
In 2020, a fork called Simpit Revamped was created by LRTNZ which has been continuously maintained. (disclaimer: this guide is written by some active developers/users of this fork). New features were added and there is an active community to this day (mid 2021).
This KSP mod was created by Zitronen back in 2014 and it is the original plugin used to create controllers, so a lot of existing controllers use this library.
This is the easiest protocol to work with. There is a single message sent from KSP to Arduino with all the available information and a single answer with all the commands from Arduino to KSP. The only drawback is that the features are limited to what is currently in the message, and there is no development planned (but some support is still offered by the author).
kRPC is a protocol used to control KSP from another piece of software, whatever it may be. It allows you to write python code for instance to control your rocket. So it is possible to interface KSP via this protocol to a piece of python code that will talk with the Arduino. It also has a dedicated Arduino interface called "C-nano".
The kRPC function set is fairly complete but tests by several users showed that this option was in fact quite slow and that the big controllers seem to lag with it.
If you don't want to display any information on your controller (just a bunch of buttons and/or a joystick), you should use the keyboard library and joystick library.
If you want to display information on your controller, I would personally advise to use either Simpit (the Revamped version under active maintenance) or SerialIO (simpler, but with more limited functionality). The remainder of the guide assumes that Simpit Revamped is used when discussing the potential functions of the controller.
Step 2: Microcontroler Choice & the Pin Issue
Once the KSP-controller interface is chosen, the next step is to choose the 'brain' (also known as a micro-controller) of the controller.
Different board families
The most used board for this type of project is obviously the Arduino family. The most popular is the Arduino Uno (and you can even buy an official starter kit with a board and some components that will allow you to build your first prototype). Other Arduino boards commonly used for KSP controllers are the Arduino Mega (see below), Arduino Nano (smaller, so easier to fit in an enclosure) and Arduino Leonardo (to use the Keyboard and joystick native emulation).
You can also find a lot of Arduino-like or Arduino-compatible boards. They are usually cheaper (or more powerful), but the quality may vary. A good example of a more powerful board is the Teensy family. You should check the library compatibility before using another family.
Except for specific use cases, a KSP controller will not need a lot of computing power or memory. Its main objective is to read inputs, send them to KSP, and update the displays based on information from KSP. The real bottleneck is the I/O capabilities (see below), so any model should be able to handle a controller. If in doubt, find a project of similar complexity of your own and use their Arduino model as a guideline.
The Pin issue
A standard Arduino Uno/Nano has about 14 pins to control digital input/output plus 6 for reading analog values. Each switch, button and led (if controlled independently from a switch) needs a pin in a basic wiring. Each joystick axis needs one analog pin. Since the USB connection is in use, pin 0 and 1 should not be used so this leaves a maximum of 18 pins (including 6 analog).
So for a basic controller with
- 7 switches for the action groups (SAS, RCS, Lights, Gear, Brakes, Launch, Abort)
- Two 3-axis joysticks to control both rotation and translation (6 analog pins)
- One throttle (using 1 analog pin)
- 10 switches for the custom action groups
You are already out of pins and cannot do all of this. And we are not even able to display things. So we need to come up with a solution that does not involve reducing the functionalities of our controller.
Thankfully, Arduino has foreseen this issue and has created monsters that have way more pins available. This is the job of the Arduino MEGA (or the Arduino Due) with its 54 digital pins and 16 analog inputs.
With this solution, there is no added complexity except that your wiring will be a big mess.
One classic solution is to use shift registers. You can find an introduction to shift registers at Sparkfun for instance. The idea is to use two or three pins to control any number of inputs or any numbers of outputs (depending on the shift register used) since you can chain several of them together.
Serial communication (I2C, SPI)
There are established protocols for serial communication using only 2 or 3 wires to send complex commands to other electronic components.
I2C (another Sparkun tutorial on this topic) is a protocol used to create a communication bus using only 2 wires. You can hook up any number of I2C devices to the same 2 pins (if you take care not to conflict the I2C addresses) and communicate with all of them using only those 2 pins on your Arduino. If you have some conflicting I2C addresses, you can use the TCA9548A chip to translate addresses.
You can also use I2C to communicate with I/O expanders (like the MCP23017, controlling 16 input and/or output pins) with a single chip. You can use I2C to communicate with an ADC converter (like the ADS1015 to read 4 analog signals and transmit the result via I2C). This is a little bit more complex to use than shift registers, but also more versatile. You can also easily daisy chain the chips to simplify the wiring.
Another protocol used for the same purpose is SPI (another Sparkun tutorial on this topic). The details differ but the idea is the same: control a lot of pins (for instance multiple LEDs) using a limited number of pins on your Arduino. This is more frequently used when driving large numbers of LEDs or entire displays by using MAX7219 for instance.
Step 3: The First Commands (Stage, Altitude, Throttle)
Before going too much into controller design, here are some examples of simple unit tests to show what is possible with a controller. The idea is to use basic components (resistors, switches, LEDs, potentiometers) to show how to control or display information from SimPit using an Arduino. All these components are available in an Arduino Starter Kit.
It is recommended that you first learn a bit about your Arduino and do a few of the basic tutorials found on the Arduino website, suck as Blink. It is also necessary to install Simpit and its associated library by following the install instructions.
Hello World example
Goal: Confirm connection with KSP.
Step 1: Connect the arduino via USB.
Step 2: Open the Arduino IDE and select your serial port by going into Tools>Port and choosing from the list. You may have several ports displayed, so to know which is the right one, disconnect your arduino and see which one disappears from the list. It may also say "Arduino Uno" next to it if you are using an Uno. Then upload the code to the Arduino. Remember this port name for later. Make sure the Serial Monitor is closed (or else KSP will not be able to open the connection to Arduino since only one program can use a USB connection at any time).
Step 3: Ensure that the LED on your arduino is ON. It should turn on as a result of the uploaded code and should turn on when the arduino is plugged in.
Step 4: Go into your KSP GameData folder and open up the Simpit folder. Inside there should be a file called Settings.cfg. Open it in a regular text editor and add your arduino port name where it says "PortName = ". (Ex: PortName = COM4). Save the file.
Step 5: Open KSP and go to any flight (for instance open any training or scenario or saved game). Ensure that you see the Simpit icon in the toolbar (a red background mean no connection to Arduino, a green background mean that the connection was established) and ensure that the LED on your Arduino has turned OFF. This means the mod was installed correctly and the arduino is communicating with KSP.
Debugging: Is your arduino still connected to the same port name? Does your Arduino have a built-in LED? (If not, you will need to wire up an LED and change the code to reflect that I/O pin rather than LED_BUILTIN). Is the port name correct in Settings.cfg? Are you using the right version of Simpit?
This example uses the Altitude Example code found in the Simpit Arduino Library.
This code works much like the Hello World example above and uses the same LED (LED_BUILTIN).
Goal: Turn on an LED when the vessel has reached an altitude of 500m.
Step 1: Upload the Altitude Example code to your arduino.
Step 2: Ensure that you are using the correct serial port and have it listed in Settings.cfg.
Step 3: Run the game. Ensure the LED turns OFF when the game is in the opening menu.
Step 4: Build a rocket capable of flight above 500m. Put it on the launch pad (or open any training scenario starting with a rocket on the ground).
Step 5: Ensure that the LED has turned back ON. Launch the rocket and observe the LED. It should turn OFF after the rocket has reached 500m.
Debugging: Is the arduino using the correct serial port, and is that port name in Settings.cfg? Are you using an LED/circuit that already works with the Hello World example?
This code works by activating the Message Handler in the code that reads "mySimpit.inboundHandler(messageHandler);". This line of code is needed only once in your script. After that, you can register whatever message channels you want. This example registers an altitude message channel in the code that reads "mySimpit.registerChannel(ALTITUDE_MESSAGE);".
The remaining code of interest is located in the messageHandler function near the bottom of the script. It has a line that reads "case ALTITUDE_MESSAGE:" with a lot of code below it. For every additional channel, you will need to copy this code (from 'case' down to 'break;' as a template and paste it below the "break;" line).
To alter what happens when an altitude message is received, you can edit the code within the messageHandler function. In this case, it turns the LED on or off depending on if it is above or below 500m.
Goal: Stage a rocket using a physical button.
Special Note: For simplicity's sake, this tutorial uses "INPUT_PULLUP" on the input pin (pin 2). For reasons explained later, this is necessary for cleanly detecting the input. It has the added side effect of making it so the button detects ground (GND) as the input rather than positive voltage. In general, this is not a suitable solution for boards using shift registers or other common input methods.
Step 1: Follow the DigitalInputPullup Example from the Arduino website using your adruino and relevant components on a breadboard. You can use the example code there to test the circuit.
Step 2: Upload the Stage Example code to the arduino. As the Arduino button example and the Simpit Stage Example both use I/O pin 2 for the button pin, the code should work as is.
Step 3: Ensure the arduino port name matches the port name in Settings.cfg as seen in the Hello World example.
Step 4: Run the game and open a saved game.
Step 5: Build a rocket with a booster, and put it on the launch pad. Press the button wired to the arduino. It should activate the booster.
Debugging: Are you using the correct pins on the button? (Some of them have multiple pins.) Are you using the right serial port? Is the button connected to pin 2 and GND?
The code works by triggering "mySimpit.activateAction(STAGE_ACTION);" when the arduino senses input from the button. To get other actions working, simply replace that line with the proper code for that action. (Ex: mySimpit.activateAction(SAS_ACTION); and to deactivate, use mySimpit.deactivateAction(SAS_ACTION);)
Also, take note of the debouncing code, which is comparatively complex. This prevents multiple inputs from the same button from happening in quick succession (such as preventing 5 stage commands after pressing the button once). Hardware is never perfect, so this kind of code is important to use. Depending on how your board is designed, you may need this code specific for each input, but there are ways around that.
This example uses the Throttle example found in the Simpit Arduino Library.
Goal: Change the throttle of a rocket using a potentiometer (dial).
Step 1: Follow the Analog Input Example from the Arduino website using your Arduino and relevant components on a breadboard. You can use the example code there to test the circuit.
Step 2: Upload the Throttle Example code to the Arduino. As the Arduino analog input example and the Simpit Throttle Example both use analog pin A0 for the potentiometer pin, the code should work as is. This example code also uses other pins for rotation axes, but they can just be ignored.
Step 3: Ensure the Arduino port name matches the port name in Settings.cfg as seen in the Hello World example.
Step 4: Run the game and open a saved game.
Step 5: Build a rocket and put it on the launch pad. Turn the potentiometer wired to the arduino. It should change the throttle.
Debugging: Are you using the correct pins on the potentiometer? Are you using the right serial port?
This code works by reading the analog pin and then mapping the value to an integer between 0 and 32,767 (also seen as "INT16_MAX"). This then gets sent to KSP using "mySimpit.send(THROTTLE_MESSAGE, throttle_msg);" You can send other analog messages this way, though they typically range from -32,768 (INT16_MIN) to 32,767 rather than 0 (with 0 actually being the center position on a joystick). The rotation code in this same example should provide a decent format.
Using these examples, you should have most of the tools necessary for expanding your board to include all sorts of functions!
Step 4: Action Groups
Action groups are one of the main inputs of a controller. They include the Staging command and the SAS & RCS status as well as custom action groups.
For staging, a typical momentary switch (preferably big and red) is enough to launch the rocket when pressed. But for action groups that are toggled (especially SAS, RCS, Lights, Gear and Brakes), an issue arises when using a controller and switching vessels. This vessel switch can happen when docking (when it is common to switch between the two vessels to control docking), when quick loading or even just when launching a new rocket.
The easiest way is to have an on/off switch (a stable, 2-position switch) to represent each of those actions. But when loading a new vessel, this new vessel can have a different value than the one in the controller. There is either a discrepancy (for instance a rocket with SAS activated when the controller shows it deactivated) or a forced change at each loading to ensure that the rocket has the same state as the controller.
Both solutions are unsatisfactory as is. With a potential discrepancy between the controller and KSP, it might lead to piloting errors. With a forced change, it can lead to a disastrous situation. For instance after launching and recovering a rocket (with no gears, so gears retracted), if a plane is loaded it will retract its legs as soon as it's loaded.
To compensate for the potential discrepancy, one might want to add an LED to indicate the action group state. This way, the discrepancy is visible on the controller (if the switch is on and the led off for instance).
Another way to deal with this is to use push buttons with a status LED. The press of the button is only used to toggle the status on or off, thus eliminating the possibility of having a discrepancy. There is even the possibility of having a push button with a integrated led. One should be aware that the LED status must be able to be controlled independently of the button position.
Step 5: Analog/Joysticks
For analog controls, up to 11 axes can be controlled at any time by the user:
- 3 axes for the vessel rotation
- 3 axes for the vessel translation (when using RCS while docking for instance)
- 1 axis for the throttle (can be a linear potentiometer)
- 3 axes for the camera rotation
- 1 axis for the camera zoom
A typical joystick is 2 axes (Left/Right and Up/Down) but some joysticks have 3 axes. Depending on the size of the intended controller, a single joystick can be used for all of the rotation/translation controls (with some kind of selector to be able to change what is controlled by the joystick) or each axis group can have a dedicated joystick.
Some people have also used motorized sliders to be able to automatically put the throttle to full or cut it by the press of a button.
In order to ensure the joysticks are not giving inputs at all times, a deadzone must be added to the joystick's resting position, which can be done in code.
Step 6: Information Displays
Several kinds of displays are found in a lot of projects, each with their own unique characteristics:
- Digit displays: 7-segment displays (up to 4 digits each, with or without decimal points) or even 14/16-segment displays to allow additional characters. The 7-segment displays are the most commonly used.
- Resource displays with LED bar graphs
- LEDs for status indicators
- LCD screen (more customable, easier to display characters).
- TFT screen (to draw arbitrary shapes. See this guide for instance for what is possible with such screen). This can even be used to draw a navball (this is more advanced, see this example by my5tr0)
It is important to consider the units being displayed, especially for altitude—we want to be able to display altitude from 10s of meters for landing up to 100,000,000s of km for outer planet orbits. For instance, if exiting the Eeloo SOI while Eeloo is at its apoapsis, the altitude of the vessel in Kerbol's SOI will be roughly the same as the Eeloo apoasis: 113,549,713,200m. To display this value, we would need at least 12 digits on our display.
Another solution would be to change the unit based on the number displayed. One could limit, for instance, to 6 digits and add an LED display to show if the display is using meters, kilometers, or megameters (1,000,000m). This change of unit can be linked to the mode (for instance meters for landing/takeoff, km in orbit mode, etc.).
There is also an issue of the number of parameters to display: if you want to display everything then it will be a very big controller! Just look at all the values that Kerbal Engineer Redux can display to get a good idea as to what might be possible (hint: more than 100 values!). The KSP interface mods (such as Simpit) might not display all of these datapoints. If you find one that you'd like to use but is missing from the library, you can do a feature request to the library developers or find a workaround. You should also consider combining displays in order to save on real estate.
Here is a list of the most common display choices:
- Altitude display (with the issue mentioned previously regarding the range of values). This can also be surface altitude or sea level.
- Speed (orbital, ground or horizontal depending on the situation)
- Resources (solid fuel, liquid fuel, oxidizer, monopropellant, Xenon), either in the whole craft or in the current stage
4 digit 7 segment
While it is possible to use shift registers to power these, you are much better off using a multiplexer chip like MAX7219. This tutorial provides a good base to start with. You can also find one of these handy modules that use the same chip. If you want to use MAX7219 without those modules, it is absolutely critical that you use common cathode (common ground) displays. Common anode will not work.
LED bar graphs
The typical LED bar graphs use the form factor in this tutorial. They are essentially 10 separate LEDs stuck together. Thus, they are simple to work with. You can drive them using shift registers like the 74HC595 as seen in that tutorial. It is also possible to get fancier with them and power them with a multiplexing chip such as the MAX7219, though the available libraries are not suited for this, and it requires tying the grounds together in groups of 8 in order to mimic the common cathode displays. If you need a more in-depth tutorial on this, feel free to contact CodapopKSP on reddit.
You can also find modules that are sold ready to be used, controlled by I2C, like this one from Adafruit.
These are more self explanatory and depend on your board setup. A common way to drive these is with shift registers like 74HC595. You can also use I/O pins.
LCD screen and TFT screen
To be completed at a later date.
Step 7: Miscelaneous Tips
The Need for Different Modes
With the amount of information/inputs needed, a common solution is to use different modes.
As hinted at in previous steps, with 2 number displays, you might want to display ground speed/ground altitude in plane mode, orbital speed/orbital altitude in orbit mode and heading/speed in rover mode.
Another useful mode is one where you can test all your components without having to connect to KSP—for instance, you can use the displays to show the current state of the inputs. It helps when diagnosing an issue with the controller without having to launch KSP and reproduce a given issue.
Using the API of the library to get ideas
If you decided to use an existing library (Simpit or Kerbal SerialIO for instance), you should look into all the available messages to have an idea of what you can control or display. This can give you idea of things to add to your controller. Here are some examples of controls and information that you can display that have not been mentioned previously:
- Timewarp control (to speed up time, warp to next maneuver, etc.)
- Quicksave/Quickload, opening the map
- Life support resources from mods (Water, Oxygen, etc.)
- Maneuver data, DeltaV available, current SOI
Future-proofing the controller
It is always a good idea to add additional inputs and lights (an LCD screen, some buttons, some LEDS, etc.) even if you don't know yet what to do with them. At some point, you might have new ideas and won't want to redo the whole controller.
Conclusion of Part 2
You should now have everything you need to design your own controller from a functional point of view. This means deciding what kind of inputs/displays you want, what kind of switches to use to do a certain function, etc.
The next step will focus on how to build this controller once you have a list of all the inputs/displays you want, with a rough idea of the spatial organization.
Step 8: Dealing With Power - PSUs and Multiple Voltages
Power management is a necessary part of the controller design. As the Arduino must be connected to a computer to interact with KSP, the computer will supply some power to the controller. A USB port on a computer usually provides a maximum of 500 mA. The Arduino will use some of it, but in general, an Arduino Uno can only provide 200mA of power total (and 20mA from any single pin). Other boards may supply more or less, and it's a good idea to look up your board's limits. LEDs typically use about 5-10mA, perhaps more, so the maximum without a PSU is about 15 LEDs, considering safety margins.
If the current is higher than the capability of the Arduino, random errors might happen that can be hard to debug. So this step is mandatory to perform early (after unit testing but before moving on) to ensure it won't cause random errors during the development of the controller.
How to get additional power
If 200mA is not enough for your controller, several solutions are available to get additional power (more details later on how to evaluate the power needed).
- Use batteries (with the drawback of having to replace or recharge them regularly)
- Get additional power from another USB connector from the computer (usually limited to 500mA)
- Get additional power from a Power Supply Unit. This is usually like a wall adapter used to charge smartphones: you plug one side into an electrical socket and the other side into your circuit.
Difficulties may arise since there will be two difference sources of power—the USB cable from the Arduino to the computer and the additional power supply. You must avoid connecting them to avoid a short circuit. One solution is to power everything with the external PSU except for the Arduino, with the only exception being the analog pins reading inputs from joysticks. In order to get the correct analog reading, the arduino must read the same voltage through the analog pins as it is supplied with. If you wish to use a different voltage or power your analogs with the PSU, then you should connect the PSU into the AREF pin (analog reference pin) to ensure an accurate reading.
All grounds must be tied together for the circuit to work, so connect the arduino ground to the PSU ground.
Important note: PSUs have a tendency to leak voltage into your arduino. Typically this will be expressed as the arduino being powered ON despite not being connected via the USB port. This is bad for the arduino and should be avoided. There are various solutions with their own pros and cons (such as using diodes or relays), but so far we have not managed to find a simple suitable solution. The most direct way to ensure no damage is done to your board is to always plug in the arduino first before turning on the PSU and turn off the PSU first before unplugging the arduino.
How do you pick an external PSU size?
There are many different kinds of PSUs, with any range of voltages, amperages, and other features. In general, you will want to pick a PSU that matches the voltage requirements of your circuit. For most boards, this is probably 5v, as that is what is supplied by most Arduino boards and what most of the common IC chips run off. The next step is figuring out your maximum possible current (amperage).
For the most part, you can use any PSU as long as the current rating is higher than the maximum your board will require. You could in theory use a 500A 5V PSU to power a tiny board, but there would be extreme inefficiencies (and probably safety issues!) Ideally, you would use a PSU that supplies slightly higher than your maximum possible current. So how do you figure out your maximum current? You sum up all the amperages of all your components (assuming the same voltage is used everywhere, else you have to sum Watts instead of Amperes).
You should know Ohm's Law by now, but in case you don't, here it is: I = V/R. I is current, V is voltage, R is resistance. You are trying to find the current, so we don't even need to reorganize this equation. For each component, you can either find the max current in the datasheet (for instance if you are using an LCD screen) or use Ohm's Law to approximate the value needed for basic components.
Power usage for an LED
Pick one LED on your board and make note of what value resistor you used for it. Use that value and plug it into the equation with your voltage. If you are using a 200Ohm resistor and 5v, then your current is
I = 5/200 = 0.025 or 25mA
This particular LED will use, at maximum, 25mA of power. It will actually use a lot less than that, as LEDs themselves have a voltage drop (something like the equivalent of 2V depending on the LED), but 25mA is the value that you can be sure it will never exceed, and that's the value that I prefer to use.
Power usage of a switch or potentiometer
When using a switch, the current value is limited by the pullup (or pulldown) resistor used. The typical value for the Arduino built-in pullup is 20k Ohms (or even 50k Ohms on the Due). Even with a 10k Ohm resistor, the current is 5/10,000 = 0.5mA. This is insignificant with respect to the consumption of a single LED.
With a potentiometer, you can use the value of the potentiometer in your calculation.
To avoid extra computation, assuming a total of 100mA for all ICs, switches, and potentiometers is probably a conservative hypothesis.
I have a board that uses 5V for everything, 10 LEDs with 300Ohm resistors, 20 LEDs with 1000Ohm resistors, an LCD whose datasheet indicates the need for 50mA, and a number of buttons and switches.
5v/300Ohms = 17mA for a single LED, so 170mA for 10 LEDs.
5v/1000Ohms = 5mA for a single LED, so 100mA for 20 LEDS.
Other components = 50 mA (for the LCD screen) + 100mA (as a safety net for all other components)
170mA + 100mA + 150mA = 420mA
I will need to use a 5v PSU that can supply at least 420mA. It is common to find 500mA PSUs, so that is what I would likely end up using.
Connecting an external PSU to a circuit
The PSU usually connects to the circuit using a standardized plug such as a barrel plug or a USB plug. Typically you will have only your power and ground wires. As noted above, all grounds must be tied together for the circuit to work, so connect the arduino ground to the PSU ground.
You can find some ideas and more information in this Sparkfun tutorial.
Dealing with multiple voltages
You may find yourself wanting to use multiple voltages in order to power beefier components. This essentially creates multiple separate circuits in your board, though they will still need to be connected directly via ground. Connecting the VCC of different voltages together is typically a bad idea, so the components will need to be separated somehow. You can achieve this in various ways, but the most common are to use MOSFETS or relays (seen here using magnets, but there are common powered versions) as electrical switches to allow the 5v data lines of the arduino to power the higher voltage components.
There are two ways to work with multiple voltages.
Using separate PSUs
The first way is to simply use multiple PSUs---one for every voltage. In order to pick the right PSU, just follow the steps above.
Using voltage converters
You may bump up your voltage for a section of your circuit by using a buck converter. This greatly complicates your power calculations, as you need to calculate using watts rather than amperes, which can be made easy using this handy calculator. Keep in mind that there are power conversion efficiency losses, so it's best to read up on your converter to make an accurate prediction of what your power drain might be. When in doubt, increase the safety margins!
Step 9: Designing a Housing for Your Controller
Once we move away from the proof of concept stage, we need a way to house all of the components together. The housing will have two main objectives:
- The top will usually house all the inputs/display and will be the face that will make your controller look good. It need some kind of labeling in addition to holding the components.
- The whole housing will hold and protect the internal components (Arduino, PCB, cables, etc.)
The Manual Way
The easiest solution for prototyping is probably to use a shoe box and cut holes for all the components. You can also write (or tape a printed sheet of paper) on it to label everything. However, it will feel quite cheap, and if the box is not firm enough, it will be more difficult to interact with the components (try pressing a big red button when the box bends easier than the button is pressed...). This is still a good prototyping tool to test the layout of your controller and the correct size of the holes, especially if you print your current design on a piece of paper, tape it to the box and cut all the holes yourself.
Another DIY-at-home solution is to cut a sheet of plywood to make the housing. It will be firmer (and potentially bigger) than a shoe box, but you will need additional power tools.
The Automated Way
The other solutions mostly rely on the use of automated machinery to create the housing (or part of it) from a computer plan (this is called a CNC machine). You can usually order the finished housing online and have it delivered to you if you don't have such a machine. The most common options are:
- Laser cutting
- 3D printing
- Aluminum PCB
- Other CNC tools
Laser cutting involves a potentially large sheet of material (acrylic, particle board, aluminum, etc.) that is cut and engraved by a laser. This is especially useful for us since it allows us to cut big flat pieces (like the top of the controller) with holes of precise sizes to hold the components, as well as the engraving to label everything. It is also possible to cut all the controller sides and assemble them with glue. The downside is that you cannot make any kind of shape. You can only engrave or cut the material.
Ordering a laser cut part usually involves creating a vector file (usually a .svg or .ai file) with all the holes/engraving in it. The most commonly used free software to create vector files is Inkscape (but if you have Adobe, then you can use Illustrator) and the service you use to do the laser cutting will usually have additional constraints to be met (like a minimal spacing between cuts, etc.). The price depends on the material, the size of the piece and the amount of cutting/engraving you want to do. You should be sure to draw the cutting lines and engraving lines in different colors or layers.
Note: If you need to convert .svg files to .ai, first export the image as a PDF and then simply rename the file to end with '.ai' rather than '.pdf'.
The images used in this step are the actual files used for laser cutting the top of a controller (done with Adobe Illustrator) and the finished product, by madram7.
3D printing usually refers to a process of creating an object by adding layers of material to produce an arbitrary shape. This allows us to either create the whole controller housing (uncommon, as this method is usually not well suited for big pieces) or part of it. It could be used to do part of the top of the controller or some smaller part of it (switch guards for instance).
Ordering a 3D printed part usually involves create an object file (usually a .stl file). The price depends on the material, the size of the piece, and the amount of cutting/engraving you want to do. There are a lot of tutorials out there about 3D printing.
One specific PCB printing technology uses aluminum as a base material which produces quite robust PCBs usually used when significant cooling is needed (which is not the case with most KSP controllers). In our case, it could be used as the top of the controller. This method is potentially far cheaper for smaller controllers, and the labeling (painted onto the soldermask layer) is typically free.
Aluminum PCBs are created the same way as normal PCBs (as discussed in the next step), but typically they are designed using software such as EasyEDA and ordered from a company like JLCPCB. Keep in mind that aluminum is conductive, so you should design your controller in such a way that doesn't actually utilize this PCB for an electrical circuit (perhaps by including another PCB for your circuit as a sublayer).
Other CNC tools
Other CNC tools exist to build custom pieces without using laser cutting or 3D printing. This tutorial will not discuss them much, as the authors have no specific knowledge about them. Don't hesitate to send us first hand knowledge that you may have to incorporate into this tutorial!
Step 10: How to Make an Electronic Circuit
One of the main components of the controller will be the electronics. It will be needed to connect the power, the components (switches, LEDs, joysticks, etc.) and the needed integrated circuits (ICs for short).
Electronic Design Methods
The first method is to use a breadboard or several breadboards (as with the proof of concept done earlier) to wire everything. The advantage is that it is easy to work with (i.e. no soldering) but it can be a mess for a medium-sized project. It is also prone to having wires disconnecting when working on it or moving it, and it is tedious to check all the connections. (see the image above, taken on Wikipedia by Fulladder)
The second method is to use a prototyping board or perfboard. The idea is to do the same kind of wiring as with a breadboard, but with the added need of soldering. This is a long process, but is it more reliable than a breadboard and a mistake can be quite easily fixed by de-soldering and resoldering (see the 2 images above, from the top and the bottom of a prototyping board).
The third method is to design a PCB (a Printed Circuit Board). This is the green card you usually associate with electronic devices. There are a lot of online services that can print them for you if you provide them with the design you want, and a lot of software to design them. Depending of the service, you might have to solder the components on it yourself (the resistors, ICs, etc.) or have it done before receiving it. The advantage is that the PCBs can be easily reproduced (if you need the same circuit several times) and are more durable and reliable. The drawback is that it is usually a little bit more expensive that the other alternatives, especially if you make some mistakes in the design since they cannot be easily fixed. Typically you must order PCBs in multiples of 5, and the file you need to send is called a gerber.
Planning Before Doing
Unless you want to do it the Kerbal way (i.e. a lot of iteration with a lot of failure, and no limit on the money spent), you will need to create schematics of what you want to do. Several methods are available. You can draw everything yourself on a piece of paper or you can use software to do it (which is necessary if you go for a PCB).
You can find a more extended tutorial from Sparkfun about schematics here.
For the software:
- Fritzing is an open source sofware to draw schematics that also allows you to draw a consistent physical view (how to organize the breadboard for instance).
- EasyEDA is an online tool to design and directly order a PCB and its parts from their partners (JLCPCB for the printing, which you can order directly)
- The most known software to design PCBs is probably Eagle (commercial with a free limited version) and KiCAD (free).
Step 11: Now, Make Your Own Controller
You should now have everything you need to start building your own.
It is always a good motivator to do it in an active community, so don't hesitate to share your progress and ask for advice in those communities:
As it is intended to be a living instructable, feel free to contact the authors with some additional information that you'd like to see added.
Grand Prize in the