HumusBeta

Boards & Sensoren

Ein Mikrocontroller-Board am USB-Kabel macht aus jedem Sensor einen Regler und aus jedem Bedienelement in Humus einen Schalter, einen Dimmer oder eine Farbe. Es gibt zwei Wege, mit einem Board zu sprechen, und diese Seite geht beide mit einem Arduino Uno durch:

  • Board, ein Organism, das keinen Code auf dem Board braucht. Spiel einmal den Standard-Firmata-Sketch auf, und seine Pins gehören dir.
  • SerialIn und SerialOut, für einen eigenen Sketch. Der Sketch schreibt und liest Klartext oder Bytes, und die beiden Boxen sprechen, was immer der Sketch festgelegt hat: Der Sketch ist das Protokoll.

Was du brauchst

  • Ein Board mit serieller USB-Verbindung. Die Beispiele nutzen einen Arduino Uno: sechs analoge Eingänge (A0 bis A5) und die eingebaute LED an Pin 13. Ein Nano, ein Leonardo, ein Mega, ein ESP32-Entwicklungsboard oder ein Raspberry Pi Pico funktionieren genauso, und das Board-Organism hat für jedes ein Preset.
  • Die Arduino IDE, oder welchen Editor dein Board auch nutzt, um den Sketch aufzuspielen.
  • Einen Sensor mit analogem Ausgang für die erste Geschichte: Ein Potentiometer ist am einfachsten, ein Thermistor oder ein analoger Temperatursensor ist der aus der Geschichte. Eine LED und einen 220-Ohm-Widerstand für die zweite Geschichte, oder einfach die eingebaute LED an Pin 13. Einen adressierbaren Ring mit 24 LEDs für die letzten drei.

Jedes Patch und jeder Sketch auf dieser Seite liegt in Humus unter Datei > Beispiele > Organisms, ein Ordner pro Szenario: Board enthält die beiden Firmata-Geschichten, SerialIn und SerialOut die eigenen Sketches, der Ordner NeoPixel den Ring. Derselbe Baum ist der Ordner examples/ im Quellcode, also liegt der Sketch zum Aufspielen neben dem Patch, das ihn steuert, in einem Ordner mit seinem eigenen Namen, wie es der Editor des Boards erwartet.

Unter Linux gehört der Port der Gruppe dialout; füge dich mit sudo usermod -aG dialout $USER hinzu und melde dich neu an. Unter macOS und Windows ist der Port bereit, sobald das Board eingesteckt ist. Egal welchen Weg du gehst: Schließ nach dem Aufspielen den seriellen Monitor der IDE, denn nur ein Programm kann den Port belegen.

Kein Code auf dem Board: Firmata

Das Board-Organism spricht Firmata, ein offenes Protokoll, für das die Arduino IDE einen Sketch mitliefert. Du spielst ihn einmal auf und öffnest die IDE nie wieder:

  1. Öffne die Arduino IDE, steck das Board ein und wähle unter Werkzeuge das Board und seinen Port.
  2. Datei ▸ Beispiele ▸ Firmata ▸ StandardFirmata, dann Hochladen.

Erste Geschichte: Ein Temperatursensor spielt einen Filter

Verbinde den Ausgang des Sensors mit A0, seine Versorgung mit 5V (oder 3.3V, je nachdem, was der Sensor braucht) und seine Masse mit GND. Ein Potentiometer kommt zwischen 5V und GND, mit dem Schleifer an A0.

