Deshalb werden wir uns jetzt mit einem Analog-Digital-Wandler, kurz ADC, beschäftigen.
Kurze theoretische Einführung
Leider lassen sich nicht alle Dinge in der Welt um uns herum auf so einfache Art und Weise beschreiben. Wenn wir einen Abstandssensor anschließen, möchten wir die genaue Entfernung zu einem Hindernis wissen und nicht nur eine Information nach dem Motto: Hindernis sichtbar, kein Hindernis sichtbar.
Ein solcher Sensor könnte eine zum Abstand proportionale Spannung ausgeben. Die Messung würde dann darin bestehen, die Spannung abzulesen, z.B. von 0-5V. Dies ist der analoge Ansatz. Daher werden wir in den folgenden Beispielen geeignete Arduino-Peripheriegeräte verwenden, die es uns ermöglichen, die an speziellen Eingängen der Schaltung anliegende Spannung zu messen.
Achtung!
Bevor wir zum Testen übergehen, denk daran, dass du nur Spannungen im Bereich von 0-5V an die Eingänge des Arduino UNO anschließen kannst. Andere Spannungswerte können die Platine und sogar den Computer, an den Sie den Chip anschließen, beschädigen!
Zum Beispiel für einen Linearwandler:
Spannung => Vom ADC ausgelesener Wert
[V] (gerundet)
0 => 0
1 => 51
2 => 102
3 => 154
4 => 205
5 => 255
Es ist interessant zu wissen, dass Analog-Digital-Wandler relativ langsam arbeiten. Natürlich werden wir das in unseren Programmen nicht bemerken, aber wenn wir den ADC mit anderen Mikrocontroller-Peripheriegeräten vergleichen, schneidet er nicht so gut ab.
Eine Messung mit dem ADC dauert 0,0001 s,
d.h. es können maximal 10.000 Messungen pro Sekunde durchgeführt werden!
Zweitens sind diese Wandler teuer in der Herstellung. Wie du dich aus der zweiten Lektion über den Arduino UNO erinnerst, haben wir 6 Analogeingänge (A0-A5) zur Verfügung. In der Tat gibt es nur einen ADC im Mikrocontroller, an den ein Multiplexer angeschlossen ist. Dadurch ist es möglich, die Spannung auf 6 Kanälen zu messen.
Damit ist die theoretische Einführung abgeschlossen. Nun können wir zum ersten Programm übergehen.
Fertige Sets für Forbot-Kurse
Sie können jetzt ein Set von mehr als 70 Elementen, die für die Kursübungen notwendig sind, bei unseren Händlern kaufen!
Beliebtes Paket: Arduino Meister – Robotik Meister
ADC in der Praxis
Es ist an der Zeit zu sehen, wie der ADC in der Praxis funktionieren wird. Baue dazu die Schaltung wie in der Abbildung unten gezeigt auf. Ein Potentiometer erscheint hier in der Rolle eines Spannungsteilers.
Es bleibt uns nichts anderes übrig als unser erstes einfaches Programm. Wir beschränken uns zunächst nur darauf, den gelesenen Wert an den Computer zu senden. Dazu verwenden wir natürlich den UART, den wir im vorherigen Teil des Kurses kennengelernt haben.
int ausgelesenerWert = 0;
void setup() {
Serial.begin(9600);//Start der Kommunikation über UART
}
void loop() {
ausgelesenerWert = analogRead(A5);//Lesen des Spannungswertes
Serial.println(ausgelesenerWert);//Wir senden ihn an das Terminal
delay(200);//Wir warten, um die Ergebnisse bequemer zu lesen
}
Sind solche trockenen Werte für uns nützlich? Das ist schwer zu sagen. Es wäre besser, das Ergebnis in verständlichen Einheiten abzulesen. Zum Beispiel in Volt, richtig?
Einfaches Voltmeter
1024 => 5V 1 => x
1024x = 1*5
x = (1*5V)/1024 = ~0,0049V
Einfach ausgedrückt: Jede Erhöhung der Eingangsspannung um ~0,0049 V erhöht die ADC-Anzeige um eins. Das heißt, um das Ergebnis in Volt zu erhalten, muss man nur eine Zeile hinzufügen:
int ausgelesenerWert = 0;//Wert vom ADC lesen
float Spannung = 0;//Wert umgerechnet auf Spannung in V
void setup() {
Serial.begin(9600);//Start der Kommunikation über USART
}
void loop() {
ausgelesenerWert = analogRead(A5);//Lesen des Spannungswertes
Spannung = ausgelesenerWert * (5.0/1024.0); //Umrechnung des Wertes in Spannung
Serial.println(Spannung);//Senden der gemessenen Spannung
delay(200);//Wir warten, um die Ergebnisse bequemer zu lesen
}
Beachte, dass die Spannungsvariable als Float-Typ deklariert wurde, d. h. als ein Typ, der die Speicherung von Fließkommazahlen erlaubt.
Die Zahlen, die im obigen Code durch sich selbst geteilt werden, wurden mit der Anmerkung „.0“ geschrieben; dies ist eine Information für den Compiler, um sie als Fließkommazahlen zu behandeln. Andernfalls wäre das Ergebnis einer solchen Operation eine ganze Zahl!
Von nun an sollte auf dem Bildschirm des Computers ein Wert von 0-5V angezeigt werden. Wir haben also gerade ein sehr einfaches, aber funktionierendes Voltmeter gebaut. Kann man damit auch die Spannung anstelle eines Potentiometers zum Beispiel an einer Batterie messen? Ja, aber nur, wenn man sehr vorsichtig ist.
Denke daran, dass der Anschluss einer höheren Spannung als 5V den Arduino irreversibel beschädigt! Versuche daher gar nicht erst, die im Set enthaltene 9V-Batterie an unser Voltmeter anzuschließen.
Wenn du jedoch irgendwo eine gewöhnliche AA-Batterie mit 1,5 V auftreiben kannst (z. B. in TV-Fernbedienungen), kannst du ein wenig damit experimentieren:
- Verbinde den Minuspol (GND) der Batterie mit einem Kabel mit der
- Verbinde das Kabel von Pin A5 mit dem Pluspol der Batterie
- Lese die Spannung am Computer ab.
In meinem Fall lag die Spannung bei einer neuen Batterie knapp über 1,6 V, also war alles normal. Es sollte also nur als ein Experiment betrachtet werden.
Siehst du schon eine praktische Anwendung für ADC-Messungen (abgesehen von einem Voltmeter)? Wenn nicht, schau dir die folgende Übung an.
Steuerung des Programmbetriebs durch den ADC
Das frühere Programm war nur dazu gedacht, die Funktionsweise des Wandlers zu demonstrieren. Wir können nun das an die Schaltung angeschlossene Potentiometer verwenden, um den Betrieb des Programms zu beeinflussen. Zu diesem Zweck fügen wir dem Arduino eine einzelne LED hinzu.
Die Werte des Wandlers liegen zwischen 0 und 1023, was relativ klein ist. Was passiert, wenn wir die ausgelesene Zahl als Verzögerungswert im Programm verwenden? Hier ist der schnellste Weg, ein Gerät zu bauen, das eine LED mit einer durch ein Potentiometer gesteuerten Frequenz blinken lässt:
int ausgelesenerWert = 0; //Variable für die Speicherung von ADC-Messwerten
void setup() {
pinMode(2, OUTPUT); //Konfiguration der Ausgänge für die LED
}
void loop() {
ausgelesenerWert = analogRead(A5);//Auslesen des Wertes aus dem ADC
digitalWrite(2, HIGH);//Diode einschalten
delay(ausgelesenerWert);//Abhängigkeit des ADC-Timeouts
digitalWrite(2, LOW);//Diode ausschalten
delay(ausgelesenerWert);//Abhängigkeit des ADC-Timeouts
}
Hausaufgabe 4.1
Beobachte, was bei einer der Endpositionen des Potentiometers passiert. Was denkst du, was die Ursache dafür ist?
Anzeige an den Dioden
Es ist Zeit für ein etwas aufwendigeres Projekt. Dieses Mal werden wir je nach Stellung des Potentiometerschiebers die entsprechende Diode einschalten. Zunächst müssen alle Komponenten miteinander verbunden werden. Mein Anschlussvorschlag sieht wie folgt aus:
Ihre Anwendung sieht in der Praxis so aus:
skalierterWert = map(ausgelesenerWert, 0, 1023, 1, 5);
Die obige Codezeile ergibt immer einen Wert im Bereich von 1-5. In der Praxis kann dies wie folgt verwendet werden:
int ausgelesenerWert = 0;
void setup() {
pinMode(8, OUTPUT); //Konfiguration der LED-Ausgänge
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
}
void loop() {
ausgelesenerWert = analogRead(A5);//Auslesen des Wertes aus dem ADC
ausgelesenerWert = map(ausgelesenerWert, 0, 1023, 1, 5);//Skalierung der Werte
if (ausgelesenerWert == 1) { //Erster Bereich
digitalWrite(8, HIGH);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
} else if (ausgelesenerWert == 2) { //Zweiter Bereich
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
} else if (ausgelesenerWert == 3) { //Dritter Bereich
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, HIGH);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
} else if (ausgelesenerWert == 4) { //Vierter Bereich
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, HIGH);
digitalWrite(12, LOW);
} else { //Anderer, d.h. fünfter Bereich
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, HIGH);
}
delay(50); //Verzögerung, um den ADC nicht zu schnell zu lesen
}
Mir ist klar, dass sich erfahrene Entwickler an den Kopf fassen werden, wenn sie die oben genannten Bedingungen sehen. Aber wir haben alles unter Kontrolle. Wir werden uns bald mit der switch/case-Konstruktion befassen, die solche langen Bedingungen erleichtern wird
Überprüfe, was mit den einzelnen LEDs passiert, wenn du das Potentiometer drehst. Wenn alles richtig angeschlossen wurde, sollte beim Drehen des Reglers jeweils eine andere Diode aufleuchten.
Bei einer der Endstellungen des Potentiometers kann man feststellen, dass sich die Dioden seltsam verhalten. Am besten ist es dann, durch Ausprobieren den Maximalwert des ADC zu ändern, der in der map()-Funktion eingestellt ist.
In meinem Fall verhielt sich die Schaltung bereits beim Wechsel von 1023 auf 1021 korrekt.
Hausaufgabe 4.2
Was passiert, wenn du deine Hand in die Nähe des Kabels bringst (ohne das Ende zu berühren)? Hasst du eine Idee, warum das so ist? In meinem Fall, als der Draht in der Luft hing, leuchteten 3 LEDs, aber ich brauchte meine Hand nur bis auf 2 cm an den Draht heranzuführen, dann leuchteten alle LEDs. Habt ihr eine Idee, warum das so ist?
Wenn dieser Effekt bei euch nicht so ausgeprägt ist, könnt ihr am Ende des Kabels eine „Antenne“ anbringen, z.B.: aus Alufolie.
Diese Erfahrung sollte dir in Erinnerung bleiben als Beweis dafür, dass du keine Schaltkreiseingänge in der Luft „hängen“ lassen darfst. Siehe, welche Probleme das verursachen kann!
Bei Dunkelheit aktiviertes Licht
Mit Hilfe des Fotowiderstands können wir einen Spannungsteiler bauen, der von der Lichtmenge in der Umgebung abhängt. Baue die Schaltung wie in der folgenden Abbildung gezeigt auf. Der Fotowiderstand soll zusammen mit einem 1k-Widerstand einen Teiler bilden.
Mit einer solchen Schaltung können wir eine Leuchte bauen, die sich bei Dunkelheit einschaltet. Der Code ist sehr einfach (wie immer):
int ausgelesenerWert = 0; //Variable zur Speicherung des ADC-Wertes
void setup() {
pinMode(8, OUTPUT); //Konfiguration des Wertes aus dem ADC
}
void loop() {
ausgelesenerWert = analogRead(A5);//Auslesen des Wertes aus dem ADC
if (ausgelesenerWert < 100) {
digitalWrite(8, HIGH);//Diode einschalten
} else {
digitalWrite(8, LOW);//Diode ausschalten
}
delay(50);
}
In meinem Fall habe ich ihn anfangs auf 500 eingestellt und ihn dann schrittweise verringert, bis die Diode im richtigen Moment (als ich den Sensor mit der Hand abdeckte) eingeschaltet wurde.
Anstelle einer blauen Diode kann man nun einfach ein paar stärkere weiße Dioden anschließen (über einen Transistor) und schon hat man ein funktionierendes Licht, das selbst weiß, wann es leuchten soll. Was aber, wenn wir es in einen anderen Raum bringen, wo die Bedingungen minimal anders sind? Müssen wir dann wieder den Arduino mehrmals programmieren, um den richtigen Schwellenwert zu wählen? Ja, es sei denn…
Bei Dunkelheit aktiviertes Licht v2
Ich habe ein Potentiometer verwendet, das an einen anderen Analogeingang (A4) angeschlossen ist:
Anstatt das Einschalten der Diode von einem festen Grenzwert abhängig zu machen, können wir die Einschaltschwelle nun stufenlos mit einem Potentiometer einstellen. Die Änderung im Programm ist sehr einfach und beschränkt sich auf die Bearbeitung von 3 Codezeilen:
int ausgelesenerWert = 0; //Variable für die Speicherung von ADC-Messwerten
int prog = 0; //Lichteinschaltschwelle - einstellbar über Potentiometer
void setup() {
pinMode(8, OUTPUT); //Konfiguration der Ausgänge für die Diode
}
void loop() {
ausgelesenerWert = analogRead(A5);//Auslesen des Wertes aus dem ADC
prog = analogRead(A4);//Auslesen des Wertes aus dem ADC
if (ausgelesenerWert < prog) { //ist es dunkler als die eingestellte Schwelle?
digitalWrite(8, HIGH);//Diode einschalten
} else {
digitalWrite(8, LOW);//Diode ausschalten
}
delay(50);
}
- Stelle das Gerät in das Licht, bei dem die Diode ausgeschaltet sein soll
- Dreh das Potentiometer auf die Stellung, in der die Diode ausgeschaltet wird
- Geschafft!
Die Verwendung des ADC ist sehr einfach, es ist also an der Zeit, die Hausaufgaben eigenständig durchzuführen. Denke daran, alle Lektionen gut zu beherrschen. Mit der Zeit werden wir viele Funktionen in den Programmen verwenden. Es bleibt dann nicht mehr viel Zeit, um zu den Grundlagen zurückzukehren!
Hausaufgabe 4.4
Erweitere das Programm der intelligenten Beleuchtung so, dass es beim Einschalten der Diode (einmalig) an den PC sendet, welche Spannung am Teiler aufgetreten ist.
Hausaufgabe 4.5
Versuche, ein einfaches Spiel zu programmieren. Nachdem du das Programm gestartet hast, drehe das Potentiometer an eine beliebige Stelle und drücke die Taste. Der Arduino sollte dann eine Meldung auf dem PC anzeigen:
Gib eine Zahl an:
Hausaufgabe 4.6
Kannst du durch die Analyse des Unterschieds zwischen den Messwerten der beiden Sensoren ein Programm schreiben, das feststellt, auf welcher Seite der Platte sich die stärkere Lichtquelle befindet? Versuche, die Richtung mit den 5 Dioden zu bestimmen (mehr links, Mitte, mehr rechts, usw.)!
Zusammenfassung
Zu beachten ist, dass das komplette Set der Komponenten, die für alle Übungen benötigt werden, bei Botland erhältlich ist. Der Kauf der Sets unterstützt zukünftige Veröffentlichungen auf Forbot!