Files
christian 3905647b7f Proxi AI — Spielzeug-Roboter mit natürlicher Sprache steuern
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.
2026-08-22 11:41:00 +00:00

169 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (P0P3 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.