# Nextion HMI build guide Start from your existing HMI (`../../2019-teensy-nrf24/remote-nextion/remote.HMI`, the servo monitor) and **add one page named `control`** with the components below. Your existing pages keep working: | Existing | What the firmware does with it | |----------|--------------------------------| | page 1 `t1`, page 3 `t1` | writes `connected` / `not connected`, as the old firmware did. Set both to **vscope = global**, and put their real names (`page1.t1`, …) in `NEXTION_STATUS_TEXTS` in `Config.h` | | page 1 `b2` (id 5) | **upload mode**: keep "Send Component ID" ticked on it. The remote shows `uploadscreen` and passes USB straight through to the display, so Nextion Editor can upload over the remote's USB port. Power-cycle to leave. Serial key `U` does the same | | page 4 `uploadscreen` | shown on entering upload mode | | page 3 sliders `h0`–`h17` | not driven yet: the robot doesn't send servo positions back (that needs the planned telemetry channel) | The firmware drives the display by **component name**, and the display talks back with small custom frames sent from each button's touch event. Layout, fonts and colors are up to you. The names and event code must match exactly. **Set every component on `control` to vscope = global.** The firmware writes them as `control.` and keeps them current whichever page is showing. A local component on another page can't be written from outside, and with `bkcmd=0` the display ignores those writes silently. The remote is authoritative. Use **plain Button** components (not Dual-state buttons) and don't toggle anything locally in the HMI. The remote repaints every label and color from its own state, including a full redraw every 2 s and whenever the display reboots. ## Program.s / page setup In **Program.s**, before `page 0`, add: ``` bauds=115200 ``` This sets the display to the `NEXTION_BAUD` in `remote/Config.h`. The display ships at 9600, and `bauds=` persists across power cycles. The old firmware used the ITEAD library at 9600, so your HMI probably runs at 9600 today. Name the new page `control`. The firmware never changes pages, except into `uploadscreen` for upload mode. Add buttons on your other pages to switch to it (`page control`). ## Components Text components need **txt_maxl** at least as large as the longest string the firmware writes. Button bounds here allow some slack. | Name | Type | txt_maxl | Firmware writes | |----------|---------|----------|----------------------------------------------| | `bArm` | Button | 10 | `ARMED` / `DISARMED`, bco red / gray | | `bKill` | Button | – | nothing (static "DISARM" label, make it red) | | `bStand` | Button | 6 | `STAND` / `SIT`, bco green / gray | | `bGait` | Button | 8 | `TRIPOD` / `WAVE` | | `bMode` | Button | 8 | `DIRECT` / `HEADING` | | `bRs` | Button | 10 | `R: ROTATE` / `R: MOVE` | | `bRGyro` | Button | – | bco green / gray (label it "REMOTE GYRO") | | `bBGyro` | Button | – | bco green / gray (label it "ROBOT GYRO") | | `hSpeed` | Slider | – | `val` 0..255 (set **maxval = 255**) | | `nSpeed` | Number | – | `val` 0..100 (speed %) | | `hHeight`| Slider | – | `val` 0..200, 100 = default (set **maxval = 200**) | | `nHeight`| Number | – | `val` -100..100 (height offset %) | | `bCal` | Button | 9 | `CAL` / `SAVE CAL`, bco orange while active | | `bCalX` | Button | – | nothing (static "CANCEL CAL") | | `bZero` | Button | – | nothing (static "LEVEL") | | `tLink` | Text | 10 | `LINK 97%` / `NO LINK`, pco green / red | | `tMsg` | Text | 40 | status / rejection messages | ## Touch events Put this in each component's **Touch Release Event** (the Speed slider uses **Touch Move** as well so the value tracks your finger). Frame format: `'#'` (0x23), length, command byte, optional value byte. | Component | Event code | Command | |-----------|------------------------------------------|--------------------------------| | `bArm` | `printh 23 01 41` | `A` toggle arm (needs sticks centered) | | `bKill` | `printh 23 01 4B` | `K` disarm, always accepted | | `bStand` | `printh 23 01 53` | `S` toggle sit/stand | | `bGait` | `printh 23 01 47` | `G` tripod ↔ wave | | `bMode` | `printh 23 01 4D` | `M` direct ↔ heading-hold | | `bRs` | `printh 23 01 58` | `X` right stick rotate ↔ translate | | `bRGyro` | `printh 23 01 52` | `R` remote-gyro tilt on/off | | `bBGyro` | `printh 23 01 42` | `B` robot self-stabilize on/off | | `hSpeed` | `printh 23 02 56`
`prints hSpeed.val,1` | `V` + speed byte | | `hHeight` | `printh 23 02 48`
`prints hHeight.val,1` | `H` + height byte (Touch Move + Release) | | `bZero` | `printh 23 01 5A` | `Z` zero handset level | | `bCal` | `printh 23 01 43` | `C` start / save stick calibration | | `bCalX` | `printh 23 01 51` | `Q` cancel calibration | **Uncheck "Send Component ID"** on every component on `control`: those standard touch frames only add serial traffic. The one exception is the old page 1 `b2` upload button (see the top). Protocol details and the parser live in `NextionUI.h/.cpp`. To add a control, pick an unused command byte, add it to `NextionUI::decodeCustom()` and `UiCmd`, handle it in `RemoteState::handle()`, and add a row here.