An open API service indexing awesome lists of open source software.

https://github.com/packerlschupfer/nova-voyager_firmware

Open-source replacement firmware for the Teknatool Nova Voyager DVR drill press HMI (GD32F303RC, FreeRTOS, ST7920 LCD). Reverse-engineered MCB protocol, combinable tapping triggers, hardware E-Stop.
https://github.com/packerlschupfer/nova-voyager_firmware

arm-cortex-m4 drill-press dvr embedded firmware freertos gd32 gd32f303 hmi nova-voyager open-source-hardware platformio reverse-engineering st7920 teknatool woodworking

Last synced: about 16 hours ago
JSON representation

Open-source replacement firmware for the Teknatool Nova Voyager DVR drill press HMI (GD32F303RC, FreeRTOS, ST7920 LCD). Reverse-engineered MCB protocol, combinable tapping triggers, hardware E-Stop.

Awesome Lists containing this project

README

          

# Nova Voyager Open Firmware

Open-source replacement firmware for the **Teknatool Nova Voyager DVR**
drill press HMI controller (GD32F303RCT6, ST7920 16x4 LCD, FreeRTOS).

Idle screen
Drilling at 1487 RPM

Idle — target 1500 RPM, load bar empty
Drilling at 1487 RPM, 32% load, 12.4 mm depth

Tapping with triggers
Menu

Tapping at 580 RPM with Depth+LoadInc+Quill triggers
Menu navigation (wraps at top/bottom)

> Community-developed firmware based on reverse engineering.
> Installing this replaces the OEM firmware. Back up your OEM image
> first — see [`docs/HARDWARE_SETUP.md`](docs/HARDWARE_SETUP.md).

---

## What this adds