Öffne in Humus Beispiele > Organisms > Board > Sensor, oder bau es selbst:

  1. Füge ein Board aus der Kategorie Grundbausteine hinzu und wähle Arduino Uno / Nano aus seinen Presets. Sein Menü Port zeigt Auto, und das passt, wenn nur ein Board eingesteckt ist. Die Pegelanzeige der Box fängt ein paar Sekunden nach dem Öffnen des Patches an zu flackern: Das Board startet neu, wenn der Port geöffnet wird, und meldet sich dann.
  2. Füge ein Number hinzu und zieh den Ausgang out1 (A0) von Board auf die Buchse des Numbers. Das Number zeigt den Sensor jetzt live: Wärm den Sensor an oder dreh am Poti und sieh zu, wie sich der Wert bewegt. Das ist die Zahlenbox aus der Patching-Tradition, die Stelle, an der du einen Steuerwert abliest.
  3. Füge ein TestGen, einen Filter und ein SoundOut hinzu. Verbinde die beiden Ausgänge von TestGen mit den beiden Eingängen des Filters und den Filter mit SoundOut.
  4. Klick mit rechts auf den Regler Frequency des Filters, wähle Steuern mit ▸ Number ▸ value und stell den Bereich auf 200..8000. Diesmal kein Kabel: Der Messwert, den du beobachtest, öffnet jetzt den Filter, während er steigt, und dasselbe Number kann jeden anderen Regler genauso steuern.

Jeder Parameter in Humus lässt sich so steuern, und jede Buchse nimmt ein Steuerkabel an. Ein Sensor, der am Ausgang 0..1 liefert, ist am einfachsten zu routen; skalier ihn im Bereich der Route, oder mit einem Slider oder Math dazwischen, wenn er eine Kurve braucht.

Jeder Ausgang liest den analogen Kanal, der daneben eingestellt ist, also ist A8 an einem Mega nur eine Zahl entfernt, und Outlets legt fest, wie viele die Box zeigt. Messwerte kommen standardmäßig alle 19 ms an (Read every).

Zweite Geschichte: Die Musik lässt eine LED leuchten

Nimm die eingebaute LED an Pin 13, oder verdrahte für die Dimm-Hälfte eine LED mit einem 220-Ohm-Widerstand von Pin 11 nach GND.

Öffne Beispiele > Organisms > Board > LED, oder bau es selbst:

  1. Füge ein SoundIn und einen Follower hinzu; verbinde den Ausgang von SoundIn mit dem Follower. Stell Threshold am Follower so ein, dass sein Gate bei jedem Anschlag aufgeht, egal was du ins Mikrofon spielst.
  2. Füge ein Board mit dem Uno-Preset hinzu. Zieh den Ausgang gate des Followers auf Buchse 1 von Board. Buchse 1 steuert Pin 1, der im Modus Digital auf 13 steht: Die LED leuchtet bei jedem Anschlag.
  3. Zieh den Ausgang env des Followers auf Buchse 2. Buchse 2 steuert Pin 11 im Modus PWM, und die zweite LED atmet mit dem Pegel.

Alles, was einen Steuerwert trägt, kann einen Pin steuern: ein Button für ein Relais, ein LFO für sanftes Ein- und Ausblenden, ein Slider für eine Hand am Dimmer. Der Modus Digital schaltet bei 0.5; PWM bildet 0..1 auf das Tastverhältnis des Pins ab, und nur die PWM-Pins können dimmen (3, 5, 6, 9, 10 und 11 beim Uno).

Dein eigener Sketch: SerialIn und SerialOut

Wenn das Board etwas tun soll, das StandardFirmata nicht kann - einen digitalen Sensor über I2C lesen, einen adressierbaren LED-Ring ansteuern, ein Tastenfeld entprellen -, schreib den Sketch selbst und sprich mit Humus in Klartext oder Bytes. Keine Bibliothek von uns, kein Protokoll, das du lernen musst: Der Sketch ist das Protokoll, und die SerialOut-Box zeigt genau die Bytes, die über die Leitung gehen.

HumusBoard.ino ist der Start-Sketch, im Ordner HumusBoard unter SerialIn und unter SerialOut, und er kann beide Richtungen: Alle 30 ms gibt er A0 und A1 als eine Zeile aus, 0.512 0.087, und sobald eine Zeile ankommt, schaltet er Pin 13 mit der ersten Zahl und dimmt Pin 11 mit der zweiten. Spiel ihn genauso auf wie oben.

