-
Notifications
You must be signed in to change notification settings - Fork 0
FirstRun
English · Deutsch
Both boards powered with the heartbeat wire fitted, and every number below read on an instrument. Written for 0.8.1. A servo and a motor have run from the panel on the bring-up bench; what nothing here has done is put a scope or an analyser on a pin, so every step says what "good" looks like and what to write down when it is not.
Work down the list. Each step assumes the one above it passed.
A slide switch beside the BOOT and RESET buttons is marked
UART1andUART2. It selects what the bridged USB-C socket's serial side is connected to, and the console needs it onUART1.On the other setting the socket still enumerates: a COM port appears and the operating system names the CH343. Nothing crosses it in either direction — no console output and no flashing — which is the same symptom a broken cable or a broken board gives.
The panel's other USB-C socket carries native USB on GPIO19 and GPIO20, which the multiplexer hands to CAN about a second into every boot. It flashes the board and it cannot watch a running one. The bridged socket is the panel's only console while the bench runs.
Have to hand: an oscilloscope, one servo, one ESC that speaks bidirectional DShot, a bench supply with current limit, and the USB cable for each board.
Do not connect a motor to the ESC yet. Step 5 drives no pin at all -- it is the interlock, and no output is the passing result. Step 6 is the first pin on an instrument, and the first thing to look at there is the scope, not a propeller.
Current limit: set it low enough that a shorted output trips it rather than burning a track.
# coprocessor — produces rcbench-iomcu.uf2, copy it while holding BOOTSEL
cmake -S firmware/iomcu -B firmware/iomcu/build
cmake --build firmware/iomcu/build
# panel
idf.py -C firmware/panel set-target esp32s3
idf.py -C firmware/panel build
idf.py -C firmware/panel -p /dev/ttyACM0 flash monitorThe coprocessor build prints its own size check:
-- rcbench: image 272040 bytes, 6% of the 4186112 bytes a four-megabyte
module leaves below the store
Watch for: the module used for bring-up is a Waveshare RP2350-CAN with
4 MB, while PICO_BOARD defaults to a board file claiming 16 MB. The
linker measures against 16 MB and will not warn. The line above is the only
thing that will, so read it.
The panel's partition table changed. It now carries a 2 MB boardart
partition. If the panel was flashed before that, flash the merged image at
offset 0 rather than only the app:
idf.py -C firmware/panel merge-bin -o rcbench-panel-merged.bin
esptool.py -p /dev/ttyACM0 write_flash 0x0 firmware/panel/build/rcbench-panel-merged.binThe panel runs the CAN echo self-test itself, at every start-up, for 1200 ms inside the splash. It answers one question: do frames cross the bus intact? It uses no page protocol, so if it passes and the link still does not work, the fault is above the wire.
Good looks like nothing: the splash shows LINK OK CAN 1 Mbit/s and
hands over to the menu.
A failure is a screen, before the menu, with the verdict, what to check in order, and both ends' counters. It takes a two-second hold to leave. Bringing up the link has the verdicts and what each one means.
Do not go on until it passes. Every step below assumes frames cross.
The console carries the detail if you want it — the UART socket, not native USB, because GPIO19 and GPIO20 carry both and the multiplexer selects one:
I (…) rcbench: CAN self-test: every probe came back intact
I (…) rcbench: sent 2024 echoed 2024 corrupt 0 lost 0 stale 0
| Panel end | GPIO6, on J8 (a three-pin header carrying 3V3, GND, GPIO6) |
| Coprocessor end | GP3 |
| Through | the retriggerable monostable, once one exists. It is on no board, so the bring-up bench runs a direct wire and has no hardware backstop. The wire covers a panel that stops beating while the coprocessor is healthy: it disarms after 150 ms of silence. What is uncovered is a panel that stops beating while the coprocessor cannot act -- nothing then removes the outputs, and that is what the monostable would do without any firmware |
Without this wire the coprocessor refuses every arm, and that is the interlock working, not a fault.
Numbers it is judged against:
| Edge period | 20 ms |
| Gap accepted | 4 ms to 150 ms |
| Edges before it counts as alive | 4 |
So the line must be edging for roughly 80 ms before an arm can succeed.
On the scope, at GP3: a square wave, edge to edge 20 ms. If the gap ever exceeds 150 ms the coprocessor drops it and the next arm is refused.
Where the edges come from: the panel's control task, inside its poll loop. Anything that stalls that task stops the heartbeat — which is why nothing long is allowed to run there.
This is new and will happen on your first ever link-up. The coprocessor now carries a 201 kB photograph of itself, and the panel fetches it once and keeps it in flash.
On the panel console, in this order:
I (…) rcbench: coprocessor answered
I (…) rcbench: hardware 1 says where its pads are
I (…) rcbench: hardware 1 says which pads are grounds and rails
I (…) rcbench: fetching hardware 1's photograph: 500 x 206, 206000 bytes
…
I (…) rcbench: hardware 1's photograph kept
What to expect while it runs:
- Extra CAN traffic for tens of seconds. It takes 15 ms of each 50 ms poll, so it is slower in wall clock than the bus alone would need.
- A visible display stall when it finishes and writes to flash. A flash operation closes the cache the panel's bounce-buffer refill reads PSRAM through, so the panel stops for the length of the write. Settings saves already do this.
- It must not disturb the heartbeat. The transfer is sliced and the flash write runs on its own task for exactly that reason. If the heartbeat drops during this minute, stop and write it down — that is the most important thing this first run can find, and it is code that has never run.
On the second link-up the photograph is already kept and none of this happens. If you want to skip it entirely, a coprocessor built with the artwork removed reports zero blocks and the panel draws the board from its outline instead.
Nothing is wired to an output yet. This step tests the interlock, not a pin.
-
Heartbeat wire removed → arming must be refused. The coprocessor
answers
NOT_ARMEDbecause!beat.alive. The panel shows the refusal. - Heartbeat wire fitted, panel armed → the coprocessor accepts.
- Pull the heartbeat wire while armed → it must fail safe within 150 ms.
- Press STOP → latches. It must take an explicit arm to leave, not a link that recovers.
- Pull the CAN wire while armed → the coprocessor gives up after 200 ms; the panel escalates after 1 s.
- Cover the touch panel / let touch die → after 500 ms of silence arming is blocked.
Every one of these is host-tested. None of the numbers below has been seen on an instrument. A servo and a motor have since been run from the panel on a bring-up bench, so a pin does drive; what no scope or analyser has read is any pulse width, frame period or reply delay in this tree.
Use a servo, not the ESC. A servo is the forgiving case and the one the scope reads most easily.
Pins free for an output: GP0, GP1, GP2, GP4, GP5, GP6, GP7, GP13, GP14,
GP15 and up.
Reserved and refused: GP3 (heartbeat), GP8–GP12 (CAN).
Refused as a second PWM pin: a pin whose PWM compare register is already
taken by a bound pin. On the RP2350 the slice is (pin / 2) modulo 8 below
GP32 and the channel is the pin's low bit, so GP0 and GP16, GP1 and GP17, GP2
and GP18, GP4 and GP20, GP5 and GP21, GP6 and GP22 are pairs that share one
compare register. The second of a pair is refused rather than muxed onto the
first one's pulse width. The OUTPUTS page carries no bit saying "bound", so
the screen goes on looking configured while the lead produces no pulse.
On the panel: Setup → OUTPUTS, choose SERVO PWM, tick one pin. Or
Setup → PICK A PIN for the board picture — grounds are marked G, rails
carry their voltage.
Scope the pin before connecting the servo.
| Frame rate | 40 to 400 Hz (50 Hz by default) |
| Pulse | 500 to 2500 µs, refused outside |
| Resolution | 1 µs |
Measure and record: the actual frame period, the pulse at both ends of travel, and the jitter. Bit timings are the largest unverified surface in the tree.
Then: confirm the servo screen lets go when it is told to, and only
then. Lifting the finger does not stop the output: the screen holds the
position it was given and says it again every 100 ms (SERVO_HOLD_MS),
against the coprocessor's 500 ms (OUT_DEFAULT_TIMEOUT_MS), so a servo
stays where it was put. RELEASE returns the surfaces to centre; it does
not clear the slot and the pin keeps pulsing. What stops the edges is a
disarm, a STOP, or leaving the screen, which disarms. Check on the scope that
RELEASE moves the pulse to the middle of the channel's travel and that a
disarm is what stops it.
A channel nobody is refreshing does still go to rest after 500 ms, which is what happens to a bound pin the servo screen is not holding.
Written from the specification, exercised only against frames the same code builds. Record real values for each:
- Every DShot bit timing, against an ESC's tolerance rather than the spec.
- The reply rate of five quarters of the DShot rate.
- The leading-bit convention of the group code.
- The turnaround delay — whether 30 µs is what an ESC actually waits.
- The extended-telemetry frame types and their units.
- The PPM DMA ring playing a frame.
- The flash erase window on the coprocessor, and whether the heartbeat re-acquires across a save.
| Symptom | Look here first |
|---|---|
| Arm refused, wire fitted | Heartbeat not edging 4 times yet, or gap over 150 ms. Scope GP3. |
| Arm refused, no obvious reason | Touch dead for 500 ms blocks it. Touch the panel. |
| Link up, screen offers no pins | The board's catalogue did not arrive. Console says which page failed. |
| Heartbeat drops in the first minute | The artwork transfer or the flash keeper. Newest code, never run. See §4. |
| Display freezes briefly | A flash write. Expected once, when the photograph is kept. |
| Coprocessor does not boot after flashing | Image past 4 MB. Check the size line from §1. |
Panel boots but no boardart partition |
Flashed app-only over an old table. Merge-bin at offset 0. |
| Output goes to mid-travel after ½ s | Working as intended — nothing wrote to that channel, so it went to its rest: mid-travel for a servo, zero for a motor. The pulses continue while the bench is armed |
| Pulses stop altogether | Not the timeout. Something released the pin, disarmed, or stopped the bench |
If the bench misbehaves in a way that points at the panel, the three newest and least proven things are all mine and all only compiler-checked:
- the flash keeper task (
artkeep), - the artwork slice inside the control task's poll loop, and
- the run log task (
runlog), which owns every write to the SD (Secure Digital) card.
The first two are inert on a coprocessor that reports no photograph, which is
the quickest way to rule them out. The third is inert with no card in the
slot. With a card it appends a line to RCBENCH.LOG whenever a fault is
raised, armed or not; the run file is what waits for an arm, and for the
first row after it.
For each step: what was measured, against what it was expected to be, and
what the scope showed. STATUS.md carries an "Open items" table — the rows
about drivers on hardware, the control page and the flash store are the ones
this run answers.
Anything that is not measured stays written as not measured. A number guessed into that table is worse than an empty cell.
rcbench
English
Using the bench
- What this is for
- Building
- Bringing up the link
- First run on hardware
- Screens
- Balancing
- Servo procedures
- Receiver buses
- Safety
- BLHeli_32 parameters
Reference
Deutsch
Den Prüfstand benutzen
- Worum es geht
- Bauen
- Den Link in Betrieb nehmen
- Erster Lauf auf der Hardware
- Bildschirme
- Auswuchten
- Servoverfahren
- Empfängerbusse
- Sicherheit
- BLHeli_32-Parameter
Referenz