Simulation Instruments

Home›API›Hardware

Buttons, encoders, and a microcontroller

Arduino Nano or ESP32

A physical switch does not talk to an instrument by itself. You wire it to a small microcontroller, a chip with a USB port and a set of pins. An Arduino Nano is one. An ESP32 is another. The microcontroller watches the pins and tells Studio or Panel what changed. The instrument then does the rest.

This page is how you wire one button and one encoder, load a sketch onto the microcontroller, and call it from an instrument. The calls are in the hardware API.

What you can attach

The hardware path is for controls and small outputs, not for a second instrument screen. A display that draws a gauge is another panel, or another computer running Panel.

Each of those has a call. hw_dial_add is the encoder. hw_led_add is the LED. The full list is on the hardware API page.

Which simulator

The microcontroller does not talk to the simulator. It talks to Studio or Panel. The instrument then uses the normal data calls, the same ones it uses for a mouse click. So a button on a Nano works with X-Plane, with Microsoft Flight Simulator, or with Test Pilot and no simulator at all.

How it connects

A sketch is the program you load onto the microcontroller. Once it is loaded, the microcontroller sends short text lines, one per event, ending in a newline. Studio reads those lines.

USB cable, the normal path

Plug the microcontroller into the computer that is running Studio or Panel. Studio opens the serial port at 115200 baud, eight data bits, no parity, one stop bit.

A Raspberry Pi on the network

If Panel runs on the Pi and the microcontroller is plugged into the Pi, that is the USB path. The simulator can be on another machine.

If Panel is on another computer and the microcontroller is not plugged into it, USB cannot cross the network. Only an ESP32 can, over Wi-Fi. A Nano cannot.

Wi-Fi, the second path

An Arduino Nano has no Wi-Fi.

Wi-Fi is off unless you set SIS_HW_WIFI=1 before you start Studio.

SIS_HW_WIFI is an environment variable. Studio reads it when it starts.

How to set SIS_HW_WIFI

Set it in the same terminal, then start Studio from that terminal.

Mac:

SIS_HW_WIFI=1 "/Applications/Simulation Instrument Studio.app/Contents/MacOS/Simulation Instrument Studio"

Linux:

SIS_HW_WIFI=1 ./SimulationInstrumentStudio

Windows Command Prompt:

set SIS_HW_WIFI=1

then start the exe from that same window.

PowerShell:

$env:SIS_HW_WIFI = "1"

then Start-Process from that same window.

It lasts for that launch only. Start Studio the normal way and Wi-Fi is off again.

To make it permanent on a Mac or Linux, add this line to your shell profile, ~/.zshrc or ~/.bashrc, then open a new terminal:

export SIS_HW_WIFI=1

On Windows: System Properties, Environment Variables, New. Name SIS_HW_WIFI, value 1. It applies to new launches.

A one-launch set is safer while you are testing. A permanent set is for a panel that always uses Wi-Fi.

The sketch starts an access point named SIS-HW, a small Wi-Fi network the ESP32 creates, with no password. It is not your home network. Join SIS-HW, then Studio connects to 192.168.4.1 on port 4731. If USB and Wi-Fi are both present, USB wins. Joining an existing home network is not in this sketch.

SICES

A SICES is a dual encoder and a push button on one shaft, on a USB cable. Simulation Instruments Concentric Encoder Switch. Click a dial or a switch. A yellow ring marks it. Click it again and the ring goes away. On a dual dial, the push fires the button at the center. Click the center to mark that button. Click the ring to mark the dial. Set SIS_SICES=0 to stop scanning. The default is on.

Turn a DIY Knobster back

The wiring does not change. Flash the original firmware from the app that created the DIY Knobster. Open that app. Home tab, Flash. Choose Arduino Nano, then the COM port. Check Flash as Knobster. Flash. After that it answers that app again. Studio will not see it as a SICES. Flash the SICES sketch to come back.

How to flash a sketch

A sketch is the program. Flash means write it into the microcontroller so it runs on its own. Use the Arduino IDE.

  1. Install the IDE.
  2. Tools, Board. Pick Arduino Nano, or your ESP32 after you add the board package.
  3. Tools, Port. Pick the port that appeared when you plugged the cable in.
  4. File, New. Paste the sketch. Save.
  5. Click Upload, the arrow. The IDE compiles, then writes it to the chip.

The same IDE flashes an ESP32. Add the board package first. Tools, Board, Boards Manager, search ESP32, install. Then Tools, Board lists your ESP32, and Upload works the same way.

If the upload fails, the usual cause is the wrong port, or on Linux the dialout group.

