Einführung in die Mikrocontrollertechnik day by day Sommersemester 2019
(EN google-translate)
(PL google-translate)
1 -- Dienstag 19.03.2019
Vorlesung, Kapitel:
40_Mikrocontroller/01_Einfuehrung/02_Maschinensprache
40_Mikrocontroller/01_Einfuehrung/03_Assemblerbeispiel
45_Mikro17/02_ArduinoMicro
45_Mikro17/02_ArduinoMicro/01_Lauflicht
45_Mikro17/02_ArduinoMicro/02_Taster
atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf
1 -- Donnerstag 21.03.2019 (Ü)
Setzen Sie "Blinkende LED" mit dem Arduino-Micro um (Programm und Schaltungsaufbau).
2 -- Dienstag 26.03.2019 (V)
|
45_Mikro17/03_DigitalIO (und Unterkapitel)
96_Arduino/22_Universal/02_LED_Leiste
lauflicht.zip (Programm-Varianten aus der Vorlesung)
2 -- Donnerstag 28.03.2019 (Ü)
45_Mikro17/02_ArduinoMicro/04_Uebung3
3 -- Dienstag 02.04.2019 (V)
Thema: Digitale Eingänge
|
45_Mikro17/03_DigitalIO (und Unterkapitel)
Im Unterricht erarbeitet:
|
|
void setup() { pinMode(2,INPUT); // digitalWrite(2,1); //Pullup-Widerstand digitalWrite(2,0); //Deaktivieren von Pullup-Widerstand //d.h. Es muß extern ein Pulldown-Widerstand verbunden werden. pinMode(4, OUTPUT); pinMode(6, OUTPUT); } void loop() { if(digitalRead(2)==HIGH) { digitalWrite(4,1); digitalWrite(6,1); } else { digitalWrite(4,0); digitalWrite(6,0); } }
Code 0-1: 2. Externe Pulldown-Widerstände statt interne Pullup-Widerstände.
|
//Hier sehen wir: //http://www.kramann.info/45_Mikro17/02_ArduinoMicro/index.php //D2 entspricht PD1 //D4 entspricht PD4 //D6 entspricht PD7 //Wir ersetzen jetzt jeden Arduino-Befehl durch den passenden //Registerbefehl: void setup() { // pinMode(2,INPUT); // DDRD &= 0b11111101; DDRD &= ~(1<<PD1); // digitalWrite(2,0); //Deaktivieren von Pullup-Widerstand PORTD &= 0b11111101; //d.h. Es muß extern ein Pulldown-Widerstand verbunden werden. // pinMode(4, OUTPUT); DDRD |= 0b00010000; // pinMode(6, OUTPUT); DDRD |= 0b10000000; } void loop() { // if(digitalRead(2)==HIGH) // if( (PIND & 0b00000010) == 2 ) if( (PIND & (1<<PD1)) == (1<<PD1) ) { //digitalWrite(4,1); PORTD |= (1<<PD4); //digitalWrite(6,1); PORTD |= (1<<PD7); } else { //digitalWrite(4,0); PORTD &= ~(1<<PD4); //digitalWrite(6,0); PORTD &= ~(1<<PD7); } }
Code 0-2: 3. Gleiches Programm wie 2., aber mit Registerbefehlen realisiert (Korrespondierende Arduino-Befehle jeweils darüber als Kommentar).
3 -- Donnerstag 04.04.2019 (Ü)
Erstellen Sie zunächst die noch fehlenden Boxen (wie am Dienstag). Falls genug Elemente da sind: Erstellen Sie ruhig zusätzlich 1 bis 2 Ersatzboxen ohne Matrikelnummer-Zuweisung.
Übung (Wenn alle Boxen fertig sind)
Erstellen Sie eine Soft- und Hardware mit dem Arduino-Micro, deren Funktionalität einer Fußgängerampel entspricht: Kurzes Drücken eines Tasters läßt sie auf grün springen, nach einiger Zeit springt sie zurück auf rot.
|
Hinweis: Sie dürfen selber geeignete Ein- und Ausgänge festlegen. Der delay(...) Befehl (Unterbrechen des Programmflusses um die übergebene Anzahl von Millisekunden) darf in beiden Versionen benutzt werden.
4
4 -- Dienstag 09.04.2019 (V)
Die UART-Schnittstelle und ihre praktische Anwendung zur Verknüpfung eines Arduino-Boards mit einem PC.
serial.zip -- Alle Beispiele aus der Vorlesung (Arduino und Processing)
4 -- Donnerstag 11.04.2019 (Ü)
Übung
|
Hinweise zu 3.:
|
5
5 -- Dienstag 16.04.2019 (V)
Wie UART, so soll nun auch zunächst die Verwendung Pulsweiten-modulierter Signale (PWM) mittels Arduino-Befehlen eingeführt werden. Später soll beides aber auch über Registerbefehle umgesetzt werden.
96_Arduino/22_Universal/03_Motortreiber
96_Arduino/12_Motor_PWM1
45_Mikro17/04_Timer/02_Timer1_Servo
40_Mikrocontroller/04_PWM/08_LoesungUE3
5 -- Donnerstag 18.04.2019 (Ü)
23.04.2019 keine Übung/Vorlesung (Ostern)
5 -- Donnerstag 25.04.2019 (Ü2)
Die Box mit den Servos befindet sich im Raum IWZ219 in Stahlschrank Nr. 3. Zu verwenden sind ausschließlich die Miniservos, weil die anderen einen zu hohen Stromverbrauch haben.
|
fpwm = 100Hz TOP = 10000 N = 8 // MODE8 VORTEILUNG N=8 Seite 133 TCCR1B = (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10); TCCR1A = (0<<WGM11) | (0<<WGM10) | (1<<COM1A1) | (0<<COM1A0); ICR1 = 10000; //TOP für PWM MODE 8 DDRB = (1<<PB5); OCR1A = ...
Code 0-3: Daten für die Servo-Ansteuerung aus der Vorlesung.
Hineweis: Um auf Registerbasis auch einen Sweep hinzubekommen, benötigen Sie nach Ihrem aktuellen Wissensstand weiterhin die delay()-Funktion von Arduino. Diese verwendet ihrerseits den Timer 0.
6
6 -- Dienstag 30.04.2019 (V)
|
int pos = 0; void setup() { TCCR1B = (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10); TCCR1A = (0<<WGM11) | (0<<WGM10) | (1<<COM1A1) | (0<<COM1A0); ICR1 = 10000;//TOP für PWM MODE 8 DDRB = (1<<PB5); OCR1A = 0; OCR1B = 1500; } void loop() { for(pos = 500; pos <= 2500; pos+=60){ OCR1A = pos; delay(15); } for(pos = 2500; pos >= 500; pos-=60){ OCR1A = pos; delay(15); } }
Code 0-4: Studentische Lösung zur Register-basierten Ansteuerung eines Servos.
6 -- Donnerstag 02.05.2019 (E-TEST 1)
E-TEST 1 (IWZ135 8:30-10:00)
7
7 -- Dienstag 07.05.2019 (V)
|
7 -- Donnerstag 09.05.2019 (Ü)
Umsetzung objektorientierter Programmierung für den Arduino-Micro
|
In dieser Übung soll eine Klasse für ein Lauflicht auch dem gesamten PORTB geschrieben werden:
Den notwendigen Aufbau der Schaltung können Sie dem Strumlaufplan unter folgendem Link entnehmen:
Ein Beispiel, an dem zu ersehen ist, wie überhaupt mit der Arduino-IDE objektorientiert programmiert werden kann, finden Sie hier:
Schreiben Sie eine Klasse "Lauflicht", die mindestens folgende Methoden besitzt:
//Festlegen eines Typs von Lauflicht der realisiert wird. //z.B. Mode0 == Alle LEDs leuchten gemeinsam auf und gehen im nächsten Zeitschritt wieder aus. //z.B. Mode1 == Lauflicht: Das Licht wandert von LED zu LED und beginnt dann wieder von vorne. //z.B. Mode2 == Zylon: Das Licht wandert hin und her. void setMode(int m) { ... } //Bei dem Aufruf von Timestep wird der nächste Zustand von Lauflicht umgesetzt, //egal in welchem Modus sich Lauflicht befindet. void timestep() { ... }
Code 0-5: Methoden der Klasse Lauflicht.
Schreiben Sie außerdem um die Klasse herum ein Testprogramm, das es dem Benutzer erlaubt z.B. über Tasten oder Befehle über die serielle Schnittstelle einen Mode auszuwählen und laufen zu lassen.
HINWEIS: Verwenden Sie nach Möglichkeit hauptsächlich Register-Befehle, um die Modes für das Lauflicht zu realisieren.
8
8 -- Dienstag 14.05.2019 (V)
Vorgehen: Erst spannende Anwendungen mit Hilfe der Arduino-Befehle aufbauen und dann in einem zweiten Durchgang schauen, was dahinter steckt. Dann ähnliche Funktionalität mittels direkten Registerkonfiguraionen durchführen.
Für die nachfolgenden Projekte stehen nicht alle Bauelemente in ausreichenden Mengen zur Verfügung. Die einzelnen Beispiele sollten in der Übung in unterschiedlichen Reihenfolgen durchgeführt und die Bauteile herumgereicht werden.
|
Beispiele:
|
Links:
40_Mikrocontroller/06_UART/01_Bussysteme -- Bussysteme (allgemein)
40_Mikrocontroller/13_I2C -- I2C mit ATmega32
40_Mikrocontroller/09_ADW/02_Zaehler -- Timer als Zähler (ATmega32)
96_Arduino/15_Scheduler -- Verwendung eines Software Interrupts ausgelöst durch Timer 1
96_Arduino/28_CTC -- CTC mit Arduino, s. insb Code 28-8.
96_Arduino/29_Tonerzeugung -- Tonerzeugung mit Arduino im CTC-Mode auf diversen Timern
45_Mikro17/12_Uebung2017 -- MPU6050 Beispiel.
void setup() { TCCR1B &= ~(1<<WGM13); //Mode 4 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //Vorteilung 1: 16000000Hz TCCR1B &= ~(1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B |= (1<<CS10); //f = fclk/(2*N*(OCR1A+1)) //OCR1A = (fclk/(f*2*N))-1 //OCR1A = 8000000/440 - 1 == 18181 OCR1A=18181; //0,5Hz == 4 Schläge! //Toggle auf OC1A: TCCR1A &= ~(1<<COM1A1); TCCR1A |= (1<<COM1A0); pinMode(9,OUTPUT); } void loop() { }
Code 0-6: CTC-Mode mit Arduino. Beispiel.
8 -- Donnerstag 16.05.2019 (Ü)
Setzen Sie folgende Versuche um: (Wählen Sie unterschiedliche Reihenfolgen der Versuche, damit die Bauteileuntereinander ausgetauscht werden können.)
|
9
9 -- Dienstag 21.05.2019 (V)
Vertiefung der letzte Woche angeschnittenen Themen. Heute:
|
void setup() { // ICR1 = fclk / (fctc*2*N) - 1 // ICR1 = 16000000 / (1000*2*64) - 1 = 124 TCCR1B = (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10); TCCR1A = (0<<WGM11) | (0<<WGM10) | (0<<COM1A1) | (1<<COM1A0); //ICR1 = 124;//TOP CTC MODE 12 (hat nicht funktioniert) OCR1A=124; // statt dessen Mode 4 DDRB |= (1<<PB5); } void loop() { }
Code 0-7: Lauffähiger Code für ein 1kHz Signal.
9 -- Donnerstag 23.05.2019 (Ü)
1) Ausprobieren des Sketches aus der letzten Vorlesung
2) In der Vorlesung wurden verschiedene Konzepte diskutiert, wie man mit Hilfe eines einzigen digitalen Ausgangs ein analoges Sinussignal erzeugen könnte. Wählen Sie eine dieser Ideen aus, die Ihnen am überzeugendsten erscheint und versuchen sie umzusetzen. Schicken Sie mir gerne Ihre Umsetzung gezipt per E-Mail.
10
10-- Dienstag 28.05.2019 (V)
|
interrupt.zip -- Beispiel Software-Interrupt aus der Vorlesung.
#include<avr/interrupt.h> volatile bool AN=false; volatile bool ZUSTAND=false; ISR(TIMER1_COMPA_vect) { if(ZUSTAND) digitalWrite(12,ZUSTAND); else digitalWrite(12,ZUSTAND); ZUSTAND=!ZUSTAND; } void setup() { TCCR1B &= ~(1<<WGM13); //Mode 4 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //1024: 15625Hz TCCR1B |= (1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B |= (1<<CS10); OCR1A=31250; //0,5Hz == 4 Schläge! TIMSK1 |= (1<<OCIE1A); //Mode 4 sei(); pinMode(12,OUTPUT); } void loop() { }
Code 0-8: interrupt - Sketch aus der Vorlesung
10 FEIERTAG (keine Vorlesung)
11
11-- Dienstag 04.06.2019 (V)
|
|
UHR003.zip
11 -- Donnerstag 06.06.2019 (Ü)
|
|
12
12-- Dienstag 11.06.2019 (V)
|
67_Echtzeitsysteme/01_Einfuehrung -- Einführung in die Echtzeitprogrammierung / Synchrone Programmierung
70_Echtzeitsysteme2 -- Verwendung eines Betriebssystems auf einem Mikrocontroller
|
Morse002.zip
Morse003.zip
Morse004.zip -- Umsetzung in Mordecode und Verwendung einer Interrupt Service Routine.
12 -- Donnerstag 13.06.2019 (Ü)
Schreiben Sie ein Programm, das eine serielle Schnittstelle emuliert: Es soll auf einem beliebigen digitalen Ausgang seriell daten herausschreiben. Diese sollten testweise von einem anderen Mikrocontroller an RxD (Serial1) empfangen und an den seriellen Monitor am PC weiter gereicht werden (Serial / Serial0).
Als Vorarbeit: Senden Sie erst einmal von einem Mikrocontroller über TxD zyklisch so etwas wie "Hallo" und versuchen es mit einem anderen Mikrocontroller zu empfangen. Versuchen Sie erst dann genau diese Signalfolge mit einem gewöhnlichen digitalen Ausgang zu emulieren.
13
13-- Dienstag 18.06.2019 (V)
|
|
Serialemu002c.zip -- Seriell Daten auf beliebigem Pin empfangen.
Bild 0-1: Planung des Serialemu-Moduls.
#include<avr/interrupt.h> bool wort[] = {1,1,1,0,1,0,0,0,0,0,1,0,1,1,1,1}; int inx = 0; ISR(TIMER1_COMPA_vect) { digitalWrite(13,wort[inx]); inx++; inx%=16; } void setup() { TCCR1B &= ~(1<<WGM13); //Mode 4 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //1024: 15625Hz //1: 16000000Hz TCCR1B &= ~(1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B |= (1<<CS10); OCR1A=1667; //16000000Hz == 1 => 9600Hz == 1667 TIMSK1 |= (1<<OCIE1A); //Mode 4 sei(); Serial.begin(9600); Serial1.begin(9600); pinMode(13,OUTPUT); digitalWrite(13,HIGH); } void loop() { if(Serial1.available()) { Serial.write(Serial1.read()); } }
Code 0-9: Serialemu001, senden
#include<avr/interrupt.h> #define LESEPIN 13 #define PUFFERGROESSE 100 //Serielle Daten über die emulierte Schnittstelle empfangen! int leseindex = 0; bool liestgerade = false; int zeichen; char inpuffer[PUFFERGROESSE]; int inindex = 0; int inindey = 0; int x=0; int zaehler=0; ISR(TIMER1_COMPA_vect) { if(liestgerade==false && digitalRead(LESEPIN)==LOW) { leseindex = 0; zeichen = 0; liestgerade = true; } if(liestgerade==true) { if(leseindex==12 && digitalRead(LESEPIN)==HIGH) zeichen+=1; if(leseindex==12+8 && digitalRead(LESEPIN)==HIGH) zeichen+=2; if(leseindex==12+16 && digitalRead(LESEPIN)==HIGH) zeichen+=4; if(leseindex==12+24 && digitalRead(LESEPIN)==HIGH) zeichen+=8; if(leseindex==12+32 && digitalRead(LESEPIN)==HIGH) zeichen+=16; if(leseindex==12+40 && digitalRead(LESEPIN)==HIGH) zeichen+=32; if(leseindex==12+48 && digitalRead(LESEPIN)==HIGH) zeichen+=64; if(leseindex==12+56 && digitalRead(LESEPIN)==HIGH) zeichen+=128; if(leseindex>=12+64) { liestgerade=false; inpuffer[inindex] = zeichen; inindex++; inindex%=PUFFERGROESSE; } leseindex++; } } void setup() { TCCR1B &= ~(1<<WGM13); //Mode 4 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //1024: 15625Hz //1: 16000000Hz TCCR1B &= ~(1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B |= (1<<CS10); //8fach: // OCR1A=208; //16000000Hz == 1 => 8*9600Hz == 208,3333 //Glatte Teiler: OCR1A=250; //16000000Hz == 1 => 8*8000Hz == 250 // OCR1A=1667; //16000000Hz == 1 => 9600Hz == 1667 TIMSK1 |= (1<<OCIE1A); //Mode 4 sei(); pinMode(LESEPIN,INPUT); digitalWrite(LESEPIN,HIGH); //macht Sinn, um ohne Verbindung High-Potential zu gewährleisten Serial1.begin(8000); Serial.begin(8000); } void loop() { if(zaehler>10000) { Serial1.write('A'+x); x++; x%=10; zaehler=0; } //delay(100); if(inindex != inindey) { Serial.write(inpuffer[inindey]); inindey++; inindey%=PUFFERGROESSE; } zaehler++; }
Code 0-10: Serialemu002c, empfangen
13 -- Donnerstag 20.06.2019 (2. E-TEST)
2. E-TEST (IWZ135 8:30-10:00)
14
14-- Dienstag 25.06.2019 (V)
|
14 -- Donnerstag 27.06.2019 (Ü)
Thema: HIL -- Hardware In the Loop
Auf der Basis von Arduino und Processing soll das Prinzip HIL praktisch erarbeitet werden. Dies soll in zwei Stufen geschehen.
Erste Stufe:
|
Zweite Stufe:
|