Zuerst der Selbsttest

Prüf die Verbindung, bevor du irgendetwas verdrahtest. Spiel SerialTest.ino aus Organisms > SerialIn > SerialTest auf und öffne das Patch daneben. Der Sketch gibt zwanzigmal pro Sekunde drei Zahlen aus: eine Rampe, die einmal pro Sekunde von 0 auf 1 steigt, das, was er zuletzt von Humus gehört hat, und A0. Ein SerialIn legt sie auf drei Numbers. Bewegt sich die Rampe, spricht das Board mit dem Port und die Baudrate stimmt; folgt das Echo dem LFO an der ersten Buchse von SerialOut, wird Humus gehört und das Format passt; der Button an der zweiten Buchse lässt die eingebaute LED des Boards leuchten, das Einzige, was am Board selbst zu sehen ist. Steht die Rampe still, prüf Port und Baudrate; steht nur das Echo still, prüf das Format.

Dieselben zwei Geschichten, über den Sketch

serial-sensor.hum ist die erste Geschichte über den Sketch: Ein SerialIn liest die Zeile, die der Sketch ausgibt, sein Ausgang a landet auf einem Number, und der Wert des Numbers öffnet den Filter über eine Steuern-mit-Route. Das Menü Port zeigt Auto, und die Baudrate ist 115200, mit der der Sketch den Port öffnet. Die Anzeige in der Box bewegt sich kurz nach dem Öffnen des Patches.

serial-led.hum ist die zweite Geschichte: der Ausgang gate des Followers an Buchse 1 von SerialOut und sein Ausgang env an Buchse 2, dreißigmal pro Sekunde als Standardzeile %1 %2\n gesendet; der Sketch schaltet Pin 13 und dimmt Pin 11.

Dritte Geschichte: ein Pixel-Ring, auf drei Arten

Der Ring zeigt ein eigenes Protokoll. NeoPixel.ino unter Organisms > SerialOut > NeoPixel steuert einen adressierbaren Ring mit 24 LEDs an Pin 6 und liest einen Befehl pro Zeile, jede Zahl 0..1 außer der Pixelzahl: P i r g b färbt ein Pixel, F n r g b lässt die ersten n leuchten und schaltet den Rest dunkel, A r g b färbt alle, H h s v färbt alle nach Farbton, B v stellt die Helligkeit ein. Verbinde den Datenpin des Rings mit 6, seine Versorgung mit 5V und seine Masse mit GND, spiel den Sketch auf und öffne eines der drei Patches daneben.

paint.hum ist das einfache: vier Slider an vier Buchsen von SerialOut, das Format P %1 %2 %3 %4\n, Send auf On change. Die erste Buchse hat Scale 23 und Int an, also wählt ein 0..1-Slider ein Pixel nach Nummer; die anderen bestimmen, wie viel Rot, Grün und Blau. Beweg einen Slider, und das Pixel folgt.

vu-meter.hum berechnet die ganze Nachricht aus einem Wert. env des Followers liegt an Buchse 1, und das Format lautet F %(floor(v1*24+0.5)) %(v1) %(1-v1) 0\n: Der Pegel bestimmt, wie viele Pixel leuchten, und die Farbe geht von Grün in Ruhe bis Rot bei Vollaussteuerung, dreißig Zeilen pro Sekunde. Hier rechnet die Nachrichtenbox, und der Sketch bleibt dumm.