- **Tapping** — 6 combinable triggers (depth, load increase, load slip,
clutch, quill direction, peck) with GF bit 2 direction-change polling
- **Foot pedal** — uses the unused X11 connector on the HMI board for
hands-free chip-break and reverse override
- **Load bar** — ST7920 CGRAM bar graph on row 3 (40-step, 16x16 custom chars)
- **F4 display modes** — load bar / temperature + DC bus voltage / speed info / off
- **Material speed calculator** — 12 materials, 9 bit types, auto RPM
- **Configurable motor** — overload threshold (LD), speed ramp (DN),
max speed, advanced PID submenu, motor profiles (Soft/Normal/Hard)
- **OEM-compatible EEPROM** — speed presets and max RPM survive firmware
switches; custom settings in 0xB0-0xFF; crash dump persists across power cycles
- **Step drilling** — automatic RPM adjustment by tool diameter
- **Favorite speeds** — F1 cycles presets, long-press saves current RPM
- **Sensor alignment** — ALIGN command tests RPS phases via voltage hold
- **F0 fault decoding** — motor error screen shows decoded MCB fault code
- **Settings export** — DUMP (all settings) + EEDUMP (EEPROM hex dump)
- **Games** — optional Pong, Snake, Penguin in a separate FreeRTOS task
(`pio run -e nova_voyager_games`); zero game code in default build
- **Serial console** — 61 production + 38 debug commands (9600 baud)
- **USB DFU updates** — with the companion
[bootloader](https://github.com/Packerlschupfer/nova-voyager_bootloader),
no ST-Link needed for subsequent flashes
- **Documented MCB protocol** — see [`docs/MOTOR_PROTOCOL.md`](docs/MOTOR_PROTOCOL.md)
and [`docs/EEPROM_MAP.md`](docs/EEPROM_MAP.md)

---

## Quick start

```bash
# Build (production, no games)
pio run -e nova_voyager

# Build with games (Pong, Snake, Penguin)
pio run -e nova_voyager_games

# Flash via ST-Link (fast — assumes flash already unlocked)
./flash_firmware.sh quick

# First-time install (unlocks flash protection, writes bootloader + app)
./flash_firmware.sh custom

# Restore OEM firmware
./flash_firmware.sh original
```

For bench setup, wiring, and first-flash instructions see
[`docs/HARDWARE_SETUP.md`](docs/HARDWARE_SETUP.md).

---

## Hardware

| | |
|---|---|
| MCU | GD32F303RCT6 (ARM Cortex-M4F, 120 MHz, 256 KB flash, 48 KB RAM) |
| Display | ST7920 16x4 character LCD, 8-bit parallel |
| Motor link | USART3 @ 9600 baud to MCB (Switched Reluctance Motor controller) |
| Inputs | Rotary encoder + 7 buttons (EXTI), foot pedal |
| Sensors | Depth (ADC), guard switch, E-Stop |
| Bootloader | DFU at `0x08000000` (12 KB), application at `0x08003000` (244 KB) |

### Pin map

| Signal | Pin | Notes |
|--------|-----|-------|
| LCD data bus | PA0-PA7 | 8-bit parallel |
| LCD RS / RW / E | PB0 / PB1 / PB2 | Control lines |
| Encoder A / B / Btn | PC13 / PC14 / PC15 | 4 counts/detent, button = fine/coarse toggle |
| E-Stop | PC0 | Active high, direct GPIO cutoff path |
| Guard switch | PC2 | Active high (open = high) |
| Foot pedal | PC3 | Active low (X11 connector) |
| Depth ADC | PC1 | ADC1 channel 11 |
| Motor UART | PB10 / PB11 | TX / RX |
| Debug UART | PA9 / PA10 | TX / RX, 9600 baud |

---

## LCD layout

```
1487 1500 <- actual RPM (left), target RPM (right)
32 DRL --- FWD <- load, state, triggers, direction
T: D: 12.4 <- target depth, current depth
[|||||||| ] <- load bar (F4 cycles: load / temp / speed / off)
```

State codes: `IDL` idle, `DRL` drilling, `TAP` tapping, `STP` step drill, `MNU` menu.

### F-keys

| Key | Short press | Long press |
|-----|-------------|------------|
| F1 | Cycle favorite speeds | Save current RPM to favorites |
| F2 | Arm / disarm tapping | — |
| F3 | Set depth target to current depth | — |
| F4 | Cycle row 3 (load bar / temperature / speed info / off) | — |

---

## Tapping

Six **combinable** triggers. Enable any subset in the menu; arm with F2.

| Code | Trigger | Watches | Use case |
|:----:|---------|---------|----------|
| `D` | Depth | Quill depth sensor | Stop / reverse at target depth |
| `I` | Load Inc | KR (load %) spike | Blind holes, excessive resistance |
| `S` | Load Slip | CV overshoot | Through-hole exit detection |
| `C` | Clutch | Load plateau | Torque limiter engaged |
| `Q` | Quill | Quill direction change | Auto-reverse on quill lift |
| `K` | Peck | Timed cycles | Chip clearance |
| `P` | Pedal | Foot pedal | Manual chip-break / hold |

Priority: **Pedal > Quill > Depth > Load > Peck**.

---

## Foot pedal (optional)

The HMI board exposes PC3 on the **X11** connector. The OEM firmware
doesn't use it; this firmware reads it as a foot-pedal input.

| Part | Spec |
|------|------|
| Foot switch | TFS-1 momentary SPST, NO contacts |
| Panel jack | GX12 2-pin, panel-mounted |
| Internal cable | JST PH 2.54mm 3-pin to X11 |

```
foot switch chassis panel jack HMI board X11
┌─────┐ ┌─────────┐ ┌──────────┐
│TFS-1│──── 2 wire ───┤ GX12 ├──── 2 wire ───┤ PC3 sig │
│ NO │ │ 2-pin │ │ GND │
└─────┘ └─────────┘ │ N/C │
└──────────┘
```

Active low, internal pull-up. Disable in `Menu > Tapping > Pedal`
if wired but not wanted for a session.

---

## Architecture

5 FreeRTOS tasks (+ 1 dynamic game task when games are active):

| Task | Prio | Stack | Rate | Role |
|------|:---:|:-----:|:---:|------|
| Main | 1 | 256 W | ~100 Hz | Event queue, console, watchdog |
| Depth | 2 | 96 W | 50 Hz | ADC quill sensor |
| UI | 2 | 256 W | 50 Hz | Buttons, encoder, LCD |
| Tapping | 3 | 160 W | 20 Hz | Trigger state machine |
| Motor | 4 | 192 W | 2/20 Hz | UART to MCB (adaptive) |

Per-task heartbeat watchdog: the main loop feeds the IWDG only when
all tasks have checked in and the event queue is draining. HAL tick
kept in sync via `vApplicationTickHook()` → `HAL_IncTick()`.

Motor stack:

```
task_motor.c FreeRTOS task, command queue, status polling
+- motor.c MCB parameter API (profile, PID, power)
+- motor_protocol.c Packet build / parse
+- motor_uart.c USART3 hardware (DMA RX)
```

---

## Safety

- **E-Stop** — ISR drives PD4 low (motor enable) before any queued
command. Cannot be delayed by a stuck task, full queue, or UART failure.
- **Guard interlock** — motor refuses to start with guard open;
auto-stops and activates spindle hold if guard opens while running.
- **Queue purge** — E-Stop, guard open, and motor fault purge the motor
command queue to prevent stale FORWARD/REVERSE from re-enabling the motor.
- **Watchdog** — IWDG ~3 s, fed only when all 5 tasks are alive and the
event queue is draining. Queue saturation = stall = reset.
- **EEPROM settings** — when EEPROM is present, no flash writes needed
(no 20ms CPU stall, safe to save while motor running).
- **COMM FAULT** — 15 consecutive UART failures trigger hardware motor
disable + fault state with F0 code decoding.
- **USART overrun handling** — ORE flag cleared on every RX poll to
prevent silent data loss during FreeRTOS task switches.
- **Depth target** — auto-stop and beep when quill reaches target depth
or step drill reaches target diameter.

---

## Serial console

9600 baud on PA9/PA10. 61 production commands — start with `HELP`.

| Command | What it does |
|---------|--------------|
| `STATUS` | System state, queues, overflow counters |
| `STACK` | Per-task stack high-water marks |
| `DEPTH` | Live depth sensor |
| `GUARD` | Guard / pedal / E-Stop GPIO state |
| `KR` | Query MCB load percentage |
| `CV` | Query MCB current speed |
| `TAP` | Show / configure tapping triggers |
| `SPEED ` | Set target RPM |
| `DUMP` | Export all settings as key=value |
| `EEDUMP` | Hex dump HMI EEPROM (256 bytes) |
| `ALIGN [A/B/C/OFF]` | Sensor alignment test |
| `GAME P/S/N` | Pong / Snake / Penguin (games build only) |
| `DFU` | Reboot into USB DFU bootloader |
| `SAVE` | Persist settings to EEPROM |

---

## Project status

- All features implemented; firmware in daily use
- **389 unit tests** across 13 suites (all passing)
- 0 compiler warnings
- ~31% flash / ~28% RAM (production); ~34% / ~41% RAM with games

---

## License

GPL-3.0 — see [LICENSE](LICENSE).

Community reverse-engineered. No warranty. Use at your own risk.

## Credits

Reverse engineering based on independent analysis of the Teknatool
firmware (R2P05x, R2P06e, R2P06k), logic-analyzer captures of the MCB
protocol, and patient experimentation.