Bis jetzt haben wir uns unter anderem Kontrollstrukturen, Variablen und Funktionen angesehen. Im zweiten Beitrag dieses Kurses haben wir gesehen, wie man über eine serielle Schnittstelle kommunizieren kann und heute werden wir sogar noch einen Schritt weiter gehen. Wir verwenden die serielle Schnittstelle nicht nur, um das Debugging unserer Programme durchzuführen oder Informationen zu erhalten, sondern wir können über den seriellen Monitor auch Anweisungen an unsere Steuerplatine ZUM BT 328 oder jede andere Arduino Platine senden. So können wir zum Beispiel einen Vektor an unseren Roboter senden, der angibt, in welche Richtung und mit welcher Geschwindigkeit er sich bewegen soll. Darüber hinaus lernen wir, wie man dies mit einem analogen Signal über die PWM-Pins von Arduino durchführt, die wir dafür verwenden, die Farbe der RGB-LED zu verändern. Die PWM der Arduino-Platinen ermöglicht uns, mit digitalen Signalen ein analoges Signal zu generieren.Wenn du mehr über PWM erfahren möchtest gehe zur Referenzseite über PWM.
Materialliste
- ZUM BT-328, Arduino Platine oder kompatibel.
- Breadboard (Steckplatine oder Protoboard).
- RGB -LED, hier zusammengefasste Kathode
- Überbrückungskabel.
Elektrische Verbindungen
Wenn wir eine Steckplatine benutzen ist es wichtig darauf zu achten, dass wir verschiedenfarbige Kabel verwenden, um den Kreislauf besser zu visualisieren. Zu Beginn eines Projektes oder bei kleineren Projekten mag dies noch nicht so wichtig sein, aber wenn der Umfang steigt, ist es von großer Bedeutung. Bei der RGB-LED beispielsweise können wir uns die Verbindungen vereinfachen, indem wir für die Steuerung des roten Lichts der LED ein rotes Kabel verwenden. Für gewöhnlich wird zur Markierung des Versorgungskreises ein rotes Kabel verwendet und für die Masse oder Erdung (GDN) – aus dem Englischen von Ground – ein schwarzes oder braunes Kabel. Das LED-Modul, das wir für dieses Beispiel verwenden, enthält Widerstände, um den Strom im Modul selber zu begrenzen. Solltest du ein anderes Modul verwenden, das nicht über diese Widerstände verfügt, vergewissere dich, einen Widerstand pro Farbe einzusetzen, damit die LED nicht durchbrennen kann. Ein Beispiel für die Einbindung einer LED ohne integrierte Widerstände findet sich auf der Abbildung. Für unser Projekt verbinden wir die RGB-LED mit der ZUM BT-328 Platine nach dem folgenden Schema:
ZUM BT-328 | LED RGB |
GND | GND |
6 | R |
5 | G |
3 | B |
Der Code
Wie immer beginnen wir damit, die Variablen der Pins zu benennen:
1 |
int redPin = 6, greenPin = 5, bluePin = 3; |
Außerdem benennen wir einige Variablen, die wir für den Sketch benötigen:
1 2 3 |
int delayLed = 10; // Zeit, die zwischen jeder LED-Veränderung vergeht (ms) // Variablen, die die letzte Farbe jeder LED speichern int red_old = 0, green_old = 0, blue_old = 0; |
In der Variablen delayLed speichern wir die Zeit in Millisekunden, die beim Übergang von einem Wert der LED zum nächsten vergeht. Wir empfehlen, einen sehr niedrigen Wert zu verwenden, da das delay dazu verwendet wird, einen weicheren Übergang zu erreichen. Daher müssen wir bedenken, dass die Zeit, die für den Übergang benötigt wird, mit höherem Wert ansteigt. Beispielsweise benötigt der Übergang für seine Umsetzung bei einem Wert von 10 ms von schwarz ( nicht leuchtende LED) zu weiß oder von (0,0,0) bis (255,255,255) 7,6 Sekunden. Für den gleichen Übergang mit einem Wert von 5 ms werden 3,8 Sekunden benötigt. Im Folgenden verwenden wir die setup-Funktion, um unser Programm zu initialisieren.
1 2 3 4 5 6 7 8 9 10 11 |
void setup() { // seriellen Port initialisieren. Serial.begin(9600); // Wir markieren die verwendeten Pins als Ausgänge. pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("Fertig!"); } |
Bei setup starten wir den seriellen Port, den wir verwenden, um zwischen Arduino und dem Computer zu kommunizieren. Außerdem legen wir die Pins, die wir für jede einzelne Farbe verwendet haben, als Ausgänge fest. In der Schleife loop finden wir verschiedene Methoden, die wir bis jetzt noch nicht kannten, nämlich parseInt y constrain. Die Methode parseInt wird zusammen mit der Serial über den Befehl Serial.parseInt(); verwendet und sucht in der Information, die über den seriellen Port ankommt, die nächste aus ganzen Zahl bestehende Zahlenreihe bis ein Komma kommt. Die Referenzseite findest du hier. Die Funktion constrain wird dazu verwendet, um einen Wert auf einen Wertebereich zu “beschränken”. Liegt ein Wert entsprechend zwischen A-B erhält er diesen. Liegt sein Wert darunter nimmt er den Wert A an, liegt er darüber nimmt er B an. Die Referenzseite findest du hier. Der Code der Schleife loop sieht folgendermaßen aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
void setup() { // Den seriellen Port initialisieren. Serial.begin(9600); // Wir markieren die verwendeten Pins als Ausgänge. pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.println("Fertig!"); } void loop() { // Liegt am seriellen Port Information vor, verwenden wir sie: while (Serial.available() > 0) { int red = 0, green = 0, blue = 0; // suche die nächste gültige Reihe ganzer Zahlen und // weise den zu einer ganzen Zahl umgewandelten Wert der entsprechenden Variable zu red = Serial.parseInt(); // suche erneut. green = Serial.parseInt(); // suche erneut: blue = Serial.parseInt(); // suche das Zeichen für Zeilenende. Sage dem Programm, dass die Dateneingabe abgeschlossen ist. // Wenn du die Arduino-IDE oder eine andere IDE verwendest, die es erlaubt, das Format // der neuen Zeile beim Senden von Daten über den seriellen Monitor einzuschließen, entferne den Kommentar // der Zeile 33 und kommentiere die Zeile 34. // if (Serial.read() == 'n'){ if (Serial.read() == '*'){ // Mit constrain vergewissern wir uns, dass sich der Wert im Bereich des PWM befindet //Verwende für zusammengefasste Anoden für rot beispielsweise: red = 255 - constrain(red, 0, 255); red = constrain(red, 0, 255); green = constrain(green, 0, 255); blue = constrain(blue, 0, 255); // print the three numbers in one string as hexadecimal: Serial.print(red, HEX); Serial.print(green, HEX); Serial.println(blue, HEX); //Wir verändern die Farbe der RGB-LED fade(redPin, red, red_old); fade(greenPin, green, green_old); fade(bluePin, blue, blue_old); Serial.println("Farbe geändert"); //Wir speichern die Daten der vorigen Farben. red_old = red; green_old = green; blue_old = blue; } } } |
In der Schleife können wir sehen, dass die Funktion fade aufgerufen wurde. Wir haben sie erstellt, um die Farbe der LED in weicher Abstufung von einer zur nächsten ändern zu können. Die Funktion Fade wird nach loop festgelegt und sieht folgendermaßen aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void fade(int pin, int newValue, int aktValue) { // Diese Funktion ändert jede Farbe von ihrem aktuellen Wert zum nächsten // Wir unterscheiden dabei zwei Fälle: // 1 - Der neue Wert ist höher als der aktuelle Wert, daher muss erhöht werden // 2 - Der neue Wert ist niedriger als der aktuelle Wert, daher muss verringert werden if (newValue < aktValue) { for (int i = aktValue; i <= newValue; i++) { analogWrite(pin, i); delay(delayLed); } } else if (newValue > aktValue) { for (int i = aktValue; i >= newValue; i--) { analogWrite(pin, i); delay(delayLed); } } } |
In dieser Funktion unterscheiden wir zwei Fälle:
- Der nächste Wert ist höher als der aktuelle Wert und wir müssen daher den Wert der LED erhöhen.
- Der nächste Wert ist niedriger als der aktuelle Wert und wir müssen daher den Wert der LED verringern.
In dieser Funktion gibt es ein weiteres Kommando, das wir bis jetzt noch nicht kennen. Es handelt sich um analogWrite, das dafür zuständig ist, die PWM (Pulse Width Modulation)-Kapazitäten unserer Platine zu verwenden. Die PWM simuliert ein analoges Signal, indem es die diskreten Werte eines digitalen Signals verwendet. Auf der Referenzseite zu PWM findet ihr weitere Informationen.