Do not screw the Nano or the ESP32 into the panel yet. A sketch that compiles only means the program has no typing errors. It does not mean the chip is talking to Studio. Plug it in, start Studio, and wait until Studio shows the microcontroller as connected. Then mount it.

Build a SICES

A SICES is a dual encoder and a push button on one shaft, wired to a microcontroller that speaks USB serial at 115200. Studio looks for HELLO SICES.

A classic Arduino Nano works. That is the ATmega328P Nano, the one a DIY Knobster uses. An ESP32 works, on the same USB cable. An Uno or a Mega works if you use the pins below. A Nano Every is a different chip with a different pin map. This sketch does not fit it. An STM32 could, if it shows up as a serial port. There is no sketch for it.

Pins on a classic Nano:

PartNano pin
Outer encoder AD3
Outer encoder BD2
Inner encoder AD4
Inner encoder BD5
Push buttonD6
All commonsGND

On an ESP32 use GPIO 16 and 17 for the outer encoder, GPIO 18 and 19 for the inner, GPIO 21 for the push, commons to GND.

The sketch. Load it with the Arduino IDE. How to flash is in the section above.

// SICES. Classic Nano pins. Outer A D3 B D2. Inner A D4 B D5. Push D6.
const int pinOuterA = 3;
const int pinOuterB = 2;
const int pinInnerA = 4;
const int pinInnerB = 5;
const int pinPush = 6;
int lastOuterA = HIGH;
int lastInnerA = HIGH;
int lastPush = HIGH;

void setup() {
  pinMode(pinOuterA, INPUT_PULLUP);
  pinMode(pinOuterB, INPUT_PULLUP);
  pinMode(pinInnerA, INPUT_PULLUP);
  pinMode(pinInnerB, INPUT_PULLUP);
  pinMode(pinPush, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("HELLO SICES");
}

void loop() {
  int push = digitalRead(pinPush);
  if (push != lastPush) {
    lastPush = push;
    Serial.println(push == LOW ? "PUSH 1" : "PUSH 0");
  }
  int outerA = digitalRead(pinOuterA);
  if (lastOuterA == HIGH && outerA == LOW) {
    Serial.println(digitalRead(pinOuterB) == HIGH ? "OUTER 1" : "OUTER -1");
  }
  lastOuterA = outerA;
  int innerA = digitalRead(pinInnerA);
  if (lastInnerA == HIGH && innerA == LOW) {
    Serial.println(digitalRead(pinInnerB) == HIGH ? "INNER 1" : "INNER -1");
  }
  lastInnerA = innerA;
}

The same sketch on an ESP32. Plug it in with a USB cable. Studio opens that serial port.

// SICES on an ESP32. USB serial. Outer A 16 B 17. Inner A 18 B 19. Push 21.
const int pinOuterA = 16;
const int pinOuterB = 17;
const int pinInnerA = 18;
const int pinInnerB = 19;
const int pinPush = 21;
int lastOuterA = HIGH;
int lastInnerA = HIGH;
int lastPush = HIGH;

void setup() {
  pinMode(pinOuterA, INPUT_PULLUP);
  pinMode(pinOuterB, INPUT_PULLUP);
  pinMode(pinInnerA, INPUT_PULLUP);
  pinMode(pinInnerB, INPUT_PULLUP);
  pinMode(pinPush, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("HELLO SICES");
}

void loop() {
  int push = digitalRead(pinPush);
  if (push != lastPush) {
    lastPush = push;
    Serial.println(push == LOW ? "PUSH 1" : "PUSH 0");
  }
  int outerA = digitalRead(pinOuterA);
  if (lastOuterA == HIGH && outerA == LOW) {
    Serial.println(digitalRead(pinOuterB) == HIGH ? "OUTER 1" : "OUTER -1");
  }
  lastOuterA = outerA;
  int innerA = digitalRead(pinInnerA);
  if (lastInnerA == HIGH && innerA == LOW) {
    Serial.println(digitalRead(pinInnerB) == HIGH ? "INNER 1" : "INNER -1");
  }
  lastInnerA = innerA;
}

Turn a DIY Knobster into a SICES

A DIY Knobster is an Arduino Nano and a dual encoder on fixed pins. The wiring already matches. Flash the sketch in Build a SICES. A DIY Knobster uses the classic Nano, not a Nano Every.

Encoder pinNano pin
Outer AD3
Outer BD2
Inner AD4
Inner BD5
PushD6
CommonsGND

Studio looks for HELLO SICES at 115200. If a ring turns the wrong way, swap A and B on that encoder.