Direction Pad

Four directions and a centre, like the pad of a game controller. A rover, a pan-tilt camera, a menu on a small screen: anything that moves in steps.
What it does
Each key sends a word, not a number: UP, DOWN, LEFT, RIGHT, CENTER. Holding a key sends UP_LONG; letting go sends UP_RELEASE. So the pad needs a Text signal, and the device gets the whole story of every key — pressed, held, released — which is what a motor needs to start, keep going and stop.
When to use it
- A rover or a robot arm — forward while held, stop on release.
- A camera or a turret — one step per tap, continuous while held.
- Navigation — up/down/left/right in a menu the device draws on its own screen.
Set it up
- Declare a Text signal — The pad sends words, so it needs a Text signal. Tap the device icon at the top right, then Declare a signal, and choose the type Text.
- Place it — Back on the dashboard, tap + and choose Direction Pad under Controllers.
- Wire it to the signal — Tap the pad, open the Data tab, tap + Add a target and pick the Text signal you just declared.
- Pick a look and try it — In the Appearance tab, choose the layout you like under Mode. Close the settings, tap ▶, and press a key: the device receives
UP.
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 — a pad sends words. 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 | UP · UP_LONG · UP_RELEASE |
Shown for reference: one word per key and per gesture. The device sorts them with WHEN_UP, WHEN_UP_LONG, WHEN_UP_RELEASE… |

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. |
Mode
| Setting | Type | Default | What it controls |
|---|---|---|---|
| Mode | Cross / ABXY / Dual / PS / Arrows / Round | Round | The layout of the keys. Same words on the wire whatever the look. |
Colors
| Setting | Type | Default | What it controls |
|---|---|---|---|
| Buttons | colour | theme | The keys at rest. |
| Pressed | colour | theme accent | A key while pressed. |

States
- Run mode — a key lights while pressed; holding it sends
_LONGafter half a second; releasing sends_RELEASE. - Device offline — gestures are never replayed. A rover that starts on its own after a power cut is not what anyone wants.
Arduino device code
The address is all the device knows — I7 here; use the one the app gave your signal. In the sketch, one clause per key and gesture, and WHEN_RELEASED_ANY for whichever key, stop:
IDirectionPad(I7) {
WHEN_UP { … }
WHEN_UP_LONG { … }
WHEN_RELEASED_ANY { … }
};
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";
IDirectionPad(I7) {
WHEN_UP { forward(); }
WHEN_DOWN { backward(); }
WHEN_LEFT { turnLeft(); }
WHEN_RIGHT { turnRight(); }
WHEN_UP_LONG { faster(); }
WHEN_RELEASED_ANY { stop(); } // whichever key: stop
};
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(I7, const char* v)runs with exactly the same value asIDirectionPad(I7): 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 pad is gestures, nothing is replayed. See One block for everything.
Notes
- Always handle
WHEN_RELEASED_ANY. A motor that only knows start never stops. WHEN_PAD_PRESSED(key)receives every key in one clause if you prefer aswitchon the key.- One pad, one Text signal. Two pads on the same signal would talk over each other.
Next
→ Joystick — two axes in one gesture, for smooth motion → Advanced Button — one action, one value