Skip to content

Cow_Remote

Remote controller firmware (STM32G0B1, Cow_Remote_006). Web tools live in The_Real_Cow_Flasher and The_Real_Cow_Configurator.

Gotchas

  • Remotes on Remote_Record_6.5.2 cannot enter DFU from the BOOT_LOADER USB command: that build calls HAL_DeInit, which drops the EN_POWER self-hold, so the board powers off before the ROM bootloader enumerates. Use the BOOT button method (hold BOOT, plug USB) once; every build since uses the backup-register cookie and works.

Log

  • 2026-09-15: Firmware 6.15.0 makes the four max-power caps USB-configurable in motor units (PIVOT_MAX 115-1000 step 15, SLOW_MAX 350-1000 step 50, FAST_MAX 800-1000 step 50, SLOW_MODE_MAX 110-1000 step 10). Fields appended to FLASHConfigData; older EEPROM bytes fall back to defaults. Verified on hardware, settings survive power cycle. Flasher and Configurator updated and deployed via GitHub Pages.

  • 2026-09-22: Analysis only of remote master c86cb99 versus Record 4ed45a4. USB cap feature is ed30b20 (6.15.0); Record identifies as 6.5.2. Recommend a focused source port, preserving recording controls, PLAY_STOP_DELAY_MS and radio behavior; no implementation or branch changes made. Existing Record configuration occupies bytes 0x00–0x44, overlapping recorder header at 0x40 and first sample at 0x44. Adding caps extends config through 0x48. Resolve storage separation and legacy migration before porting; 0x80 is a candidate recording base (4004 bytes fits configured 8192-byte EEPROM). Existing recordings contain raw drive/turn only, so new caps would affect manual control/new recordings, not replay of old samples. Preserve replay semantics unless separately requested. Port config_manager.h/.c and main.h/.c changes from ed30b20, retain Record delay field (master calls it reserved_legacy), initialize/validate appended caps with an explicit schema marker so old recording bytes cannot masquerade as settings. Verify SAVE/LOAD/RESET, boundary rounding, power-cycle persistence, config/record coexistence, LEDs and playback stop/allstop behavior. Hardware verification remains pending; USB bootloader power-off issue is a separate existing defect.

  • 2026-09-22: Implemented and pushed Record 3754b323bc2b9c51fb73692424f1b40f3291fe1f (firmware 6.6.0), authorized by owner. Ported USB caps, moved recordings to 0x80, retained 60 seconds and 55 spare config bytes. New config magic migrates legacy settings, initializes caps and invalidates recordings; owner explicitly does not need old recordings. Release built with Arm GNU 13.3.Rel1 (zero compiler warnings), ELF/bin/disassembly committed. Host production-code tests passed for migration, USB boundaries/rounding, SAVE/LOAD/RESET, simulated reboot and full recording/playback storage isolation. Binary Release/Remote_Record_6.6.0.bin (57504 bytes, SHA256 17d8d5c0a7d9d43f8579692f72864603c295c2d3e8984028903bfc7bcafd3687). Reproducible build script and test harness included. No hardware flash/test; existing USB bootloader issue remains. Work checkout: ~/engineering/cow-remote-record-usb. Toolchain installed user-space under ~/.local/share/arm-toolchains; checksum matched official Arm download. Primary performed implementation and checks locally; no helper models ran.

  • 2026-10-06: Customer asked to pair two remotes to one robot. Analysis only (remote origin/master b0ac3c7 fw 6.16.0, robot origin/main 3072045 fw 4.8.4): Radio V2 is strictly 1 remote : 1 robot. Robot stores a single link (peer_id, key, address, hop_seed); pairing a second remote overwrites the first, and the remote is the sole FHSS slot-clock master, so two V2 remotes cannot share a robot. V1 (shared ADDR/CH, no auth) technically accepts both remotes, but each remote transmits every 20 ms including neutral, so an idle second remote fights the active one; not a supported mode. Multi-remote V2 would need firmware on both sides (N link records, per-remote keys/addresses, single clock master or robot-owned schedule, control arbitration/handover). No code changed.

  • 2026-11-02: U073 schematics finished on both boards (decoupling, robot BOOT0 bug fixed, pin map verified against ST open pin data, remote rev 007 in its own folder). Local commits only; PCB not started. See handoff.

  • 2026-11-02: Both schematics converted to the project template (sch_src.py generated, function sheets), proven equivalent, ERC 0 errors, 0 rendered overlaps; robot rev 005 moved to hardware/Robot_Cow_005.

