Firmware, Bluetooth-Brücke und Agent-Skill für den KOSMOS-Proxi: einmal flashen, danach hört der Roboter über Bluetooth LE auf Textbefehle. Was die Befehle schickt, ist ihm egal — ein Skript, ein curl, oder ein KI-Agent, der aus "mach mal was Lustiges" eine Choreografie baut. firmware/ MakeCode-Projekt (TypeScript) und fertige .hex für V1 und V2 bridge/ BLE-Brücke und HTTP-API, einzige Abhängigkeit ist bleak agent/ Skill-Definition: Alltagssprache -> Befehle tools/ Quelltext aus .hex extrahieren, Musik-Tabellen prüfen docs/ Protokoll, Einrichtung, Hardware, Lizenzen Zwei Dinge, die sonst nirgends stehen und in docs/HARDWARE.md dokumentiert sind: die Pin-Belegung des Roboters ist nicht öffentlich, sie wurde aus den mitgelieferten .hex-Dateien rekonstruiert (tools/hex_source.py holt sie heraus). Und der Ton braucht zwingend eine ganzzahlige Frequenz sowie Pin P0 — sonst kracht der Lautsprecher, der Aufruf hängt und die Bluetooth- Verbindung stirbt. Am echten Roboter durchgetestet: Verbindung, Sensoren, Display, 41 Sekunden Musik am Stück, alle Bewegungsrichtungen, Musik und Fahren gleichzeitig, Tanzfiguren, Not-Stopp mitten in der Bewegung, Autostart nach Neustart. MIT-Lizenz. Die Hardware-Extension stammt von kaku111 (TobbieII) und die Notendaten aus pxt-microbit, beide ebenfalls MIT — siehe THIRD-PARTY-NOTICES.
169 lines
6.9 KiB
Markdown
169 lines
6.9 KiB
Markdown
# Proxi — Hardware
|
||
|
||
Wie der Roboter wirklich verdrahtet ist, und woher diese Angaben stammen.
|
||
|
||
## Herkunft
|
||
|
||
Kosmos dokumentiert die Pin-Belegung nirgends: die Anleitung richtet sich an
|
||
Kinder, programmiert wird ausschließlich mit den fertigen Blöcken von
|
||
[kosmos.de/proxi](https://kosmos.de/proxi). Die Angaben hier sind also nicht
|
||
abgeschrieben, sondern rekonstruiert.
|
||
|
||
Möglich ist das, weil MakeCode jedes Projekt komprimiert an die kompilierte
|
||
Firmware anhängt. Die `.hex`-Dateien der Kosmos-Beispielprogramme (Download
|
||
über [kosmos.de/proxi](https://kosmos.de/proxi)) enthalten damit ihren eigenen
|
||
Quelltext. Herausholen lässt er sich mit dem Werkzeug in diesem Repo:
|
||
|
||
```bash
|
||
python3 tools/hex_source.py 00_Funktionstest.hex -o ./quellen
|
||
```
|
||
|
||
Die interessante Datei darin ist `custom.ts`: die Kosmos-Extension mit allen
|
||
Hardware-Zugriffen. Sie liegt hier unverändert als
|
||
[`firmware/proxi.ts`](../firmware/proxi.ts) — wer wissen will,
|
||
wie sich eine Funktion in Grenzfällen verhält, liest am besten dort nach.
|
||
|
||
Sie ist eine eingedeutschte Fassung der MIT-lizenzierten Extension
|
||
[`kaku111/20190209`](https://github.com/kaku111/20190209) für den **Tobbie II**.
|
||
Proxi ist derselbe Roboter unter anderem Namen — Kosmos' eigenes Programm
|
||
`12_APP_Fernbedienung` hängt noch direkt an dieser Extension:
|
||
|
||
```json
|
||
"TobbieII": "github:kaku111/20190209#9c728847d1a08815275108ec42009211d57c2f0d"
|
||
```
|
||
|
||
Herkunft und Lizenzen im Detail: [LICENSES.md](LICENSES.md).
|
||
|
||
## Pin-Belegung
|
||
|
||
| Pin | Richtung | Funktion |
|
||
|---|---|---|
|
||
| **P13** | Ausgang | Laufmotor vorwärts |
|
||
| **P14** | Ausgang | Laufmotor rückwärts |
|
||
| **P15** | Ausgang | Drehmotor links (Oberkörper/Kopf) |
|
||
| **P16** | Ausgang | Drehmotor rechts |
|
||
| **P12** | Ausgang | IR-Sendediode (Messpuls) |
|
||
| **P1** | Analog-Eingang | IR-Empfänger links |
|
||
| **P2** | Analog-Eingang | IR-Empfänger rechts |
|
||
| **P8** | Digital-Eingang | Enable — wird vor jeder Bewegung geprüft |
|
||
| **P0** | Ausgang | Summer (Standard-Audiopin des micro:bit) |
|
||
|
||
### Motoren
|
||
|
||
Zwei Motoren, beide an einer H-Brücke mit **zwei digitalen Leitungen** —
|
||
eine je Drehrichtung:
|
||
|
||
```
|
||
P13=1, P14=0 -> vorwärts
|
||
P13=0, P14=1 -> rückwärts
|
||
P13=0, P14=0 -> aus
|
||
|
||
P15=1, P16=0 -> Drehung nach links
|
||
P15=0, P16=1 -> Drehung nach rechts
|
||
P15=0, P16=0 -> aus
|
||
```
|
||
|
||
**Es gibt keine Geschwindigkeitsregelung.** Kein PWM, kein Servo, keine
|
||
Zwischenstufen — ein Motor läuft oder er läuft nicht. Gesteuert wird
|
||
ausschließlich über die Dauer, deshalb hat kein Befehl im
|
||
[Protokoll](PROTOCOL.md) einen Speed-Parameter.
|
||
|
||
Der Laufmotor bewegt die Beine, der Drehmotor den Oberkörper. Laufen beide
|
||
gleichzeitig, geht Proxi eine Kurve.
|
||
|
||
### IR-Sensoren
|
||
|
||
Gemessen wird als Differenz, damit Umgebungslicht herausfällt:
|
||
|
||
1. Empfänger analog lesen (Grundhelligkeit)
|
||
2. Sendediode P12 einschalten
|
||
3. 250 µs warten
|
||
4. Empfänger erneut lesen
|
||
5. Sendediode aus — Messwert ist die Differenz beider Messungen
|
||
|
||
Hoher Wert = Hindernis nah. Am Gerät gemessen: freie Sicht 5-15, Hand in etwa
|
||
10 cm 200-600, Hand direkt davor bis ~980. Beide Seiten erreichen den vollen
|
||
Bereich. Die Schwellen 400-600 aus Kosmos' eigenen Programmen entsprechen damit
|
||
ungefähr einer Handbreit Abstand.
|
||
|
||
### Helligkeitssensor: durch die Scheibe blockiert
|
||
|
||
Den gibt es hier nicht, und zwar aus einem Grund, den keine Software behebt.
|
||
|
||
`input.lightLevel()` misst über die LED-Matrix — und die sitzt bei Proxi
|
||
hinter einer **getönten Scheibe**. Nimmt man die weg, misst der Sensor
|
||
einwandfrei. Eingebaut liefert er konstant 0, auch mit einer Taschenlampe
|
||
direkt davor.
|
||
|
||
Deshalb kennt das Protokoll kein `SENSOR:LIGHT`. Wer den Sensor braucht, muss
|
||
an der Mechanik ansetzen, nicht am Code.
|
||
|
||
Die 0 sah lange nach einem Softwarefehler aus: Kosmos' eigenes Programm
|
||
`04_Licht-Tracker` benutzt denselben Sensor erfolgreich (mit Schwellen von 1
|
||
bis 10 — die Werte sind klein). Widerlegt wurde die Softwarespur erst, als
|
||
jemand die Scheibe abgenommen hat.
|
||
|
||
### P8
|
||
|
||
`custom.ts` prüft `P8 == 1` vor jeder Motorbewegung, beim Abbremsen der Drehung
|
||
und bei der rechten IR-Auswertung. Was genau daran hängt, ist nicht
|
||
dokumentiert — plausibel ist der Batterieschalter beziehungsweise eine
|
||
Power-Good-Leitung, denn der micro:bit läuft auch dann weiter, wenn Proxis
|
||
Schalter auf OFF steht und nur USB-Strom anliegt.
|
||
|
||
Diese Firmware rät nicht daran herum: alle Motorzugriffe laufen über die
|
||
unveränderten Extension-Funktionen, und `SENSOR:PWR` gibt den Rohwert von P8
|
||
zurück. **Reagiert Proxi auf Fahrbefehle mit `OK`, bewegt sich aber nicht,
|
||
lohnt zuerst ein Blick auf `SENSOR:PWR`** — steht da `0`, ist der Schalter aus.
|
||
|
||
## micro:bit V1 oder V2
|
||
|
||
Die Firmware wird als **Universal Hex** gebaut und läuft auf beiden.
|
||
|
||
Knapp ist es beim V1 trotzdem: der Bluetooth-Stack frisst dort den Großteil des
|
||
Flash. Erste Fassungen dieser Firmware passten nicht hinein — Platz geschaffen
|
||
hat erst der Verzicht auf den eingebauten Melodie-Player von MakeCode (siehe
|
||
`playMelodyBuffer` in [`main.ts`](../firmware/main.ts), der Grund dafür
|
||
war allerdings ein anderer). Wer die Firmware erweitert, sollte die V1-Variante
|
||
im Blick behalten: `pxt build` bricht ab, sobald sie nicht mehr passt.
|
||
|
||
V2 erkennt man am goldenen Logo-Taster oben mittig und dem Mikrofon oben rechts.
|
||
|
||
## Ton: keine Kommazahlen
|
||
|
||
Die Frequenz für `music.playTone()` **muss** eine Ganzzahl sein.
|
||
|
||
Sie wurde hier anfangs mit `Math.pow()` gerechnet. Der Wert war korrekt — eine
|
||
Diagnoseabfrage lieferte für MIDI 79 sauber 784 —, kam als Kommazahl im
|
||
Tonausgang aber falsch an. Der micro:bit machte daraus eine unsinnige
|
||
Schwingungsdauer, krachte laut, blieb hängen und bediente den Funk nicht mehr;
|
||
nach ein paar Sekunden starb die BLE-Verbindung an `Connection Timeout (0x08)`.
|
||
|
||
Ein Fehler, drei Symptome, die wie drei verschiedene Probleme aussahen. Gefunden
|
||
wurde er durch den direkten Vergleich zweier Aufrufe, die sich nur in diesem
|
||
einen Punkt unterschieden:
|
||
|
||
```
|
||
gerechnete 784 Hz -> Krachen, hängt, Verbindung weg
|
||
übergebene 784 -> sauberer Ton
|
||
```
|
||
|
||
`midiToFreq()` in `main.ts` rechnet deshalb rein ganzzahlig über eine Tabelle.
|
||
`tools/check_melodies.py` prüft das bei jedem Build mit.
|
||
|
||
Zwei Dinge, die dabei **nicht** die Ursache waren, obwohl sie lange danach
|
||
aussahen: der eingebaute Melodie-Player von MakeCode und der interne
|
||
Lautsprecher des micro:bit V2. Beides wurde gegengeprüft und entlastet.
|
||
|
||
## Nicht vorhanden
|
||
|
||
Damit niemand erneut danach sucht — Proxi hat **keine** Touch-Sensoren, **keinen**
|
||
Servo und **keine** regelbaren Motoren. Früher lagen in diesem Repo
|
||
`Source/*.py`-Dateien, die genau das behaupteten. Sie waren KI-generiert und
|
||
frei erfunden; ihre Pin-Belegung (P0–P3 als PWM-Motoren, P4/P10 als IR, P6/P7 als
|
||
Touch, P8 als Servo) stimmt an keiner Stelle mit der Hardware überein. Sie sind
|
||
durch die echten, aus den `.hex`-Dateien extrahierten Quellen ersetzt.
|
||
|
||
Nebenbei: MicroPython auf dem micro:bit hat überhaupt kein Bluetooth. Wer BLE
|
||
will, muss über MakeCode gehen — daher TypeScript statt Python.
|