-
Notifications
You must be signed in to change notification settings - Fork 0
Link de
English · Deutsch
Die beiden Platinen kommunizieren über CAN (Controller Area Network) mit 1 Mbit/s. Zuerst die Verkabelung, dann die Protokollreferenz.
| Bus | Classic CAN (kein CAN FD (Flexible Data Rate)), 1 Mbit/s, nur 29-Bit-Identifier |
| Panel | TWAI-Controller (Two-Wire Automotive Interface, der CAN-Controller des ESP32-S3) auf GPIO19 (RX) und GPIO20 (TX; GPIO: General-Purpose Input/Output), über den USB/CAN-Multiplexer der Platine (USB: Universal Serial Bus) |
| Koprozessor | XL2515 (MCP2515-kompatibel) an spi1: SCK GP10, MOSI GP11, MISO GP12, CS GP9, INT GP8; SPI-Takt 10 MHz (SPI: Serial Peripheral Interface) |
| Transceiver | SIT65HVD230 (3,3 V) auf dem Koprozessormodul |
| Abschluss | 120 Ω an beiden Enden |
| Quarz | der XL2515 braucht einen 16-MHz-Quarz; 8 MHz begrenzen den Controller auf 500 kbit/s |
Wer CAN wählt, verliert das native USB des Panels. GPIO19 und GPIO20 führen beides, und der Multiplexer FSUSB42UMX (CH422G EXIO5: 0 = USB, 1 = CAN) wählt eines aus. Die Konsole liegt deshalb auf UART0 (Universal Asynchronous Receiver-Transmitter), der zweiten USB-C-Buchse der Platine hinter der USB-UART-Bridge, mit USB-Serial-JTAG (der eingebauten USB-Seriell- und Debug-Bridge des ESP32-S3) als Zweitkonsole.
Kommen keine Frames durch: Den Link in Betrieb nehmen.
Der Koprozessor setzt nach 200 ms ohne Anfrage Failsafe-Werte; das Panel eskaliert nach 1 s ohne Antwort. Das Failsafe rastet ein. Zurückkehrender Verkehr stoppt den Stillezähler, hebt das Failsafe aber nicht auf; verlassen wird es durch das Schreiben von 0x5AFE in das Register CLEAR der Control-Page.
Ein CAN-Transmitter, der kein Acknowledge bekommt, wiederholt von sich aus und addiert je Versuch 8 auf seinen Transmit Error Counter. Bei 1 Mbit/s erreicht ein Frame, den niemand beantwortet, die Bus-off-Schwelle von 256 in etwa 4 ms — jeder Moment ohne zweiten Knoten am Bus nimmt den Controller des Panels also vom Bus: Koprozessor ohne Strom, nach einem Reset, oder lange genug mit abgeschalteten Interrupts.
Der TWAI-Controller (Two-Wire Automotive Interface) des ESP32-S3 kommt nicht
von selbst zurück. can_twai_recover() läuft am Identity-Poll, solange der
Link unten ist, einmal pro Sekunde: aus dem Zustand Bus off ruft es
twai_initiate_recovery(), wartet die 128 Bus-frei-Signale ab, die der
Controller im Zustand Recovering zählt, und startet ihn aus dem Zustand
Stopped wieder. Die Erholung dauert damit bis zu drei Polls, also rund 3 s.
Ohne sie ist der erste stille Moment am Bus endgültig und nur ein
Aus-und-Einschalten hilft.
Der Report, der bei liegendem Link alle 5 s ausgegeben wird, trägt die Zähler:
LINK ...
bus tx errors 0 rx errors 0 bus errors 0
Ein Transmit Error Counter, der auf 256 zuläuft, heißt, dass niemand die
Frames mit einem ACK (Acknowledge) bestätigt. Die Zeile endet auf -- BUS OFF, wenn das Panel bereits aufgehört hat zu senden. Steht dort statt der
Zähler the controller is not running, ist der CAN-Controller gar nicht erst
gestartet — das ist eine andere Diagnose als ein Bus ohne Fehler.
Pages mit bis zu 32 Sechzehn-Bit-Registern, gelesen und geschrieben in Fenstern. Der Koprozessor sendet nur als Antwort auf eine Anfrage. Protokollversion 4.0. Die Major-Version ist Register 0 der Page 0. Die Major ändert sich, wenn ein Register seine Bedeutung wechselt oder eine Page umnummeriert wird; die Minor, wenn eine Page oder ein Register am Ende hinzukommt, was ein älteres Panel ignorieren kann.
Ein Koprozessor, der eine andere Protokoll-Major meldet als das Panel, gilt
als abwesend: der Link bleibt unten, der Splash-Screen markiert den
Koprozessor-Schritt als fehlgeschlagen neben der gemeldeten Version, das
Panel protokolliert beide Majors und meldet protocol mismatch -- will not arm, und kein Write erreicht den Koprozessor. Seine Ausgänge bleiben aus,
und das Panel läuft wie ohne angeschlossenen Koprozessor. Panel und
Koprozessor auf verschiedenen Seiten eines Major-Sprungs werden deshalb
zusammen geflasht.
Ein 29-Bit-Extended-Identifier trägt die ganze Adresse; ein Read ist deshalb ein Frame ohne Nutzdaten.
| Bits | Feld | Breite | Werte |
|---|---|---|---|
| 28..26 | Priorität | 3 | 0 control, 1 normal, 2 bulk (reserviert); niedriger gewinnt die Arbitrierung |
| 25..22 | op | 4 | 1 READ, 2 WRITE, 3 DATA, 4 ACK (Acknowledge), 5 NACK (Negative Acknowledge) |
| 21..14 | page | 8 | Page Map unten |
| 13..6 | offset | 8 | erstes Register in diesem Frame |
| 5..0 | count | 6 | Register in diesem Frame, 0..32 |
Die Priorität folgt aus der Page: die Pages CONTROL, LIMITS und FAILSAFE und ihre Quittungen sind Klasse 0; alles andere ist Klasse 1.
Ein Frame trägt bis zu vier Register (8 Byte, Little-Endian). Jeder Frame trägt seinen eigenen Offset und Count; eine Antwort über mehr als vier Register besteht also aus mehreren unabhängigen Frames in beliebiger Reihenfolge, und ein verlorener Frame kostet einen Registerbereich. Der Host-Poller kennt das angefragte Fenster und ist fertig, sobald jedes Register eingetroffen ist; der Transport setzt nichts zusammen. In den Nutzdaten steckt keine CRC (Cyclic Redundancy Check, Prüfsumme); es gelten die 15-Bit-CRC, der Acknowledge-Slot und die Wiederholung von CAN.
Ein NACK trägt seinen Grund in Register 0:
| Wert | Grund |
|---|---|
| 1 | BAD_PAGE |
| 2 | BAD_RANGE: Offset + Count über das Ende der Page hinaus |
| 3 | READ_ONLY |
| 4 | BAD_VALUE |
| 5 | NOT_ARMED |
Ein Write gilt ganz oder gar nicht. Jedes Register eines Frames wird geprüft, bevor eines davon gespeichert wird; ein NACK lässt die Page also genau so, wie sie war: keines der bis zu vier Register eines Frames wird übernommen, und keine Nebenwirkung eines Registers läuft. Das Aufheben eines eingerasteten Failsafe ist eine solche Nebenwirkung.
| Page | Name | Zugriff | Register |
|---|---|---|---|
| 0x00 | IDENTITY | lesen | Protokoll major, Protokoll minor, Firmware major, minor, patch, Hardware-Revision, Capabilities-Bitmap |
| 0x01 | STATUS | lesen | Zustand (0 idle, 1 armed, 2 failsafe), Fault-Bitmap, Uptime in ms (zwei Register), angenommene Anfragen (zwei Register), Empfangsfehlerzähler des XL2515, Sendefehlerzähler des XL2515 |
| 0x10 | CONTROL | lesen, schreiben | ARM (ungleich null schärft), THROTTLE (0..10000, Hundertstel Prozent, und kommandiert jeden Kanal, den CHAN_CFG als Throttle führt), MOTOR_POLES, CLEAR (0x5AFE schreiben, um das Failsafe zu verlassen). Register 0 bis 2 sind der Frame, der scharfschaltet |
| 0x11 | LIMITS | deklariert, nicht bedient | |
| 0x12 | FAILSAFE | deklariert, nicht bedient | |
| 0x13 | CHANNELS | lesen, schreiben | ein Kommando je Ausgangskanal, 0..1000 des Kanalwegs; acht Kanäle |
| 0x20 | BENCH | lesen | Spannung (10 mV), Strom (10 mA), Leistung (W), Drehzahl (min⁻¹), Temperatur des ESC (Electronic Speed Controller, Motorregler) und des Motors (0,1 °C, vorzeichenbehaftet), Ladung (mAh), Energie (0,1 Wh), Minimalspannung, Maximalstrom, Maximalleistung, Maximaldrehzahl, Flags |
| 0x21 | reserviert | nicht vergeben; nicht wiederzuverwenden | |
| 0x22 | OUTPUTS | lesen, schreiben | je Slot: Treiber (0 keiner, 1 PWM (Pulsweitenmodulation), 2 PPM (Pulspositionsmodulation), 3 DShot, 4 bidirektionales DShot), Pin, erster Kanal und Kanalzahl in einem Register, Rate in Hz (kbit/s für beide DShot-Treiber); acht Slots zu vier Registern |
| 0x23 | CHAN_CFG | lesen, schreiben | je Kanal: Rolle (0 throttle, 1 surface), Slew (Spanne je Sekunde, 0 = sofort), minimaler und maximaler Puls in µs; acht Kanäle zu vier Registern |
| 0x24 | CATALOGUE | lesen | die eigenen Pins der Platine, je ein Register: GPIO-Nummer (General-Purpose Input/Output) in 6 Bit, die daneben aufgedruckte Pad-Nummer in 6, was ihn hält in 4 (0 frei, 1 Heartbeat, 2 CAN, 3 Flash, 4 Debug, 5 Sensor, 15 sonstiges); 32 Slots, und eine Pad-Nummer von 0 heißt, in diesem Slot ist kein Pin |
| 0x25 | SHAPE | lesen | wo diese Pads liegen: Umriss-Breite und -Höhe in 0,01 mm, die Ecke, an der Pad 1 sitzt, und die Pads in einer Reihe gepackt als (Ecke << 8) | je Reihe, das Raster in 0,01 mm und der Abstand von der Kante zur Mitte einer Pad-Reihe. Zwei Reihen auf einem Raster, nummeriert von Pad 1 weg entlang seiner Kante und zurück entlang der gegenüberliegenden. Alles null, wenn der Koprozessor keine Form für seine Platine hat — dann wird sie gelistet und nicht gezeichnet |
| 0x26 | ARTWORK | lesen | was ein Bild der Platine ist: Blöcke Nutzdaten (0, wenn der Koprozessor keines trägt), Breite und Höhe in Pixeln, Format (0 keines, 1 RGB565 mit dem niederwertigen Byte zuerst), Nutzdatenlänge in zwei Registern und eine CRC (zyklische Redundanzprüfung) über die gesamten Nutzdaten mit Startwert null |
| 0x27 | ART_DATA | lesen, schreiben | das Bild selbst: Register 0 schreiben, um den Block zu nennen, dann die Page lesen. Register 0 liest den gerade bedienten Block zurück, Register 1 bis 31 tragen 62 Bytes davon. Ein Block rückt beim Lesen nicht vor, eine verlorene Antwort wird also erneut angefordert statt übersprungen |
| 0x28 | PADS | lesen | die Pads, die keine Pins sind, je ein Register: die Pad-Nummer in 6 Bit, was es ist in 2 (0 kein Pad und die Liste endet, 1 Masse, 2 eine Versorgung, 3 keines von beiden) und die Spannung in 8 Bit zu Zehntelvolt. Null Volt bei einer Versorgung heißt, sie ist keine feste Spannung — das ist nicht dasselbe wie die 0 V einer Masse. 32 Slots, in Pad-Reihenfolge |
Fault-Bitmap: Bit 0 Link still, Bit 1 Überstrom, Bit 2 Übertemperatur, Bit 3 Stall, Bit 4 Heartbeat ausgeblieben, Bit 5 Protokollversion abweichend. Faults bleiben gesetzt, bis sie gelesen und gelöscht werden. Bit 0 setzt voraus, dass über den Link mindestens eine Anfrage gelaufen ist: der Koprozessor ist wach, bevor das Panel pollt, und das Warten auf die erste Anfrage ist keine Stille.
Capabilities-Bitmap: Bit 0 ESC-Ansteuerung, Bit 1 ESC-Telemetrie, Bit 2 Servo-PWM, Bit 3 Servo-Strommessung, Bit 4 Akkumessung, Bit 5 Empfängerbus, Bit 6 Vibrationssensor und Indeximpuls, Bit 7 Zellenmonitor, Bit 8 Programmierung. Das Panel leitet daraus die Marken im Menü ab.
BENCH-Flags: Bit 0 Spannung gültig, Bit 1 Strom gültig, Bit 2 Drehzahl gültig, Bit 3 Temperatur des ESC gültig, Bit 4 Temperatur des Motors gültig, Bit 7 simuliert. Die beiden Temperaturen haben getrennte Bits, weil sie aus verschiedenen Quellen kommen und eine davon meist gar nicht kommt: ein ESC meldet seine eigene Temperatur über die erweiterte DShot-Telemetrie und weiß nichts über den Motor, den er treibt. Bis Protokoll 3.0 galt Bit 3 für beide — deshalb ist diese Änderung ein Major. Ein Koprozessor ohne Mess-Frontend setzt Bit 7, und das Panel zeichnet SIMULATION über den Bildschirm.
MOTOR_POLES ist die Magnetzahl des geprüften Motors, gerade und zwischen 2 und
42, oder null: dann hat es niemand gesagt. Ein bidirektionaler DShot-ESC meldet
elektrische Perioden und weiß nicht, woran er angeschraubt ist; das ist also die
eine Zahl, die die Leitung tragen muss, damit der Coprozessor eine mechanische
Drehzahl melden kann. Bei null meldet er keine Drehzahl statt einer aus einer
Schätzung abgeleiteten. Das Panel sendet sie aus der Einstellung Motor poles,
sobald ein Coprozessor zu antworten beginnt, erneut bei jeder Änderung der
Einstellung und im Frame, der scharfschaltet, ob eine Änderung offen ist oder
nicht. Ein Schreibvorgang,
den niemand beantwortet, bleibt offen und geht beim nächsten 50-ms-Poll
erneut hinaus; einer, den der Coprozessor ablehnt, wird nicht wiederholt,
denn dieselbe einmal abgelehnte Anfrage wird jedes Mal abgelehnt, und er
wartet stattdessen auf die nächste Änderung oder die nächste
Link-up-Flanke. Der Schutz bei null greift für eine nie gesendete Zahl, nicht
für eine veraltete: jede Zahl, die die Einstellung zulässt, liegt im Bereich,
den die Page annimmt.
Der Coprozessor verweigert einen Pin, den er nicht treiben darf — die Safety-Leitung, die Pins des CAN-Controllers und jede Nummer über dem letzten GPIO des Bauteils. Ein verweigerter Slot bleibt ungebunden, während die Page weiterhin zurückliest, was gefordert wurde. DShot und die Output-Treiber hat den Rest.
Einträge in CHAN_CFG und OUTPUTS werden ganz geschrieben, vier Register auf einmal. Der Pulsbereich eines Kanals ist standardmäßig 1000..2000 µs; Endpunkte außerhalb von 500..2500 µs werden mit BAD_VALUE abgewiesen. Ein Kommando außerhalb seines Bereichs wird begrenzt. Zwei Slots auf einem Pin oder zwei Slots, die denselben Kanal ausgeben, werden abgewiesen. Über das Schärfen entscheidet der Koprozessor: ein Schreiben von ARM wird mit NOT_ARMED abgewiesen, solange der Link im Failsafe ist oder dem Heartbeat nicht vertraut wird.
Ein Schärfen vom Panel sind zwei Transaktionen. CLEAR geht zuerst und allein:
der Koprozessor prüft ARM gegen sein Failsafe, bevor er ein CLEAR aus
demselben Frame anwendet, also wird ein Frame mit beidem genau dann mit
NOT_ARMED abgewiesen, wenn das Clear nötig war. Danach gehen ARM, THROTTLE
und MOTOR_POLES als ein Frame mit drei Registern ab Offset 0, sodass der
Koprozessor den Lauf mit der Polzahl beginnt, die das Panel gesendet hat,
oder ihn nicht beginnt. Jeder Poll alle 50 ms danach schreibt ARM und
THROTTLE; eine während eines Laufs geänderte Polzahl geht beim nächsten Poll
in einem eigenen Write. Die Regeln der Page -- der Throttle-Bereich, die
Polzahl, die CLEAR-Magic, ARM im Failsafe abgewiesen, und dass eine
Ablehnung nichts speichert -- stehen in shared/link/link_control.c, unter
test_link_pages.
shared/can/can_timing.c berechnet die Segmentierung für den Takt jedes
Controllers und verlangt, dass die Bitrate exakt aufgeht. Beide Enden tasten
bei 75 % des Bits ab:
| Controller | Takt | Prescaler | Quanta je Bit | tseg1 | tseg2 | sjw |
|---|---|---|---|---|---|---|
| TWAI (ESP32-S3) | 80 MHz APB (Advanced Peripheral Bus) | 4 | 20 | 14 | 5 | 4 |
| XL2515 | 16-MHz-Quarz, intern halbiert | 1 | 8 | 5 | 2 | 2 |
Acht Quanta sind das Minimum für ein Bit. Deshalb braucht der XL2515 für
1 Mbit/s einen 16-MHz-Quarz, und deshalb liegt sein Sample Point fest bei
75 %; das TWAI-Timing ist passend dazu gewählt. test_can_timing hält beides
fest.
Ein Poll der Bench-Page ist ein Anfrage-Frame und vier Daten-Frames (13 Register). Bei 20 Hz sind das 1,55 % des Busses. Die Nutzlast von Classic CAN bei 1 Mbit/s mit 29-Bit-Identifiern und vollem Bit Stuffing liegt im ungünstigsten Fall bei etwa 52 kB/s; der erwartete Verkehr liegt bei 12 bis 30 kB/s.
Das Identifier-Layout wird Bit für Bit über den gesamten 29-Bit-Raum
geprüft; der Timing-Rechner ist an von Hand nachgerechnete Beispiele
gebunden; test_link_loopback lässt den Host-Poller gegen den
Device-Dispatcher laufen, über einen Bus, der Frames verwirft, verzögert und
umsortiert: geteilte Antworten in umgekehrter Reihenfolge, abgewiesene
Schreibzugriffe, verlorene Teilstücke, die eine Anfrage unbeantwortet lassen
statt halb beantwortet, und der Watchdog des Geräts, der auf einem stillen
Bus feuert.
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