static
Meet TIM - GearSense's Throttle Injection Module".
Meet TIM — GearSense's Throttle Injection Module
GearSense needs a way to take control of a bike's throttle signal — smoothly, safely, and in a way that the rider can override at any moment. That job belongs to TIM, the Throttle Injection Module.
TIM sits physically inline between the bike's thumb throttle and the motor controller (ESC). When GearSense is active, TIM substitutes a computed signal for the rider's own throttle input. When the rider wants control back, they take it — instantly, unconditionally.
The relay topology
The heart of TIM is a single relay, K1, wired as a changeover switch between two signal sources:
PHYSICAL THROTTLE ──── K1 NC ─┐
├─ COM ──── ESC throttle input
MCP4725 DAC out ────── K1 NO ─┘
K1 de-energised (default / fail-safe): the rider's physical throttle feeds straight through NC → COM → ESC. TIM is electrically invisible. The bike rides exactly as stock.
K1 energised (TIM active): the DAC drives NO → COM → ESC. The rider's physical throttle is electrically disconnected from the ESC. GearSense has full control of the throttle signal.
This is a hard, hardware-level switch — not a software blend. TIM must actively hold the relay to stay in control. Any power failure, watchdog trip, or firmware crash drops K1 immediately, returning the bike to stock throttle behaviour. The fail-safe state requires no microcontroller involvement to reach or hold.
THROTTLE_SENSE — the rider's hand is always visible
While K1 is energised and the DAC has control, GearSense still has a live ADC tap on the physical throttle signal via a dedicated sense network on pin 8 of the TIM ↔ GearSense connector. This tap runs ahead of the relay — so it's always live, regardless of K1's state.
PHYSICAL THROTTLE SIGNAL
│
├───────────────────── K1 NC (→ ESC when de-energised)
│
└── sense network ──→ GearSense ADC / THROTTLE_SENSE
The network uses an R5 = 5.6kΩ / R6 = 10kΩ divider to scale the throttle's voltage range down to safe ESP32 ADC levels. An optional BAT54S dual Schottky clamp protects the line — it runs through the external harness and could pick up noise. ADC1 is used specifically because ADC2 is unreliable while BLE is active on the ESP32-S3.
This tap is what makes rider intent detection possible while TIM is in control, and it's what closes the previously-open FMEA-07 item: GearSense was formerly blind to what the rider was doing with the throttle grip while the DAC was driving — THROTTLE_SENSE fixes that.
The override state machine — "rider's touch always wins"
TIM operates in two states:
- AUTO — K1 energised, DAC controls the throttle line, assist control law running
- OVERRIDE — K1 de-energised immediately, physical throttle passes straight to the ESC
The rule is deliberately asymmetric:
Entry to OVERRIDE is fast and generous. Any deliberate throttle movement outside the idle envelope triggers it, debounced by just two consecutive filtered samples — roughly 2–8ms worst case. False positives (TIM yields when it didn't need to) are harmless. False negatives (TIM keeps driving when the rider wants out) are the actual hazard. The rule is: any deliberate throttle input is authoritative, full stop — TIM does not try to infer whether the rider wants more or less than it's already delivering.
Return to AUTO is slow and conservative. THROTTLE_SENSE must remain continuously inside the idle envelope for 0.5–1.0 seconds before TIM resumes. And critically, the DAC is written to V_idle before K1 re-energises — so the ESC never sees a stale or mid-computation DAC value when TIM takes back control. No jolt, no unexpected surge.
Auto-calibration — one TIM, any bike
Throttle conventions vary between bikes. Most eBikes use a rising convention (~0.8V idle, rising to ~4.2V full throttle). GearSense's own Cargo and Tofino bikes use an inverted convention (~3.4V idle, falling to ~0.76V full throttle) — meaning LOW voltage = MORE power. Hardcoding these constants into firmware would make each TIM unit bike-specific.
Instead, TIM includes a guided auto-calibration routine:
- Prompted: confirm throttle fully released — sample idle voltage V_a
- Prompted: briefly open the throttle partway — sample partial-open voltage V_b
- Polarity is self-determined: V_b > V_a = standard/rising; V_b < V_a = inverted. No brand or model knowledge needed.
- Capture the full-open endpoint
- Store
(V_idle, V_full, direction)in flash — not firmware constants
The result is a TIM that can be installed on any compatible eBike without a firmware rebuild. A bad calibration can only ever degrade TIM's active control behaviour — and only while the rider's hand is off the throttle. It cannot affect the hardware fail-safe path, which is hard-wired to the physical throttle through K1's NC contact regardless of any software state.
The TIM ↔ GearSense connector
TIM and the GearSense head unit are physically separate boards, connected by a fixed 8-pin JST-GH connector (1.25mm pitch, 22 AWG silicone wire). The GearSense-facing pinout is the same on every TIM variant — only the bike-facing side changes between installations.
| # | Wire | Direction | Purpose |
|---|---|---|---|
| 1 | GND | shared | Common reference |
| 2 | SDA | GearSense ↔ level shifter | I2C data |
| 3 | SCL | GearSense ↔ level shifter | I2C clock |
| 4 | RELAY_EN | GearSense → TIM | Energise relay command |
| 5 | RELAY_STATE | TIM → GearSense | Relay/coil readback — firmware confirms the command landed |
| 6 | 5V (charge) | TIM → GearSense | Docked charging via OR-diode at GearSense's VBUS |
| 7 | 3.3V logic ref | GearSense → level shifter | Powers the I2C level shifter's low side only |
| 8 | THROTTLE_SENSE | TIM → GearSense | Filtered/divided tap of the physical throttle signal, always live ahead of K1 |
What's built and what's next
TIM's relay, DAC, THROTTLE_SENSE network and connector are hardware-done. The override state machine and auto-calibration are firmware tasks in progress. Sitting above all of that — and the reason TIM exists — is the assist control law: the baseline-hold controller that infers rider effort from cadence deviation and computes a target throttle voltage for the DAC to output. That layer is designed in INTENT_SENSING_DESIGN.md and is the next firmware phase.
Two eBikes will carry TIM installations: the Energy One Cargo (Lishui LSW899-45-21M controller) and the Tofino (LSW899-76E). Both share the same controller family but have different gear clusters, making them complementary test beds for the gear-sensing and assist algorithms. A third GearSense variant — running without TIM on a standard pushbike — is being developed separately for Roman.