Proposal: one firmware with Normal and Recording modes

Status: implementation authorized on 2026-09-22; in progress on feature/unified-normal-recording-usb, pending fixes from cow-remote-unified-review.

2026-09-22 analysis against master c86cb99 and Record 3754b32: one runtime-selectable firmware on master is feasible. Start from master to retain its bootloader, factory-test, EEPROM and transport improvements; port Record's recorder, playback safety/delay and 0x80 storage layout as an optional feature. Share radio, movement, speed settings and persistence code. The input map must be explicit: PB0 = Straight Mode / Record Stop; PB7 = Speed Up / Play Stop; Record uses PC15 for Speed Up, sharing the power input. Indicators also differ (PB1 straight, PB2 record/learn, PA15 power/play), so review LED ownership and actual board/panel wiring before promising identical physical operation. Decouple physical inputs from logical actions and suppress conflicting hold/release callbacks.

Recommended interface: persisted NORMAL/RECORDING mode, configurable first through proposed USB MODE=NORMAL or MODE=RECORDING plus SAVE, effective after restart; DUMP exposes active and saved mode. Reject changes during movement/record/play/pairing/factory activity; startup remains neutral until all buttons release and never auto-plays. Preserve recordings when switching modes and share caps initially. One appended mode byte leaves 54 reserved settings bytes; maintain recording start 0x80 and 60 seconds. Use a versioned migration that distinguishes Record 6.6.0's marker and defaults ambiguous older layouts explicitly rather than guessing; Normal default on blank units, Recording preserved when reliably identified. Invalid mode falls back to Normal. Audit RESET and interrupted writes. Optional later boot-only multi-button setup with LED feedback; exact combination awaits pairing/trim/power overlap audit and physical validation. Avoid live remapping. Release build and host tests must cover both modes, migration, records, caps, mode persistence, invalid input, startup/held buttons and safety stops; bench-check both panel variants, V1/V2 radio, allstop, USB/DFU and LEDs. Existing Record build uses about 57.5 KB image and 17.1 KB static RAM, versus linker regions 128 KB flash and 144 KB RAM; combined image and stack headroom must be measured, not assumed. No firmware changes made for this proposal.

  • 2026-09-22: Built the local master-based unified Normal/Recording firmware 6.16.0 with USB mode staging/SAVE/restart, Record 6.6 migration and 0x80 storage. Release and original host integration suite pass. At owner request, read-only Claude Opus 5.5 review completed; primary independently reproduced playback-arming, short-stop and partial-record-save concerns inherited from Record. Review-only pass made no source changes; branch remains local/unpushed pending findings. Full triage: cow-remote-unified-review.

  • 2026-09-22: Inspected active Cow Flasher and Configurator repositories for owner-requested release/mode integration planning. Proposed two additions Record6.6 and Unified6.16, capability-gated mode UI, verified save/restart status and deliberate release default. Found unacknowledged saves and fragile serial response handling. No app/firmware implementation or deployment. Plan: cow-flasher-configurator-mode-plan.

  • 2026-09-22: Owner authorized implementation/push of all planned integration changes. Pushed unified branch418d3b5 with CRC/commit-last verified recording storage serviced one page per control tick, neutral storage output, loading cancellation/indicators, auto-stop60seconds, neutral-at-press Play arming, immediate Play stop, V1 stale packet neutralization and SAVE/LOAD/RESET responses. Release64,060bytes (text63664/data396/bss16780), SHA2560925ecc91c80afebb352fb1b9e6d6266de9ef4512c5707ec3860762fc9272fa7. Host fault/scheduler/mode tests passed; no hardware flash. Configurator7384691 and Flasher45346f7 pushed to feature branches. Unified is preview, Normal6.15 remains catalog default, legacy Record6.6 unchanged. Delivery: cow-flasher-configurator-mode-plan.

  • 2026-09-22: At explicit owner request, fast-forwarded and pushed default branch master to418d3b5. Existing feature branches retained. Web-app GitHub Pages deployment triggered; status verification ongoing at this log entry. No new source changes.

  • 2026-09-22: Added root README.md and pushed to master at342979e, requested by owner. Covers purpose, usage, build/local setup, tests, related projects and firmware/mode compatibility. Relative links and Git whitespace checked; documentation-only change.

  • 2026-11-01: Second-source MCU plan (owner request): WCH RISC-V CH32V208CBU6 (QFN48, 128K/64K, 4 UART, CAN, USBD+USBFS, BLE 5.3, needs 32 MHz crystal) for both robot and remote; optional BLE config channel via Web Bluetooth in the Configurator. Plan only, local branch mcu-second-source (worktrees ~/engineering/worktrees/Cow_Robot_Board-mcu2, Cow_Remote-mcu2), docs/MCU_SECOND_SOURCE_PLAN.md, not pushed. Open gates: V208 LCSC stock, USART half-duplex, CAN/USBD SRAM sharing, remote I2C 1 MHz->400 kHz. Stock 2026-11-01: G0B1CBT6/CCT6/CET6 all 0 at DK+Mouser; G0B1KET6 249/514; G0B1KCT6 1500 at DK (rung-0 drop-in for robot; option-byte dual-bank bits must be skipped).
  • 2026-11-01: Cross-vendor MCU survey (ST/NXP/Microchip/TI/others) added as Appendix A on mcu-second-source plans. Recommendation changed: STM32U073 (CBT6 remote, KCU6/KBU6 robot; same Cube HAL, crystal-less USB, ultra-low-power, $2.05-2.43@100, in stock) is the primary second source; CH32V208 kept as Bluetooth option; fallback NXP MCXC243VFT (remote) / SAME51J19A (robot). Gates: robot RAM <=40K, AN2606 U0 DFU, LQFP48 pin compatibility, remote stop current.
  • 2026-11-01: Radio drops on battery vs USB (owner report), analysis only: 006 radio E01-ML01SP4 (20 dBm PA, ~120 mA TX, needs >=3.3 V) fed by XC6206 LDO from 1S Li-ion (3.5-4.2 V) -> LDO dropout/sag below ~3.6-3.7 V battery; USB adds antenna ground. Tests + respin fixes (buck-boost radio rail) in Cow_Remote mcu-second-source plan Appendix B. Not measured yet.
  • 2026-11-01: CH32V208CBU6 stock confirmed from owner's LCSC screenshot: C5713556, QFN-48 5x5, 2,192 in stock, $1.53@1, $0.95@100, $0.85@980. LCSC only (not at DK/Mouser). Plans updated.