spectrum.hum ist das Pd-Patch, das Frequenz auf Farbe abbildet, nachgebaut: Ein Crossover mit drei Bändern teilt das Mikrofon auf, ein Follower pro Band liest dessen Pegel, und die drei env-Ausgänge landen auf drei Buchsen, gesendet als A %1 %2 %3\n: Bass als Rot, Mitten als Grün, Höhen als Blau, auf dem ganzen Ring. Verschieb die beiden Frequenzen des Crossovers, um festzulegen, was als Bass zählt und was als Luft. Tausch die Quellen der Follower gegen LFOs, und der Ring treibt von selbst dahin; setz einen Slider zwischen einen Follower und seine Buchse, um ein Band zu zähmen. Jedes der drei Patches könnte auch H %1 1 %2\n senden, mit einem Farbton an Buchse 1 und einem Pegel an Buchse 2, und der Sketch würde das Farbrad übernehmen.

Die beiden Boxen

Von Humus zum Board. Ein SerialOut zeigt so viele Wert-Buchsen, wie sein Feld Values angibt, anfangs zwei und bis zu acht, dazu eine Trigger-Buchse im Modus On trigger, und hat ein Feld Format. %1 bis %8 geben die Werte aus, \n beendet eine Zeile, \t ist ein Tab, \xNN ist ein rohes Byte. Jeder Wert hat ein Scale und einen Schalter Int, also verlässt ein 0..1-Steuerwert die Box mit zwei Klicks als 0..255, und eine Buchse, auf die nichts gezogen ist, sendet die Zahl, die in ihrem Feld steht. Send legt fest, wann: Continuous mit der eingestellten Rate, On change, damit ein Befehl einmal rausgeht, oder On trigger, wenn die Trigger-Buchse ansteigt, was aus einem Button eine Befehlsbox macht.

Mehrere Befehle in einer Box. Schreib eine Nachricht pro Zeile ins Feld Format, und eine Buchse Message erscheint: Die Zahl darauf wählt die Zeile, also wählt ein Number oder ein Slider zwischen home, M %1 und stop, und ein Button an der Trigger-Buchse sendet die gewählte.

Vom Board zu Humus. Ein SerialIn hat bis zu acht Ausgänge, a bis h: Die erste Zahl jeder Zeile landet auf a, die zweite auf b und so weiter. Ein Sketch, der seine eigene Form ausgibt, bekommt eine Vorlage in Parse, das Spiegelbild von Format: T=%1;L=%2 liest T=23.5;L=0.4, und eine Zeile, die nicht passt, wird ignoriert. Ist eine Vorlage gesetzt, feuert ein Ausgang match, sobald eine Zeile passt, also wird ein Sketch, der pressed ausgibt, zu einem Button-Druck. Die Anzeige in der Box zeigt, was angekommen ist. Skalier auf dem Board auf 0..1; Humus nimmt die Zahlen so, wie sie gesendet werden.

Berechnete Nachrichten. %(v1*180) gibt das Ergebnis eines Ausdrucks aus, in der Sprache der Math-Box, und %?(v1>0.5){LED 1} gibt den Inhalt seiner geschweiften Klammern nur aus, wenn der Test wahr ist, so kann eine Nachricht mit einem Wert ihre Form ändern. %b(expr) und %w(expr) senden das Ergebnis als Bytes.

Was die Box zeigt. Jede serielle Box zeigt unten, an welchem Port sie hängt und was sie zuletzt gesendet oder empfangen hat, jedes Byte ausgeschrieben, und SerialIn markiert eine Zeile, die nicht zu seinem Parse passte, als übersprungen. Wenn ein Protokoll nicht funktioniert, schau dir diese Zeile an. Das Preset-Menü von SerialOut und SerialIn enthält die üblichen Nachrichtenformen als Ausgangspunkt.

Namen auf der Leitung. Eine Var ist ein Wert mit einem Namen. Zieh eine Var namens temp auf Buchse 1 von SerialOut und schreib %n1 %1\n, dann bekommt das Board temp 0.5. In der anderen Richtung gibt ein SerialIn, das temp 23.5 light 0.4 liest, jede Zahl an die Var mit diesem Namen weiter, wo auch immer sie im Patch sitzt, ganz ohne Kabel: send und receive aus Pd, mit dem Namen, der auf dem Wert mitfährt.

