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.
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user