Arduinos In Space!

A library for interacting with Objects in Space via a serial connection.

Protocol support

Arduinos In Space supports all of the known request types and command types documented in the unofficial Objects in Space wiki as of 2018-06-18. Note that at this stage the game is still under rapid development. New requests and commands are being added, and the protocol is likely to get some refinement. Arduinos In Space may lag slightly, or even briefly stop working between releases.

Note also that the library itself is still under development. Breaking changes are planned. But trust me, they're good ones.


Docs are in the process of being migrated to the OiS wiki:

In the meantime, the old installation and usage documentation is still below.


While the library (and the game!) aren't really released yet, it can only be installed manually by following these steps:

  • Download the most recent release from the downloads section of the Bitbucket repository.
  • In the Arduino IDE, navigate to Sketch -> Include Library -> Add .ZIP Library...
  • Select the zip file previously downloaded.

Brief usage

Initialisation and handshaking

First, create an Arduinos In Space object to interface with the game.

ObjectsInSpace OIS(Serial, 5);

The first argument here is the serial interface to use to communicate with the game. This will almost always be Serial, but Arduinos In Space should also work with the Serial2 interface present on Arduino Mega and Leonardo boards, as well as SoftwareSerial interfaces in more esoteric setups.

The second argument is the number of request channels this device will create to request data from the game. This does not include command channels.

Then, inside your setup() function, initialise the serial interface as well as the Arduinos In Space interface.

Serial.begin(9600); // This is the only rate supported by the game.

The begin() method handles the initial handshaking stage, and moves to the synchronisation stage, described in more detail below.

Once synchronisation is complete, activate the interface to start sending commands and receiving data.


Attaching commands to input pins

Arduinos In Space can monitor input pins, sending appropriate commands when the pin changes state. To use these, call the appropriate functions during the synchronisation phase to register the commands and associate them with an input pin.

Arduinos in Space has two input pin modes:

  • OIS.registerTrigger(pin, ACTIVE_COMMAND, INACTIVE_COMMAND) In Trigger mode, AiS will send ACTIVE_COMMAND when the switch is activated, and INACTIVE_COMMAND when the switch is deactivated. INACTIVE_COMMAND is optional. It's good for toggle switches, "latching" push buttons, or when a momentary button is used for momentary actions (burning main engine as long as the button is held down, for example).
  • OIS.registerLatching(pin, FIRST_COMMAND, SECOND_COMMAND) In Latching mode, AiS will send FIRST_COMMAND when the switch is first activated. The next time the switch is activated, AiS will send SECOND_COMMAND, and continue alternating between the two. A good example of using latching mode is pushing a momentary button to activate RCS in one direction, and pushing it again to deactivate it.

The library is intended for use with normally-open (NO) switches. Normally-closed can be used, but the logic is inverted (just swap the active/inactive commands and you should be fine). Furthermore, AiS can specify the input mode of the pin as an optional last argument:

  • INPUT. The pin is placed in regular input mode, and requires a separate pull-down resistor (pull-down is assumed, invert the logic if you're using a pull-up). This is the default mode, and is compatible with all of the Arduino tutorial examples.
  • INPUT_PULLUP. The pin is placed in input mode and the internal pull-up resistor is activated. Good for just wiring switches between the input pin and ground.

Sending commands

Before we can send a command, we must first register it. This is best done in your setup() function during the synchronisation phase. To register a command, just pass its name (from the wiki page) like this


Once a command has been registered and synchronisation has been completed, a command can be sent at any time in a similar fashion. For instance, call this in your loop() function to stop your vessel


Receiving data

Data can be received from the game by writing a callback function to receive and process the data, and then during the synchronisation phase registering the request type and callback. A small callback function that will light an LED when the EMCON system is active might look like this

void emconCallback(int channel, bool data) {
  if (data == 0) {
    digitalWrite(EMCONPin, LOW);
  } else {
    digitalWrite(EMCONPin, HIGH);

Then, in your loop() method during synchronisation, this callback can be registered to receive EMCON status updates like this

OIS.registerBool(EMCON_MODE, emconCallback);

OiS sends three data types; bool, int, and float. Each type has a dedicated method to register a callback:

  • registerBool(int channel, boolCallback(int channel, bool data))
  • registerInt(int channel, intCallback(int channel, int data))
  • registerFloat(int channel, floatCallback(int channel, float data))

Each callback takes two arguments. The first is always the channel ID (useful if you want a single callback to handle multiple channels). The second is the data sent.

Note that this library translates data from the game to the appropriate type. This means that each channel type requires a different callback function that accepts different arguments. If you don't want this, then use one of the following methods to register your callback:

  • registerBoolRaw(int channel, rawCallback(int channel, int data))
  • registerIntRaw(int channel, rawCallback(int channel, int data))
  • registerFloatRaw(int channel, rawCallback(int channel, int data))

Note that all register* methods return an integer indicating the request channel ID.

Receiving data and driving pins directly

For bool data types, Arduinos in Space can optionally request them and drive an output pin directly, eliminating the need for callback functions for simple usage. Note that the pin mode does not need to be set separately, AiS will take care of this.

To do this, just pass a pin number instead of a callback function. For example, this can be used to activate an LED on pin 13 when EMCON is active:

OIS.registerBool(EMCON_MODE, 13);

The default behaviour is to set the output pin HIGH when the requested data is true, and LOW when the requested data is false. This can be inverted, by passing a third parameter:

OIS.registerBool(EMCON_MODE, 13, true);

Example sketches

Sketches in the examples/ directory illustrate basic usage for trivial controllers.