Bytes statt Text. Ein Sketch, der in rohen Bytes spricht, nutzt in beiden Feldern %b1 für ein Byte und %w1 für ein Zwei-Byte-Wort. In Format macht Scale 255 aus einem 0..1-Steuerwert ein volles Byte; in Parse wartet \xAA%b1%w2 auf das Header-Byte und nimmt die nächsten drei, und alles dazwischen überspringt es, bis es wieder synchron ist.

Prüfsummen, Wörter und Listen. %x oder %s in einem Format fügt das XOR oder die Summe der bisherigen Bytes hinzu, %X und %S dasselbe als zwei Hex-Ziffern, und %[ und %] markieren den Teil, den sie abdecken, also ist $%[HUM,%1,%2%]*%X\r\n ein Satz im GPS-Stil. %{slow,fast,turbo}1 gibt ein Wort aus einer Liste aus, gewählt durch Wert 1, und wird beim Lesen zu einer Position von 0 bis 1. %c ist ein Zähl-Byte und %b* die gezählten Bytes, für ein Paket mit wechselnder Länge; %* nimmt oder gibt jede Zahl einer Zeile aus. Ein Parse prüft die Prüfsumme und verwirft eine Zeile, die sie nicht besteht. Die vollständige Liste steht in der Hilfe jeder Box.

Der Port selbst. Frame an jeder Box stellt Parität und Stoppbits für das seltene Gerät ein, das nicht 8N1 nutzt; die Baud-Liste reicht bis 1000000, und Custom nimmt jede andere Rate. Reset entscheidet, ob das Öffnen des Ports das Board neu startet, so wie es der eigene Editor des Boards tut; schalte es aus für ein Board, das weiterlaufen soll, während Humus sich neu verbindet.

OSC über seriellen Port. Ein Board, das OSC in SLIP verpackt spricht, wie es die Teensy- und ESP-Bibliotheken tun, braucht SerialIn gar nicht: Aktiviere OSC über seriellen Port unter Einstellungen ▸ MIDI & OSC, und seine Nachrichten kommen auf den OSC-Steuerbus, sodass OSC-Learn sie an jedem Regler zuweist. Siehe MIDI & OSC.

Beliebig viele Board-, SerialIn- und SerialOut-Boxen können sich einen Port teilen: ein Kabel, drei Formate, drei Boxen, und jede Box zeigt, was sie sendet.

Wenn es nicht funktioniert

  • Nichts flackert. Ein anderes Programm belegt den Port: der serielle Monitor der Arduino IDE, ein vorheriges Humus, das sich noch beendet. Drück Reconnect an der Box, oder steck das Board aus und wieder ein; die Boxen verbinden sich von selbst neu.
  • Die Pegelanzeige flackert, aber die Ausgänge bleiben auf null. Auf dem Board läuft nicht StandardFirmata. Spiel StandardFirmata erneut auf, oder nutz SerialIn für einen eigenen Sketch.
  • Die Pegelanzeige flackert, aber die Werteanzeige steht still. Die Baudrate passt nicht zu der, mit der der Sketch den Port öffnet, oder der Sketch gibt eine Form aus, die das Feld Parse nicht erwartet. Leere Parse, um jede Zahl der Zeile zu nehmen.
  • Messwerte erreichen nur einen Teil des Bereichs. Ein Sensor nutzt selten die vollen 0..5V. Stell den Steuern-mit-Bereich auf den Teil, den er tatsächlich nutzt, oder setz einen Slider zwischen den Ausgang und das Ziel und stell dessen Min und Max ein.
  • Der Pin lässt sich nicht dimmen. Nicht jeder Pin hat PWM; nimm einen, der es hat.
  • Linux verweigert den Zugriff. Die Gruppe dialout, siehe oben.