Handoff 2026-11-02 (updated, second chat): STM32U073 respin (robot rev 005 + remote rev 007)

Owner chose STM32U073CCT6 (LQFP48) for both boards + fix robot USB-C footprint. All local, nothing pushed. - Worktrees (branch mcu-second-source): ~/engineering/worktrees/kicad-lib-mcu2, .../Cow_Remote-mcu2, .../Cow_Robot_Board-mcu2. - kicad-lib (daef605, 4d50cc2): symbol EmbeddedEra:STM32U073CCT6 (IPN blank, ERP sync NOT run, needs owner OK); HRO TYPE-C-31-M-12 land pattern fixed; tools scripting/schematic/mcu_swap.py, sch_netcheck.py, specs mcu_swap_specs/. - Schematics DONE (both): pin map checked against ST open pin data STM32_open_pin_data/mcu/STM32U073CCTx.xml (power pins, PF2-NRST=7, USART/LPUART/SPI/I2C/USB alternate functions all valid). EXTI/timer check against shipping G0 firmware: remote uses EXTI only on IRQ (now PB10, line 10) and USB_DET (PA8, line 8), robot only IRQ (PA3); no PWM/timer-channel or wake pins; no line clashes. Decoupling per added supply pin: 0.1u each + 1u VDDA (CL10B105KA8NNNC, JLC C29936). - Remote: now in its own folder hardware/Cow_Remote_007 (006 restored to released state, product.yml lists 007 prototype). Commits 0a23c1a (C25-C27), 5a6d21a (folder + C28 1u). PCB file there is still the 006 layout. - Robot: hardware/Robot-Cow-004B edited in place (repo keeps only that folder). Commits 0b50eab (U4 swap, BOOT0 moved off SWDIO PA13 to PF3-BOOT0, C15/C17 moved out from under the bigger symbol, C20-C22), 540ba00 (C23 1u). Decide with owner whether rev 005 gets its own folder before PCB work. - Netcheck vs pre-swap: only planned pin moves + new caps. ERC 0 errors (warnings remote 232->235, robot 283->306: categories not yet diffed). - Overlaps: fast check 26 each, rendered 38 remote / 35 robot (SOP-021 wants 0): stacked +3.3V/GND symbols on MCU power pins, ref/value on pin names, "MCU" title on rail symbols. Fix before review. core.hooksPath not set / no .githooks in either repo, so the overlap hook never ran. - 2026-11-02 (later): both schematics rebuilt on the project template (owner request). Remote rev 007 bfc58db in hardware/Cow_Remote_007; robot rev 005 4bb0bdc in its own folder hardware/Robot_Cow_005 (004B restored to released; product.yml lists 005 prototype; this settles the folder question). Each is generated from sch_src.py (root overview + function sheets with notes, template title block, <board>.kicad_dru = JLCPCB rules because of USB-C). Proof: node-set equivalence against the pre-conversion schematic = EQUIVALENT (same parts/refs/footprints/fields; USB pair renamed USB_D+/USB_D-, unnamed nets named from their pin), ERC 0 errors, 0 rendered overlaps on every sheet. Library fields a part never had are left blank on purpose (library would have added e.g. an 0402 MPN to C10 and R3) -> BOM/library sync is a separate review. Symbols missing from the library live in <board>.kicad_sym. Tool: kicad-lib de2df37 scripting/schematic/sch_convert/ (also fixes sch_gen derived-symbol naming and makes the rendered checker skip DNP crosses). PCB files are the old layouts renamed to the project; footprints must be relinked by reference on the first update. - Owner feedback 2026-11-02: too many labels, not enough wires. The converted sheets connect every pin by stub + label (generator shortcut) and, to dodge local labels rendering over their stubs, ALL signal nets were forced to global labels (b.force_global in each sch_src.py). Fix before PCB: 1. In kicad-lib-mcu2/scripting/schematic/sch_convert/gen.py (place_sheet + emission): place each 2-3 pin part next to the pin it serves and draw wires with s.wire(...): decoupling caps on U1/U4 supply pins, pull-ups between rail and pin (R36/R39 on U6), LED->resistor series chains with one label at the MCU end, button->series R->filter C chains, regulator in/out caps, ferrite filter. Same-sheet nets: wires or local labels; global labels only for nets on more than one sheet (drop the force_global line in gen.py and fix the local-label stub overlap properly: check sch_gen.label justify/offset against the rendered check). 2. Keep the gates: sch_convert/convert.sh OLD CONFIG BOARD_DIR (equiv EQUIVALENT vs remote 5a6d21a hardware/Cow_Remote_007/Remote Cow.kicad_sch and robot 540ba00 hardware/Robot-Cow-004B/Robot Cow.kicad_sch), ERC 0 errors, sch_overlap_check.py --rendered 0 on every sheet, look at the PDF. 3. Configs: remote = sch_convert/example_cow_remote_007_cfg.py; robot = sch_convert/example_robot_cow_005_cfg.py (kicad-lib 15789c3). - PCB: not started. Neither board has pcb_place.json; both are already routed (remote 564, robot 612 segments) and kicad-pcb-from-netlist is documented for unrouted boards. Plan: run it on a copy with every footprint except U1/U4 (and robot J11) locked, diff non-MCU positions + segment count; on the remote rip all old tracks into U1 first (same footprint, every pin remapped, they would short). Then SOP-021 routing order. Owner's Claude weekly budget was at 92% on 2026-11-02; hook advises codex-worker for implementation. - Firmware: both ports incomplete (details below). New open item in both PORTING.md (20c3282 / 58909af): U0 nBOOT_SEL factory value may make the core ignore the PF3-BOOT0 pin; check RM0503/AN2606 before build, conflicts with "never OB_Configure on U0". - Open: generated sch_src.py defaults KICAD_LIB_REPO to ~/kicad-lib, which lacks the branch's sch_gen (show_value) -> crashes until kicad-lib mcu-second-source is merged; until then run with KICAD_LIB_REPO=~/engineering/worktrees/kicad-lib-mcu2. LCSC number for U073CCT6; ERP part (SOP-008) on owner OK; BOM/library field sync (C10, R3 etc.); merge kicad-lib branch so STM32U073CCT6 resolves (last ERC warning). - 2026-11-02 rewire done (codex-worker, reviewed): kicad-lib 10bd667 (gen.py clusters: series spine, shunts GND down/rails up, cap bank per rail; force_global only for local nets under a global label), remote 4c3aabe, robot bf17ab5. Gates on the real dirs: EQUIVALENT, ERC 0 errors (warnings = pre-existing footprint_link + U073 lib), 0 rendered overlaps, python3 sch_src.py regenerates byte-identical. Labels remote 195->139, robot 151->123. convert.sh no longer runs tidy/fieldfix (they moved generated fields back into overlaps). Still labels: connector pins to their series R (J5->R9..R12, robot J1/J6), 3-pin parts, remote Power soft-switch mesh. PDFs sent to owner for review. - Next action: owner review of the PDFs; if OK, optional second pass (wire connector pins straight to their series parts, hand-tune Power), then the PCB stage (copy-first trial, relink footprints by reference). - 2026-11-02 remote firmware agent result (commit 4509fdd, firmware/Cow_Remote_007_U073/, PORTING.md): port incomplete, U073 never compiled. Done: CubeU0 driver fetch script (pinned), linker 256K/40K, startup, system file, usbd_conf fork. G0 006 rebuilt byte-identical (SHA 0925ecc9…), host tests pass. Findings: 006 actually runs on HSI16 (keep 16 MHz on U0 → timing identical); I2C TIMINGR 0x00200105 may violate FM+ SCL-low (unverified); CubeU0 has no classic USB Device lib (reuse 006's); G0 code parks PA9/PA10/PA1/PA8/PB5/PF2 as analog — now LEDs/NRST on U0, must fix; LED_MID mask 0; BOOT pin PA14→PF3; U0 system memory 0x1FFF0000 (CMSIS), USB DFU unverified (AN2606); IDENTIFY proposal COW_REMOTE_V6.16.0-U0 (flash_cow_pair.py substring check needs update). Not started: main.h/main.c switches, pin header, hal_conf, it/msp, clocks+CRS, STOP mode, option bytes (plan: read-only on U0), build script, sizes. - 2026-11-02 robot firmware agent result (Cow_Robot_Board-mcu2, commits 6c94705 + baseline script, firmware/stm32/Robot_Cow_005_U073/PORTING.md): port not started in code, analysis only. G0 baseline (-Os): text 84044, data 788, bss 26016 → 26.8 KB static RAM, so 40K U073 likely fits (stack unmeasured; linker must use full 40K = SRAM1 32K + SRAM2 8K, ST template uses 32K). Rebuild with g0_baseline.sh <outdir> (sha e44982ac…). Findings: sharing code needs #ifdef BOARD_U073 in Robot_Cow_004 sources (released firmware → Engineering+Quality review, prove G0 bin hash unchanged); reuse G0's USB Device lib + new usbd_conf, enable CRS; config page 0x0803F800; never call OB_Configure on U0; IDENTIFY must be COW_ROBOT_U0_V<ver> (Flasher regex unanchored, "-U0" suffix would pass as G0) — Flasher/Universal_Tester/Configurator need lockstep update; Flasher also keys boards by DFU flash size and G0 RAM_END/config page → 256K board unknown to it.