id: Msw5YCj3DZzflNZTRLTr8PbUQO721rmpCxZlDqRN createdBy: 15sg55K8KHkN dateCreated: 1689064662293 name: Komplexaufgabe 2 - Analog-Digital-Wandler meta: logo: >- https://raw.githubusercontent.com/TUBAF-IfI-LiaScript/VL_EAVD/master/excercise/images/excercise_04.png description: >- Die Studierenden setzen eine Anwendung um, die zwei existierende Klassen für die Verwendung von peripheren Bauteilen - Ultraschallsensor und LCD-Display - um. Im Ergebnis steht eine Applikation die kontinuierlich die Distanz zu einem Hindernis vermisst. Die Daten werden zudem über die Serielle Schnittstelle ausgegeben und analysiert. selfAssign: true defaultNumberOfRooms: '2' members: teacher: [] student: [] modules: - url: https://edrys-labs.github.io/module-markdown-it/index.html config: content: >- # Komplexaufgabe 2 - Analog-Digital-Wandler Liebe Teilnehmerinnen und Teilnehmer, die zweite Aufgabe baut auf den grundlegenden Konzepten der ersten auf und dient dazu, Ihr Verständnis für die Programmierung eingebetteter Systeme weiter zu vertiefen. Wir haben uns für eine Remote-Lösung entschieden, da die Aufbauten Schritt für Schritt immer aufwändiger werden. Entsprechend erlaubt uns der Webzugriff einen ressourcensparenden und zeiteffizienten Einsatz der Setups. Die Umsetzung dieser Remote-Lösung ist für uns alle neu und wir bitten Sie daher um Verständnis, falls es zu Anfang noch zu Problemen kommen sollte. Noch umfasst unsere Lösung keinen Multi-User-Modus - entsprechend könnten Sie einen Kommilitonen ziemlich ärgern, wenn Sie ihm die Kontrolle entziehen. Prüfen Sie also bitte vorher, ob das Setup gerade von jemand anderem verwendet wird. Die „Station" merkt sich immer den letzten Stand, verlassen Sie Ihren Arbeitsplatz ordentlich und kopieren sie vor dem verlassen einfach den Original-Code in den Editor ... Für die Aufgabe erläutert Raum 1 die Fragestellungen und Lernziele. Danach ist in Raum 2 eine Simulatorübung zur Fehlerbehebung vorgesehen. Die praktische Umsetzung auf dem Laborsetup erfolgt auf der "Station". Die Aufgabe ist so konzipiert, dass Sie die Lösung selbstständig erarbeiten können. Sollten Sie dennoch Fragen haben, können Sie sich gerne an die Betreuer wenden. Ein kleines Video-Tutorial über die Verwendung von Edrys: > Ihre Codeänderungen werden auf der Station anonymisiert gespeichert. Wir wollen damit tatsächliche Problemfelder identifizieren, um damit die Veranstaltung systematisch weiterzuentwickeln. Aus den Daten können keine Rückschlüsse auf den Teilnehmenden oder spezifika des Rechners gezogen werden. Wenn Sie Fragen dazu haben, sprechen Sie uns gern an. Wir freuen uns auf Ihr Feedback und Ihre Anregungen. _Ihr CrossLab Team_ studentConfig: content: '' teacherConfig: content: '' stationConfig: content: '' showInCustom: lobby width: full height: huge - url: https://edrys-labs.github.io/module-markdown-it/index.html config: content: >- # Aufgabeninhalt ## Lernziele * Konfiguration und Nutzung eines Analog-Digital-Wandlers ohne Arduino-Bibliotheken, mit direkten Registerzugriffen (avrlibc) * Transformation von digitalen Spannungswerten in physikalische Größen (Distanz in cm) * Strukturierte und wiederverwendbare Programmierung durch die Auslagerung von Codeteilen in Funktionen * Steuerung eines Servomotors für präzise Bewegung und Positionskontrolle * Ausgabe und Speicherung der Messergebnisse ## Aufgabenstellung Entwickeln Sie einen Programmcode, der folgende Anforderungen erfüllt: * implementieren Sie eine Funktion make_scan, die den Distanzsensor schrittweise von 0° bis 180° bewegt und dabei in jedem Schritt die Distanz misst * ersetzen Sie die Funktion analogRead() durch eine direkte Konfiguration und Nutzung des Analog-Digital-Wandlers (ADC) mit avrlibc * lesen Sie die digitalen Spannungswerte ein und transformieren Sie diese in Distanzwerte in cm * strukturieren Sie Ihren Code, indem Sie redundante Codeteile in Funktionen auslagern ## Technische Basis Die Umsetzung erfolgt auf einem Arduino Uno mit den folgenden Komponenten: | Bautteil | Bezeichnung | Elektrische Verbindung | | ----------------------- | ----------- | ---------------------------------------- | | Distanzsensor (Infrarot) | Sharp GP2Y0A02 | 5V, GND, Signal (Pin A0) | | Servomotor | | PWM-Signal (Pin 9), 5V, GND | > Der Zeitaufwand für die Umsetzung der Aufgabe beträgt etwa 90 Minuten. studentConfig: content: '' teacherConfig: content: '' stationConfig: content: '' showInCustom: Room 1 width: full height: tall - url: https://edrys-labs.github.io/module-markdown-it/index.html config: content: >- # Arduino Layout ![ArduinoLayout](https://docs.arduino.cc/static/6ec5e4c2a6c0e9e46389d4f6dc924073/a6d36/Pinout-UNOrev3_latest.png) studentConfig: content: '' teacherConfig: content: '' stationConfig: content: '' showInCustom: Room 1 width: half height: tall - url: https://edrys-labs.github.io/module-markdown-it/index.html config: content: >- # Simulatorübung: Fehlerhafte ADC-Konfiguration Der ADC (Analog-Digital-Wandler) des Mikrocontrollers kommuniziert mit dem restlichen System, indem er analoge Spannungen in digitale Werte umwandelt. Dies geschieht in einer definierten Abfolge von Konfiguration, Messung und Auswertung. Damit die Messungen zuverlässig funktionieren, muss die richtige Referenzspannung eingestellt, der ADC korrekt initialisiert und die Messergebnisse korrekt interpretiert werden. Wir nehmen an, dass am analogen Pin A0 des Mikrocontrollers ein Potentiometer befestigt ist. Der ADC misst die Spannung am Pin und gibt die berechneten Werte über die serielle Schnittstelle aus. > **Aufgabe**: Das gegebene Programm enthält mehrere Fehler, die Sie beheben sollen. Ziel ist es, mit einem Potentiometer am ADC-Eingang (A0) Spannungswerte im Bereich von 0 bis 1.1V zu messen und diese über die serielle Schnittstelle auszugeben. studentConfig: content: '' teacherConfig: content: '' stationConfig: content: '' showInCustom: Room 2 width: half height: tall - url: https://edrys-labs.github.io/module-editor/index.html config: runCommand: execute language: cpp synchronize: false editorText: | #include #include void adc_init() { // Fehlerhafte Konfiguration: Falsche Referenzspannung (externe Referenz gewählt) ADMUX = (1 << REFS0); // Nur REFS0 gesetzt, sollte interne 1.1V-Referenz sein // Fehlerhafte Prescaler-Einstellung: Taktfrequenz zu hoch ADCSRA = (1 << ADEN) | (1 << ADPS1); // Prescaler auf 8, ADC läuft zu schnell } uint16_t adc_read(uint8_t channel) { // Fehlerhafte Kanalwahl: Kanal über 7 wird nicht verhindert ADMUX = (ADMUX & 0xF8) | channel; ADCSRA |= (1 << ADSC); while (!(ADCSRA & (1 << ADIF))); // Wartet auf falsches Flag return ADC; // Liefert ungenaue Werte } void setup() { Serial.begin(9600); adc_init(); } void loop() { uint16_t adc_value = adc_read(8); // Fehler: Kanal 8 existiert nicht float voltage = adc_value * (5.0 / 1023.0); // Fehlerhafte Berechnung mit falscher Referenzspannung Serial.print("Voltage: "); Serial.print(voltage, 2); Serial.println(" V"); _delay_ms(500); } studentConfig: '' teacherConfig: '' stationConfig: '' showInCustom: Room 2 width: full height: huge - url: https://edrys-labs.github.io/module-avr8js/index.html config: modules: |
execute: execute studentConfig: '' teacherConfig: '' stationConfig: '' showInCustom: Room 2 width: half height: tall - url: https://edrys-labs.github.io/module-editor/index.html config: editorText: |- #include const int analogPin = A0; const int servoPin = 9; float calculate_dist_cm(float value){ // Aufgabe 2: Bilden Sie die digitale Spannungsrepräsentation // auf einen Abstandswert ab // TODO return value; } void make_scan(int start, int end, int step){ // Aufgabe 0: Übernehmen Sie Zeile 38 - 49 und 52 - 61 // in eine Funktion // TODO // // Aufgabe 1: Ersetzen Sie die Arduino AnalogRead() // Methode } void setup() { pinMode(analogPin, INPUT); pinMode(servoPin, OUTPUT); Serial.begin(9600); //Serial.println("Los geht's"); delay(1000); Servo myservo; myservo.attach(servoPin); float val_v = 0; float val_cm = 0; Serial.print("rechts:"); int pos = 0; for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees // in steps of 1 degree // Aufgabe 0: Prozedurale Umsetzung eines Schrittes myservo.write(pos); delay(15); val_v = analogRead(analogPin); val_cm = calculate_dist_cm(val_v); Serial.print(pos); Serial.print(","); Serial.print(val_cm); Serial.print(";"); } Serial.println(""); Serial.print("links:"); for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees myservo.write(pos); delay(15); val_v = analogRead(analogPin); val_cm = calculate_dist_cm(val_v); Serial.print(pos); Serial.print(","); Serial.print(val_cm); Serial.print(";"); } Serial.println(""); } void loop(){ } runCommand: execute language: cpp theme: light showInCustom: station width: full height: medium - url: https://edrys-labs.github.io/module-station-stream/index.html stationConfig: video: true audio: false showInCustom: station width: half height: medium - url: https://edrys-labs.github.io/module-pyxtermjs/index.html config: '' studentConfig: '' teacherConfig: '' stationConfig: server: http://localhost:5000/pty execute: execute script: > echo $CODE | base64 --decode > Hello.ino arduino-cli sketch new Hello olddir=$(pwd) mv Hello.ino Hello cd Hello arduino-cli board attach -p /dev/ttyACM0 -b arduino:avr:uno cd $olddir arduino-cli compile Hello && arduino-cli upload -p /dev/ttyACM0 Hello && serial-plotter.py --type radar enable: teacher: true student: true showInCustom: station width: full height: tall - url: https://edrys-labs.github.io/module-markdown-it/index.html config: content: >- # Komplexaufgabe 2 - Analog-Digital-Wandler > Die Aufgabe 2 zielt darauf Ihre Fähigkeiten mit Blick auf die Nutzung des Analog-Digital-Wandlers zu trainieren. Dafür soll ein "Laserscanner" implementiert werden. Die Arduino-Implementierung illustriert die erwartete Funktionalität - ein Infrarot-basierter Distanzsensor ([Sharp GP2Y0A02](http://www.pololu.com/file/download/gp2y0a02yk_e.pdf?file_id=0J156)) schrittweise durch einen Servomotor um 180 Grad geschwenkt. Mit jedem Schritt um einen Grad wird eine neue Messung mit dem Distanzsensor realisiert. Der Distanzsensor ist mit dem Eingang `A0` des Mikrocontrollers verbunden. Der Servo-Motor, dessen Code aber nicht angepasst wird, wird über ein PWM-Signal an Pin 9 gesteuert. Die Grafik zeigt jeweils die Scans, die allerdings noch nicht in einen Distanzwert transformiert wurden. Folgen Sie den Anweisungen im Code und ersetzen Sie die Arduino-Funktionen durch die entsprechenden avrlibc Befehle: 0. Verbessern Sie zunächst die Struktur des Codes, in dem Sie die redundanten Codeteile in eine Funktion `make_scan` "auslagern" (siehe Zeile 13). 1. Ersetzen Sie die Konfiguration und die Durchführung der Analogen Messungen (`analogRead(analogPin)`) durch eine `avrlibc` Realisierung. 2. Transformieren Sie die Spannungswerte in einen echten Distanzwert in $cm$. Die Visualisierung übernimmt eine 180 Einträge umfassendes Array. Dabei wird der Index als Winkelangabe und der enthaltene Wert als Distanz interpretiert. ## Original Code ``` cpp #include const int analogPin = A0; const int servoPin = 9; float calculate_dist_cm(float value){ // Aufgabe 2: Bilden Sie die digitale Spannungsrepräsentation // auf einen Abstandswert ab // TODO return value; } void make_scan(int start, int end, int step){ // Aufgabe 0: Übernehmen Sie Zeile 38 - 49 und 52 - 61 // in eine Funktion // TODO // // Aufgabe 1: Ersetzen Sie die Arduino AnalogRead() // Methode } void setup() { pinMode(analogPin, INPUT); pinMode(servoPin, OUTPUT); Serial.begin(9600); delay(1000); Servo myservo; myservo.attach(servoPin); float val_v = 0; float val_cm = 0; Serial.print("rechts:"); int pos = 0; for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees // in steps of 1 degree // Aufgabe 0: Prozedurale Umsetzung eines Schrittes myservo.write(pos); delay(15); val_v = analogRead(analogPin); val_cm = calculate_dist_cm(val_v); Serial.print(pos); Serial.print(","); Serial.print(val_cm); Serial.print(";"); } Serial.println(""); Serial.print("links:"); for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees myservo.write(pos); delay(15); val_v = analogRead(analogPin); val_cm = calculate_dist_cm(val_v); Serial.print(pos); Serial.print(","); Serial.print(val_cm); Serial.print(";"); } Serial.println(""); } void loop(){ } ``` studentConfig: content: '' teacherConfig: content: '' stationConfig: content: '' showInCustom: station width: half height: tall - url: https://edrys-labs.github.io/module-code-logger/ config: studentConfig: '' teacherConfig: '' stationConfig: '' showInCustom: station, station-only width: full height: tall - url: https://edrys-labs.github.io/module-station-light-control/index.html config: '' studentConfig: '' teacherConfig: '' stationConfig: '' showInCustom: station, station-only width: third height: short