Joystick

Two axes in one gesture. Drag the handle and the device receives where it is — left/right and up/down together — which is what a rover, a drone or a pan-tilt camera needs to move smoothly.
What it does
The handle position is written as one text value, x,y, each axis from -1.00 to 1.00. Both axes always travel together, in one message: the device never sees an X without its Y, so a direction is never wrong for the length of a round trip. On release the joystick either springs back to center (sends 0,0) or stays put.
When to use it
- Driving — a differential rover:
xsteers,ysets the speed. - Aiming — a pan-tilt camera, a laser, a servo pair.
- Anything with two degrees of freedom at once.
Set it up
- Declare a Text signal — A joystick sends both axes in one text value, so it needs a Text signal. Tap the device icon, then Declare a signal, and choose the type Text.
- Place it — Back on the dashboard, tap + and choose Joystick under Controllers. Six columns square is a comfortable size.
- Wire it to the signal — Tap the joystick, open the Data tab, tap + Add a target and pick the Text signal.
- Choose what happens on release — In the same tab, under On release, keep Back to center for anything that moves — the handle springs back and the device receives
0,0. Close the settings, tap ▶, and drag.
Settings
Tap the widget in edit mode: the sheet opens with a live preview at the top, then two tabs — Data for what it reads or writes, Appearance for how it looks.
Data — what it writes
Targets
| Setting | Type | Default | What it controls |
|---|---|---|---|
| Targets | list of signals | empty — No target yet. The tap goes nowhere. | The signal the widget writes to. Accepts a Text signal only — both axes travel in one value. The picker lists nothing else. + Add a target for a second device: every target gets the value. |
What each gesture sends
| Setting | Type | Default | What it controls |
|---|---|---|---|
| Format | read-only | x,y from -1.00 to 1.00 |
Shown for reference. IJoystick splits it into x and y for you. |
On release
| Setting | Type | Default | What it controls |
|---|---|---|---|
| On release | Back to center / Stays put | Back to center | Back to center: the handle springs back and sends 0,0 — a rover stops when you let go. Stays put: the handle stays where you left it — a camera holds its aim. |

Appearance — how it looks
Title
| Setting | Type | Default | What it controls |
|---|---|---|---|
| Title text | text | empty | A title above the widget. Empty means no title. |
| Alignment | Left / Center / Right | Center | Where the title sits. |
Colors
| Setting | Type | Default | What it controls |
|---|---|---|---|
| Base | colour | theme | The disc. |
| Handle | colour | theme | The knob. |
| Handle when held | colour | theme accent | The knob while you drag. |

States
- Dragging — a stream of
x,y, paced. Released —0,0, or the last position, depending on On release. - Device offline — a joystick is a gesture, nothing is replayed.
Arduino device code
The address is all the device knows — I2 here; use the one the app gave your signal. In the sketch, the block receives both axes, already split:
IJoystick(I2, float x, float y) { … };
Complete sketch — Cloud
Paste it into the Arduino IDE, put your Wi-Fi and the token the app gave you, upload.
#include <InstantIoT.h>
const char* WIFI_SSID = "MyWiFi";
const char* WIFI_PASS = "MyPassword";
const char* DEVICE_TOKEN = "PASTE_TOKEN_HERE";
IJoystick(I2, float x, float y) { // x: -1 left … 1 right · y: -1 back … 1 forward
drive(x, y);
};
void setup() {
Serial.begin(115200);
InstantIoT.begin(WiFiLink(WIFI_SSID, WIFI_PASS), Cloud(DEVICE_TOKEN));
}
void loop() {
InstantIoT.loop();
}
Other connections
The widget block never changes. Only the begin() line says how the device reaches the app:
| Connection | begin() |
Devices |
|---|---|---|
| Cloud over Wi-Fi (above) | InstantIoT.begin(WiFiLink("MyWiFi", "secret"), Cloud(DEVICE_TOKEN)); |
ESP32 family, ESP8266, UNO R4 WiFi, MKR WiFi 1010, Nano 33 IoT, UNO WiFi Rev2 |
| Cloud over Ethernet | InstantIoT.begin(EthernetLink(), Cloud(DEVICE_TOKEN)); |
any board + an Ethernet shield |
| Direct — the device’s own Wi-Fi | InstantIoT.begin(AccessPoint("MyESP32", "12345678")); |
every board with Wi-Fi |
| Direct — Bluetooth LE | InstantIoT.begin(BLELink("MyESP32")); — #include <NimBLEDevice.h> first |
ESP32 family (not the S2) |
| Direct — Bluetooth Classic | InstantIoT.begin(BluetoothLink("MyESP32")); |
the original ESP32, Android only |
| Direct — a Bluetooth module (HC-05, HM-10) | InstantIoT.begin(SerialLink(Serial1)); — or SerialLink(13, 15) on ESP8266, SerialLink(10, 11) on UNO / Nano |
every board, radio or not |
| Your own InstantIoT Server (open source, at home) | InstantIoT.begin(WiFiLink("MyWiFi", "secret"), MyServer("192.168.1.42", DEVICE_TOKEN)); |
same as Cloud |
Direct needs no token: the phone is at the other end of the wire. See Connect for TLS, timeouts and what to do when it does not connect.
ISignaldoes the same job — and survives a restart.ISignal(I2, const char* v)runs with exactly the same value asIJoystick(I2, float x, float y): the widget block is the readable form,ISignalthe generic one, and you can use either. The difference shows when the device reconnects: with Restore after a restart on the signal, the Cloud sends the last value again and only theISignalblock runs — a joystick is a gesture, nothing is replayed — andIJoystickalready splits the text intoxandyfor you. See One block for everything.
Notes
- Use Back to center for anything that moves. A rover that keeps driving after the finger lifts is a rover in the wall.
- Keep
drive()fast — set two PWM values and return. The device receives a stream while you drag. - Two joysticks (drive + camera) need two Text signals.
Next
→ Direction Pad — steps instead of a continuous position → Horizontal Slider — one axis