[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-83828":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":15,"stars7d":16,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":17,"compositeScore":18,"rankGlobal":9,"rankLanguage":9,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":9,"pushedAt":9,"updatedAt":24,"readmeContent":25,"aiSummary":9,"trendingCount":14,"starSnapshotCount":14,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},83828,"Reevo-Hubless-E-Bike-Screen","setha-maker\u002FReevo-Hubless-E-Bike-Screen","setha-maker","The Reevo Hubless E-Bike relies on a now-defunct app for most of its features. This project solves that with a self contained screen that integrates with the bike. $20 and some terminal commands are all you need.",null,"C++",181,13,1,0,7,57,53,83.14,"Other",false,"main",true,[],"2026-06-12 04:01:42","# Reevo Display\n\nA custom dashboard for the **Beno Reevo** hubless ebike. The company abandoned the project\nand the original phone app is dead — this project replaces the entire app with\nan ESP32-S3 touchscreen that talks directly to the bike over BLE. No cloud, no\nSIM, no account.\n\nIf you own a Reevo and a soldering iron and twenty bucks, you can have a\nworking dashboard again.\n\n---\n\n## What you get\n\n- Live speedometer (green 7-segment), battery %, trip odometer with reset\n- Manual control of headlight, badge light, kickstand lock, assist level\n- Touch-PIN unlock when you lock the bike\n- **Brake warn** — flashes headlight + badge in alternation when you brake\n- **PAS auto-timeout** — drops pedal assist to 0 after 10 min idle so the\n  bike never takes off when you push it through the garage\n- **Master code recovery** if you forget your PIN\n- Built-in **Wi-Fi access point + web console** for sending raw BLE commands,\n  resetting your PIN, recoloring the screen, and viewing a full setup manual\n\n---\n\n## Hardware\n\n### Display (required)\n\nThe default target is the **Freenove FNK0104B** ESP32-S3 board with 2.8″\ncapacitive touchscreen.\n\n> Buy: \u003Chttps:\u002F\u002Famzn.to\u002F4dJlGMW>\n\nSpecs that matter:\n- ESP32-S3 with 16 MB flash, 8 MB PSRAM\n- 240×320 ILI9341 IPS panel\n- FT6336U capacitive touch\n- Native USB-C (programming + power)\n- 4-pin UART header (5V, GND, TX, RX)\n\nIf you bought a different \"CYD\" board, see [Using a different display](#using-a-different-display) below.\n\n### Power\n\nThe display takes 5V via USB-C. Three ways to power it:\n\n1. **Recommended (clean):** Solder to a labeled **5V** and **GND** pad on\n   the bike's mainboard and run those to the **5V** and **GND** pins of the\n   display's UART header. The board is fully silk-screened, so suitable 5V\n   and GND points are easy to find — just confirm with a multimeter that\n   the pad reads ~5V (not the 12V\u002F48V rail) before you connect it. This is\n   what my (Seth's) build does — the screen comes on when the bike does and\n   goes off when the battery is removed.\n2. **USB-C battery brick** — easy, less clean.\n3. Any other power source, using a cheap buck converter to step down to 5V\n\n> **The display's 4-pin UART header carries two unrelated things.** The\n> **5V\u002FGND** pins are just power (above). The **TX\u002FRX** pins are the\n> optional BLE-debug data tap described below. They're independent — you\n> can wire power without the data tap, or vice versa. Nothing on this cable\n> controls the bike: the firmware only ever *listens* on RX. It cannot\n> send anything to the bike over this connection.\n\n### Enclosure (optional, 3D-printable)\n\nA two-piece printable case for the Freenove FNK0104B board lives in\n[`screen_enclosure\u002F`](screen_enclosure\u002F):\n\n| File | Part |\n|---|---|\n| [`Reevo_Screen_Top.stl`](screen_enclosure\u002FReevo_Screen_Top.stl) | Front bezel — frames the screen, snaps onto the bottom |\n| [`Reevo_Screen_Bottom.stl`](screen_enclosure\u002FReevo_Screen_Bottom.stl) | Rear shell — holds the board, routes the UART cable out |\n\nBoth files preview in 3D right on GitHub — click either one to spin it\naround before you print.\n\n**Printing notes.** The case is **not water-resistant** — and honestly you\nshouldn't ride a Reevo in the rain anyway. Treat the bike like the\ncollector's item it now is: ride it carefully and seldom. Because of that,\nfilament choice isn't critical — **PLA or PETG both work fine**. (The one\nexception: don't leave a PLA print baking in direct desert sun, à la\nArizona — it'll soften.)\n\nFor reference, mine (Seth's) is printed in **MatterHackers NylonX** at\n**0.24 mm layer height, 3 outer walls, 25% infill** — overkill that'll\noutlast every other piece of plastic on the bike. NylonX is a\ncarbon-fiber-filled nylon, so it needs a **hardened nozzle** and an\n**enclosed printer**. Don't feel obligated to match that — use the\nfilament and machine you already know and like.\n\n### BLE pairing — read this before you flash\n\nThe bike's BLE module (RN4870) ships with passkey `111111`. **That default\nonly works if the bike has never been paired with the original Reevo app.**\nThe first time the original app paired with your bike, it rotated the\npasskey to a value only the app knew. You can't factory-reset that without\nalready being able to bond — chicken and egg.\n\nSo, in order of likelihood, here's how you actually find the passkey:\n\n- **A.** You wrote it down when you first set the bike up. Rarest.\n- **B.** It's stored somewhere on the device that originally paired. On\n  macOS, *Keychain Access* sometimes has BLE pairing data (search for\n  \"Reevo\" or the bike's MAC). iOS keeps it locked away inside the system.\n  Worth a look, mileage will vary.\n- **C.** Read it off the bike's BLE module debug UART. This sounds\n  intimidating but it's actually how I recovered mine, and it's the\n  reliable path for any bike that was ever paired with the original app.\n  You would need to take the bike apart completely and remove the main\n  board in the motor compartment. It's gnarly. It's scary. It's doable.\n  Details below.\n\n### Recovering the passkey via the UART (the real path for most bikes)\n\nWhen anything tries to bond, the bike's RN4870 BLE module **prints the\nreal expected passkey to its debug UART**. You just have to read it. Solder\ntwo thin wires to the **TX** and **GND** pads on the module — see\n[`docs\u002Fble_solder_points.png`](docs\u002Fble_solder_points.png) for the exact\npads. (You only need the module's **TX**; the connection is read-only, so\nits RX is never used.) While you've got the iron out and the bike open\n(bullet C above — you'll have the mainboard exposed), it's the natural\nmoment to also grab a **5V** and **GND** pad for permanent screen power —\nsee [Power](#power).\n\nThere are two ways to read what it prints:\n\n#### Easiest — read it right on the dashboard (no computer)\n\nIf you've already built the screen, it *is* your serial terminal. The\ndashboard's **Diagnostics page** renders whatever the BLE module chatters\nto its debug UART.\n\n1. Run the module's **TX → the display's UART-header RX**, and tie **GND**\n   to **GND**. (That's the data tap; powering the screen is a separate\n   pair of pads — see [Power](#power).)\n2. On the dashboard: Settings → **Diagnostics**.\n3. Trigger a pair attempt from *anything* — the dashboard itself,\n   **LightBlue** (iOS), **nRF Connect** (Android). Enter `111111` or any\n   6-digit number; it'll fail, that's fine.\n4. The 6-digit passkey scrolls onto the Diagnostics page.\n5. Settings → Command Prompt → Start AP, join the Wi-Fi, browse to\n   `192.168.4.1\u002F`, and type `setblepin \u003Cthe number>`. Tap **Re-pair bike**\n   under Bluetooth. Done — and you never touched a computer.\n\n#### Or — read it with a USB-UART adapter\n\nHandy if you want the passkey *before* the screen is built.\n\n1. Run the module's **TX** and **GND** to a USB-UART adapter (CP2102, FTDI,\n   CH340 — any will do; adapter **RX ← module TX**). Open a serial terminal\n   at **115200 baud, 8N1, no flow control**.\n2. With the terminal listening, attempt to pair from anything and enter any\n   6-digit number — it'll fail, but the module prints the real passkey.\n3. Read the 6-digit number off the terminal, then `setblepin \u003Cnumber>` on\n   the web prompt and **Re-pair bike**.\n\n**You do not need to do any of this on a new, never-paired Reevo** — the\ndefault `111111` works there. But for anything secondhand, plan on the\nUART tap.\n\n---\n\n## Quick install (macOS \u002F Linux)\n\nIf you've never touched any of this before:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fsetha-maker\u002FReevo-Hubless-E-Bike-Screen.git\ncd Reevo-Hubless-E-Bike-Screen\n.\u002Fscripts\u002Finstall.sh\n```\n\nThe script installs Homebrew (if needed), Python 3, PlatformIO, and the\nasset-converter dependencies, then builds and flashes the firmware. Plug\nthe ESP32-S3 board into USB-C **before** running it.\n\n## Manual install\n\nAlready have a working dev environment? Install requirements yourself:\n\n```bash\npip install platformio Pillow numpy qrcode\n```\n\nThen:\n\n```bash\ncd firmware\npython3 tools\u002Fimage_to_rgb565.py    # generates src\u002Fassets.h bitmaps\npio run -e reevo -t upload          # builds and flashes\n```\n\n---\n\n## Configuration\n\nThe repo ships a public template:\n\n> **[`firmware\u002Finclude\u002Fuser_config.example.h`](firmware\u002Finclude\u002Fuser_config.example.h)**\n\nThe install script copies it to `firmware\u002Finclude\u002Fuser_config.h` on first\nrun. That copy is **gitignored** — your personal values never leak into\nthe public repo. If you're doing the install manually:\n\n```bash\ncp firmware\u002Finclude\u002Fuser_config.example.h firmware\u002Finclude\u002Fuser_config.h\n```\n\nThen edit `user_config.h`. The defines:\n\n| Define | Default | What it does |\n|---|---|---|\n| `USER_DEFAULT_UNLOCK_PIN` | `\"1234\"` | Initial unlock PIN; rider can change at runtime |\n| `USER_MASTER_PIN` | *(commented out)* | Optional owner-recovery master code. Uncomment in your personal copy if you want one. |\n| `USER_DEFAULT_BLE_PASSKEY` | `\"111111\"` | RN4870 factory default. **Only correct for never-paired bikes** — for any used Reevo, recover the real passkey via the UART tap (see above) and set it at runtime with `setblepin`. |\n| `USER_AP_SSID` | `\"ReevoConnect\"` | Initial Wi-Fi network the dashboard broadcasts |\n| `USER_AP_PSK` | `\"reevorider\"` | Initial hotspot password (min 8 chars) |\n| `USER_SPLASH_TAGLINE` | `\"world's worst ebike\"` | Text under the Reevo logo on the boot splash |\n\n### Things you almost never need to recompile for\n\n- **Unlock PIN** — change at runtime via the web `lockreset` command.\n- **Wi-Fi SSID + password** — change at runtime via the web `changewifi`\n  command. New values persist in NVS and survive reboots.\n- **BLE pairing passkey** — change at runtime via the web `setblepin XXXXXX`\n  command (e.g., once you've recovered the real passkey via the UART tap).\n- **Splash colors** — change at runtime via the web `bgcolor` \u002F `speedcolor`\n  commands.\n\nThe compile-time defaults above are just what a fresh, factory-new flash\nshows on first boot.\n\n### The optional master PIN\n\n`USER_MASTER_PIN` is commented out in the public template — the master-code\nfeature is fully compiled out for public builds. If you want a personal \"I\nforgot my code\" backstop, uncomment the line in your `user_config.h` (which\nis gitignored) and put a 4-digit code only you know. Don't commit it.\n\n---\n\n## Using a different display\n\nIf you bought a different ESP32-S3 CYD board, edit:\n\n> **[`firmware\u002Finclude\u002Fdisplays\u002Fdisplay_config.h`](firmware\u002Finclude\u002Fdisplays\u002Fdisplay_config.h)**\n\nThis is the single source of truth for everything display-related: pin\nnumbers, panel driver, panel rotation, color order, touch chip, SPI\nfrequency. Common alternative profiles (Sunton CYD, generic ST7789, etc.)\nare listed as commented-out blocks at the bottom — uncomment the one that\nmatches and recompile.\n\nThings that vary between boards:\n- SPI pins (MOSI, MISO, SCLK, CS, DC, RST, BL)\n- Touch I²C pins (SDA, SCL, INT, RST)\n- Panel driver chip (ILI9341 \u002F ST7789 \u002F ILI9488)\n- BGR vs RGB color order\n- Color inversion\n- Backlight active-high vs active-low\n- Native panel size and rotation\n\nIf your board isn't in the list, find its schematic and fill in the values.\n\n---\n\n## First-time use\n\n1. Power on the bike.\n2. Power on the dashboard.\n3. Wait ~10 seconds. The dashboard scans for any BLE device with \"REEVO\"\n   in its name and tries to bond with the configured passkey (default\n   `111111`).\n   - **Bond succeeds → live telemetry appears.** You're done.\n   - **Bond fails \u002F dashboard sits on \"scan\"** → your bike's passkey has\n     been rotated away from the factory default. Use the UART recovery\n     procedure above to read the real passkey, then `setblepin XXXXXX`\n     from the web command prompt and tap **Re-pair bike**.\n4. The default unlock PIN is `1234`. The first time you lock, the numpad\n   will ask for it. Change it with the web `lockreset` command.\n\nAfter that, everything that needs configuring can be done from the\ndashboard itself — no recompiling.\n\n---\n\n## Built-in help\n\nThe dashboard's web command prompt has three giant text dumps you can read\nright from your phone after joining the AP:\n\n| Command | Contents |\n|---|---|\n| `newreevosetup` | Full end-user manual with troubleshooting tree |\n| `how` | Complete BLE protocol reference (every command & register) |\n| `story` | Claude's narrative of how this firmware came to be |\n\nTo get there: tap the gear icon on the main screen → **Command Prompt** →\n**Start AP** → join the SSID (or scan the QR) → open the URL in any\nbrowser → tap the chip for the command you want.\n\n---\n\n## Troubleshooting (short version)\n\nDetailed guide: type `newreevosetup` on the web prompt.\n\n| Problem | First thing to try |\n|---|---|\n| BLE won't connect | Settings → Bluetooth → Reset Default Pincode → Re-pair bike |\n| Forgot your unlock PIN | Type the master code (whatever you set `USER_MASTER_PIN` to) |\n| Screen won't wake | Tap it. Then power-cycle USB-C. |\n| PAS won't engage | Tap the PAS pill to raise assist level; the timeout may have dropped it |\n| BLE bond fails \u002F \"scan\" forever | The bike's passkey isn't 111111 anymore. Solder UART tap → trigger a pair attempt from any BLE app → read the real 6-digit passkey from the module's debug output → `setblepin XXXXXX` on the web prompt. See the BLE pairing section above. |\n\n---\n\n## Project layout\n\n```\nfirmware\u002F\n  include\u002F\n    user_config.example.h    ← public template (committed)\n    user_config.h            ← your personal copy (gitignored — install\n                                 script makes it from the example)\n    displays\u002F\n      display_config.h       ← edit me if your board isn't a Freenove FNK0104B\n    config.h, pins.h         ← derived from display_config.h\n    lgfx_board.h             ← LovyanGFX panel\u002Ftouch config\n  src\u002F                       ← the actual firmware\n  tools\u002F\n    image_to_rgb565.py       ← bakes splash, icons, QR into src\u002Fassets.h\n    source_images\u002F           ← source PNGs the converter reads\ndocs\u002F\n  PROTOCOL.md                ← full BLE protocol reverse-engineering notes\n  ble_solder_points.png      ← reference for the RN4870 UART tap\nscreen_enclosure\u002F\n  Reevo_Screen_Top.stl       ← 3D-printable front bezel\n  Reevo_Screen_Bottom.stl    ← 3D-printable rear shell\nscripts\u002F\n  install.sh                 ← macOS\u002FLinux one-shot installer\n```\n\n---\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n\nThis project is unaffiliated with Beno. Reevo is their trademark; the\nhardware design is referenced only for interoperability after the company's\nshutdown.\n\n## Credits\n\nBuilt by Seth Alvo, with assistance from Claude (Anthropic).\nSpecial thanks to the prior Claude session that did the initial BLE\nreverse-engineering, and to every Reevo owner who's still riding theirs.\n",2,"2026-06-11 04:11:34","CREATED_QUERY"]