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

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