Lap timing, races and garage for Mini 4WD. Works straight away with just the keyboard; when you build a photocell finish gate, you plug it in over USB or WiFi and nothing else changes.
| File | When to use it |
|---|---|
Cronodash-Setup-x.y.z.exe |
Normal install: Start menu, desktop shortcut, uninstall from Control Panel. |
Cronodash-x.y.z-portable.exe |
No install at all: copy it to a USB stick and take it trackside. |
Both are in Releases. You need 64-bit Windows 10 or 11, and nothing else.
Windows shows a SmartScreen warning the first time. The executable is not signed with a commercial certificate — that costs a few hundred euros a year and this is a hobby project. Click More info → Run anyway. If you would rather not trust it, build it yourself: it is three commands.
Timing — lanes side by side with the running clock, laps, last and best lap, a progress bar and live standings. Corrections happen trackside without stopping: undo the last lap, one-second penalty, off-course, retirement, disqualification. Clicking a lap time marks it invalid: it still counts towards the lap total and the overall time, but drops out of best lap, average and consistency.
The bracket puts the rounds side by side and marks who advances with ▲. There are deliberately no one-to-one connecting lines between rounds: in a four-lane heat the qualifiers are redistributed in a snake pattern, so a line would tell a lie.
For heat-based races, the rotation grid is the visual check that everything is right: every row must contain each colour exactly once.
| Format | How it works |
|---|---|
| Heats with lane rotation | Entrants are split into groups of n lanes. Each group runs n rounds and everyone shifts one lane each round, so nobody keeps the inside-lane advantage. Most points wins. |
| Knockout | Heats of n cars; the top finishers of each heat move on until the final. Seeds are spread in a snake pattern, so the strongest do not knock each other out in round one. |
| Time attack | Open session with no lap limit: only the best lap counts. |
Every racer belongs to a team, with a name, a tag and a colour. The colour follows the team everywhere — entry lists, bracket, standings — and in a race the points of every car they field are added together.
English, Italiano, 日本語. You switch in Settings → Language and the whole interface changes at once, dates and times included. Even heat names change language: they are not stored as text but as meaning, so a bracket generated in Italian reads in Japanese without regenerating it.
The translations are not machine output: the Japanese uses the words Mini 4WD people actually use — レーサー for racers, マシン for the cars, コースアウト for going off track, 準決勝 and 決勝 for the rounds.
The garage holds racers and cars with the full setup: motor, gear ratio, rollers, tires, wheels, brake, mass dampers, weight. The statistics show the lap-by-lap trend, the distribution of lap times, how each car progresses over time and an overall best-lap ranking.
The lane colours are not decoration: they are a categorical palette verified for contrast and colour-vision deficiency against the app's dark surface, and the lane number is always printed next to the colour, so identity never depends on hue alone.
- Optional demo data. The archive starts empty. From Settings → Demo data you can load teams, racers, cars and two finished races to see how the app behaves; one click removes them again, and they never touch your real data because they are tagged separately.
- Backups both ways. Export everything to JSON and read it back in: Merge only adds the entries that are missing and overwrites nothing, Replace swaps the archive out. Either way you see the file's contents next to your own before deciding.
- Multi-select. In the garage you can select several cars or racers and delete, duplicate, archive or assign them to a team in one go. Saved sessions are cleaned up the same way from Settings.
The app talks to any board that sends one line per crossing. All of these are accepted:
1 lane 1
L2 lane 2
P,3,148230 lane 3, device clock in ms
4;99120 lane 4, clock 99120
{"lane":2,"t":148230} JSON
When the line carries the device clock, that is what determines the lap times: the variable delay of USB, WiFi and the operating system stays out of the measurement. The app anchors that clock to the system time on the first packet and re-anchors by itself if the board reboots.
| Source | Accuracy | What you need |
|---|---|---|
| Keyboard | ±100 ms | Nothing: one key per lane |
| USB serial | ±1 ms | Arduino/ESP32 + photocells |
| WebSocket WiFi | ±1 ms | ESP32/ESP8266 + photocells |
| Folder | Connection |
|---|---|
firmware/cronodash_gate_serial/ |
USB — Arduino Uno/Nano/Micro, ESP32, ESP8266. No libraries. |
firmware/cronodash_gate_wifi/ |
WiFi — ESP32/ESP8266, WebSockets library by Links2004. |
⚡ ESP32, ESP8266 and the Pi Pico run at 3.3 V and are not 5 V tolerant. A photocell module powered from 5 V must either be powered from 3.3 V instead, or have its output adapted with a divider or a level shifter. Wiring it directly damages the board even when it seems to work at first.
→ Full hardware compatibility guide — supported boards, which pins to use and avoid on each, sensors, USB drivers on Windows, WiFi and troubleshooting.
When something does not add up, Settings → Gate monitor shows the lines exactly as they arrive, including the discarded ones: that is what separates "the board is not talking" from "the board speaks a dialect I do not recognise".
npm install
npm run dev # dev server + Electron window with hot reload| Command | What it does |
|---|---|
npm run dev |
Development with hot reload |
npm test |
53 tests over the race engine, gate protocol, sources, dictionaries and demo data |
npm run typecheck |
Type checking |
npm run build |
Builds the renderer and the main process |
npm start |
Builds and opens the app |
npm run dist |
Installer and portable build into release/ |
VS Code terminals already export
ELECTRON_RUN_AS_NODE=1, which would start Electron as plain Node.scripts/launch-electron.mjsstrips it: always start withnpm run devornpm start, never withnpx electron .directly.
Source comments are in Italian; everything a visitor or a user reads — this README, the hardware guide, the firmware sketches — is in English, with Italian and Japanese versions alongside. See CONTRIBUTING.md.
Electron + React + TypeScript + Vite + Tailwind. No server, no account: the data
lives in a single db.json in the user folder, written atomically and with
batched saves, so a crash mid-heat cannot corrupt the archive.
electron/ main process: window, IPC, serial port picker
src/
types.ts data model (racers, teams, cars, heats, races)
i18n/ en/it/ja dictionaries, typed: a missing key does not compile
timing/ timing sources
source.ts the shared interface: everything downstream sees only this
keyboard.ts one key per lane
serial.ts Web Serial API — no native modules to compile
websocket.ts WebSocket with automatic reconnection
protocol.ts line parser + anchoring of the device clock
manager.ts keeps exactly one source active and swaps it live
engine/ pure logic, tested, no React
heat.ts laps, penalties, lane states, heat standings
brackets.ts lane rotation, bracket, overall and team standings
stats.ts aggregates per car and per session
store/app.ts application state (zustand) + deferred saving
pages/ Timing, Races, Garage, Teams, Statistics, Settings
firmware/ Arduino/ESP32 sketches for the finish gate
docs/hardware.md hardware compatibility
Adding a new detector means writing a subclass of TimingSource and registering
it in timing/manager.ts: the race logic is untouched.
MIT — use it, change it and redistribute it freely.
Mini 4WD is a trademark of Tamiya Inc. This project is not affiliated with or endorsed by Tamiya.







