kramann.info
© Guido Kramann

Login: Passwort:










kramann.info
© Guido Kramann

Login: Passwort:




Grundlagen der Mikrocontrollertechnik im Sommersemester 2026

(EN google-translate)

(PL google-translate)

  • Nachfolgend wird im Verlauf des Semesters chronologisch vermerkt, welche Inhalte wann im Semester durchgenommen wurden.
  • Sie finden die Lehrinhalte entweder direkt hier, oder es werden hier Links auf die Inhalte angegeben.
  • Obwohl die Inhalte zum Kurs hier stehen, wird darum gebeten sich trotzdem im entsprechenden Moodle-Kurs der THB anzumelden, um besser kommunizieren zu können.
  • Beachten Sie auch die Angaben zur Prüfung hier:

04_SoSe2026 -- Einstiegsseite zum Sommersemester 2026 mit Angaben zu Räumen, Zeiten und den Prüfungen der einzelnen Fächer.

#1 Di, 24.03.2026


THEMEN HEUTE

  1. Worum geht es?
  2. Motivation -- Warum ist das wichtig?
  3. Welche Themen werden behandelt?
  4. Welche Leistungen sollten Sie erbringen? / Organisatorisches
  5. Einstieg
  6. Hands on -- Die erste Übung

1. Worum geht es?

Mikrocontroller sind aus der heutigen Welt nicht mehr wegzudenken. Sie bilden typischerweise das Kernstück s.g. Eingebetteter Systeme. Das sind technische Komponenten, die typischerweise dauerhaft steuer- und regelungstechnische Aufgaben in technischen Systemen übernehmen, die zuvor von elektronischen, bzw. elektromechanischen Komponenten übernommen wurden.

2. Motivation -- Warum ist das wichtig?

Viele Aufgaben, die zuvor durch mechanische Systeme übernommen wurden, wurden zunächst durch Elektromechanische Systeme ersetzte und noch später durch Eingebettete Systeme. Der Vorteil dieser Entwicklung liegt vor allem darin, dass das Verhalten der Eingebetteten Systeme durch ein Computerprogramm festgelegt wird und nicht mehr durch elektronische Schaltungen, oder mechanische Komponenten. Dadurch können die gleichen Grundsysteme in sehr vielen Geräten eingesetzt werden. Was sie voneinander unterscheidet ist dann das Programm, dass auf ihnen läuft. Das wiederum hat zur Folge, dass Mikrocontroller in sehr hohen Stückzahlen hergestellt werden können und damit eine sehr preiswerte Produktion möglich wird.

Zudem können Updates, Anpassungen und Fehlerbehebungen oft einfach durch eine Veränderung der Software, die auf dem System läuft vorgenommen werden, anstatt eine neue Schaltung zu entwickeln, oder eine neue Mechanik entwickeln zu müssen.

Eingebettete Systeme finden Sie beispielsweise...

  • in Kühlschränken, Waschmaschinen und anderen Haushaltsgeräten,
  • in Autos, Zügen und anderen elektrifizierten Fortbewegungsmitteln,
  • in der Haustechnik in Industriegebäuden, aber auch in Privathaushalten.

Als exemplarisches Beispiel für die Einsatzmöglichkeit eines Mikrocontrollers, sieht man hier, wie dieser werden kann, um einfache regelungstechnische Aufgaben bei kleinen autonomen Vehikeln zu übernehmen, um eine Linie zu verfolgen, oder auf einer Achse zu balancieren:

Schwarmvehikel, die eine Linie verfolgen können und auf das Auftauchen von Hindernissen reagieren.

Bild 0-1: Schwarmvehikel, die eine Linie verfolgen können und auf das Auftauchen von Hindernissen reagieren.

https://youtu.be/YS-1RRLGtgQ -- Schwarmvehikel

Einachser (Vehikel, das auf einer Achse balanciert)

Bild 0-2: Einachser (Vehikel, das auf einer Achse balanciert)

https://youtu.be/WnBl7eEdbMg -- Einachser
ÜBUNG

Versuchen Sie die nachfolgenden Fragen zu beantworten:

  1. Wie funktioniert der Einachser?
  2. Wie wird insbesondere die relative Verkippung des Chassis gemessen?

3. Welche Themen werden behandelt?

  • Prinzipieller Aufbau eines Mikrocontrollers
  • Kennenlernen der internen Peripherie eines Mikrocontrollers
  • Programmierung mittels Arduino-Befehlen in C/C++
  • Programmierung mittels Register-Befehlen in C/C++
  • Aufbau einfacher elektronischer Schaltungen mit Mikrocontroller auf einem Steckboard

4. Welche Leistungen sollten Sie erbringen? / Organisatorisches

  • Die Prüfung findet semesterbegleitend in Form eines E-Tests (elektronische Klausur) statt.
  • Die Prüfung findet am letzten Vorlesungstermin an den PCs unter Linux statt.
  • In der Woche davor findet ein nicht benoteter Probe-E-Test statt und wird da auch unmittelbar danach besprochen.

Neben dieser Prüfung wird es Miniprojekte geben, die in Zweiergruppen zu bearbeiten sind und die dazu dienen sollen, die erlernte Theorie anzuwenden.

  • Es wird Themenvorschläge für die Miniprojekte geben, aber es können auch eigene Projektthemen vorgeschlagen werden.

5. Einstieg

  • Worin besteht der Unterschied zwischen einem Mikrocontroller und einem PC?
40_Mikrocontroller/01_Einfuehrung/02_Maschinensprache -- Unterschied zwischen Mikrocontroller und PC

  • Woher stammt die Grundidee eines Computers?
40_Mikrocontroller/01_Einfuehrung/01_Entwicklungsgeschichtliches -- Grundidee eines Computers

  • Was sind Registerbefehle und was hat das mit Mikrocontrollern zu tun?
40_Mikrocontroller/01_Einfuehrung/03_Assemblerbeispiel -- Registerbefehle

  • Wie sieht ein erstes Computerprogramm für einen Arduino Mikrocontroller aus und wie bringt man es zum Laufen?
96_Arduino/02_Taster -- Computerprogramm für einen Arduino Mikrocontroller

  • Wie sieht ein entsprechendes Registerbefehl-basiertes Programm aus?
01_Einfuehrung/05_Praxis/01_Digital_IO -- Übersicht zu Registerbefehlen im Zusammenhang mit digitalen Ein- und Ausgängen

40_Mikrocontroller/01_Einfuehrung/05_Praxis/02_Byteoperationen -- Registerbefehl-basiertes Programm

96_Arduino/22_Universal/02_LED_Leiste -- PORTB beim Arduino Micro
6. Hands on -- Die erste Übung
Aufgabe 1
  • Bauen Sie die Schaltung mit den Tastern auf und übertragen das Programm auf der folgenden Seite und testen es:
96_Arduino/02_Taster
  • Weitere Aufgaben, die in Zweiergruppen gelöst werden sollen:
Aufgabe 2
  • Bauen Sie die Schaltung bei LED Leiste auf.
  • Testen Sie alle LEDs mit folgendem Programm:
96_Arduino/22_Universal/02_LED_Leiste -- PORTB beim Arduino Micro
void setup() 
{
}

void loop() 
{
    DDRB = 255;
    PORTB = 255;
}

Code 0-1: Testprogramm.

void setup() 
{
}

void loop() 
{
    DDRB = 255;
    

    PORTB = 1;
    delay(100);
    PORTB = 2;
    delay(100);
    PORTB = 4;
    delay(100);
    PORTB = 8;
    delay(100);
    PORTB = 16;
    delay(100);
    PORTB = 32;
    delay(100);
    PORTB = 64;
    delay(100);
    PORTB = 128;
    delay(100);
}

Code 0-2: Lauflicht Musterlösung 2

void setup() 
{
    DDRB = 255;
    PORTB = 255;
}

int x = 0;
void loop() 
{
    DDRB = 255;

    PORTB = 1<<x;
    x++;
    x%=8;
    delay(100);
}

Code 0-3: Lauflicht Musterlösung 2.

  • Der Befehl delay(x); erlaubt es, den Mikrocontroller für die angegebene Zeitdauer x in Millisekunden pausieren zu lassen.
  • Unter Verwendung dieses Befehls ist es möglich, Blinken oder auch ein Lauflicht umzusetzen. -- Versuchen Sie das.


#2 Di, 31.03.2026

Themen diese Woche:

  1. Quiz
  2. Die Schildkröten des Walter Grey
  3. Angaben zur Syntax von C/C++ bei der Mikrocontrollerprogrammierung
  4. Basisregister für die Programmierung digitaler Ein- und Ausgänge
  5. Bitoperationen zur Manipulation von Mikrocontroller-Registern
  6. Umsetzung eines Lauflicht-Programms auf der Basis von Mikrocontroller-Registern in Kombination mit Bitoperationen
  7. ÜBUNG

1. Quiz

  • Nennen Sie Anwendungsbereiche für Mikrocontroller.
  • Worin unterscheiden sich Mikrocontroller von PC-Systemen?
  • Wieviele Bussysteme besitzt der Mikrocontroller ATmega32u4 und für was sind diese jeweils verantwortlich?

2. Die Schildkröten des Walter Grey

Motivation / Diskussion ... Grey Walter's tortoises 1949
  • Durch die Verwendung von Mikrocontrollern werden vormals rein mechanische und elektromechanische Geräte, beispielsweise solche aus dem Haushaltsbereich wie Herd, Kühlschrank usw., zu sehr viel preiswerter herzustellenden anteilig mehr elektronischen Geräten.
3. Eingebettete Systeme auf Wikipedia.
"... Im Februar 2021 erklärtedie Bundesregierung, nach ihrer Kenntnis seien Lieferengpässe bei Halbleitern und Halbleiter-Chips für die Automobilindustrie primär entstanden, weil es weltweit nur eine sehr begrenzte Zahl von Herstellern gebe, welche die von der Automobilindustriebenötigten Halbleiter-Chips fertigten. Zudem könnten deren Produktionskapazitäten kurzfristig nicht ausgeweitet werden. Zu Prognosen und Umsatzanalysenbei Halbleitern äußerte die Bundesregierung, laut Prognosen werde sich der weltweite Umsatz an Halbleiterchips im Jahr 2024 auf 532 Mrd. US Dollar erhöhen (rund 22% höher als in 2019). Asien (inkl. China) werde mit 62% der größte Chipabnehmer sein, gefolgt von Amerika mit rund 21% und Europa rund 9%. Aus Sicht der Halbleiterfertigung (ohne die sog. Foundries -Fertigungsdienstleister) sei die USA mit 50% dominierend am Umsatz beteiligt, gefolgt von Südkorea (18%), Japan (10%), Europäische Union (9%), Taiwan (6%) und China (5%). Ein anderes Bild ergebe sich, wenn die Foundries in der Analyse berücksichtigt würden. Mit rund 76% kontrollierten China, Taiwan, Südkorea und Japan den Halbleiterumsatzmarkt. Die USA falle mit 11% zurück, gefolgt von der Europäischen Union mit 8% und Singapur mit 5%.... "

zu 4. Quelle: Bundestag Einzelanfrage: Einzelfragen zurHalbleiterproduktion, Seite 10. Web 21.03.2023: https://www.bundestag.de/resource/blob/900450/25b9b36d92928f932b242efc8578386a/WD-5-004-22-pdf-data.pdf

Hersteller in Europa: NXP, ST, Infineon. Japan: Renesas. USA: Microchip.

3. Angaben zur Syntax von C/C++ bei der Mikrocontrollerprogrammierung

4. Basisregister für die Programmierung digitaler Ein- und Ausgänge

  • Zur Realisierung digitaler Eingänge steht der Arduino-Befehl digitalRead(int nummer) zur Verfügung.
  • Verwendung mittels Registern:
Verwendung der internen Pullup-Widerstände -- 40_Mikrocontroller/03_DigitalIO/02_Pullup_Widerstaende
Bitmasken für den Eingang -- 40_Mikrocontroller/03_DigitalIO/03_Bitmasken_Eingang
Schaltung.

Bild 0-3: Schaltung.

BEISPIELPROGRAMME: Mit oberer Taste untere LED steuern:
void setup() 
{
    pinMode(11,OUTPUT);
    //digitalWrite(11,HIGH);

    pinMode(8,INPUT);
    digitalWrite(8,HIGH);//Pullup
}

void loop() 
{
     if(digitalRead(8)==0)
        digitalWrite(11,HIGH);
     else   
        digitalWrite(11,LOW);
}

Code 0-4: Arduino-Befehls-Variante.

void setup() 
{
    //pinMode(11,OUTPUT);
    DDRB = DDRB | 0b10000000; // PB7 auf 1 setzen

    //pinMode(8,INPUT);
    DDRB = DDRB & 0b11101111; // PB4 auf 0 setzen
    //digitalWrite(8,HIGH);//Pullup
    PORTB = PORTB | 0b00010000; // PB4 setzen, PULLUP 
}

void loop() 
{
     if( (PINB & 0b00010000) == 0  )
        PORTB = PORTB | 0b10000000;
     else   
        PORTB = PORTB & 0b01111111;
}

Code 0-5: Register-Befehls-Variante.

5. Bitoperationen zur Manipulation von Mikrocontroller-Registern

& bitweise logische UND-Verknüpfung
| bitweise logische ODER-Verknüpfung
~ NICHT (Invertieren aller Bits)
<< Links-Shift-Operator:   x=1<<3;  //Beispiel shiftet die 1 dreimal nach links, ergibt dezimal 8.
>> Rechts-Shift-Operator:  y=12>>1; //Beispiel shiftet die 12 einmal nach rechts, ergibt dezimal 6, entspricht Division durch 2.

Code 0-6: Liste mit Bitoperationen

Manipulation einzelner Bits bei Register-Befehlen durch Verwendung von Bitmasken

void setup() 
{
  //DDRB = 0b10000000; //PB7 als Ausgang konfigurieren.
  //NUR PB7 setzen, ohne die anderen Bits zu verändern!:
  DDRB = DDRB | 0b10000000; //Bitweises ODER-Verknüpfen eines Registers mit einer Bitmaske
}

void loop() {
  PORTB = PORTB | 0b10000000;  // 5 Volt auf Digitalpin 11 'rausschicken, bzw. auf PB7
  delay(500);
  PORTB = PORTB & 0b01111111;
  delay(500);
}

Code 0-7: Nur höchstwertigstes Bit manipulieren (PB7), mit Hilfe von Bitmasken und Bitoperationen.

6. Umsetzung eines Lauflicht-Programms auf der Basis von Mikrocontroller-Registern in Kombination mit Bitoperationen

7. ÜBUNG

Aufgabe 1

Bauen Sie die angegebene Schaltung ohne den Entfernungssensor auf und testen die weiter oben besprochenen Programme:

Schaltung.

Bild 0-4: Schaltung.

Aufgabe 2

  • Verwenden Sie erneut die bereits aufgabaute Grundschaltung.
  • Programmieren Sie eine Art Fußgängerampel auf der Grundlage von Arduino-Befehlen:
  • Normalerweise leuchtet die rote LED und die grüne ist aus.
  • Wird aber der obere Taster kurz betätigt, leuchtet für circa zwei Sekunden die grüne LED und die rote geht aus.

Aufgabe 3

  • Ersetzen Sie nun möglichst viele Programmteile der vorangehenden Aufgabe 2 durch Registerbefehle.

Di, 07.04.2026 -- keine Lehrveranstaltung wegen Ostern


#3 Di, 14.04.2026

Themen heute:

  1. Lösungen zur Fussgängerampel-Aufgabe
  2. Bussysteme
  3. Die UART Schnittstelle
  4. Übung Datenaustausch zwischen zwei Mikrocontrollern

1. Lösungen zur Fussgängerampel-Aufgabe

void setup() 
{
    pinMode(10,OUTPUT);
    pinMode(11,OUTPUT);
    digitalWrite(10,HIGH);

    pinMode(8,INPUT);
    digitalWrite(8,HIGH);//Pullup
}

void loop() 
{
     if(digitalRead(8)==0)
     { 
        digitalWrite(11,HIGH);
        digitalWrite(10,LOW);
         delay(2000);
        digitalWrite(10,HIGH);
        digitalWrite(11,LOW);}
     else    
     { 
         digitalWrite(10,HIGH);
     }
}

Code 0-8: Studentische Lösung.

void setup() 
{
    //pinMode(10,OUTPUT);
    //pinMode(11,OUTPUT);
    DDRB = DDRB | 0b11000000; // PB6 und PB7 auf 1 setzen

    //pinMode(8,INPUT);
    DDRB = DDRB & 0b11101111; // PB4 auf 0 setzen
    //digitalWrite(8,HIGH);//Pullup
    PORTB = PORTB | 0b00010000; // PB4 setzen, PULLUP 
}

void loop() 
{
     if( (PINB & 0b00010000) == 0  )
     {
      PORTB = PORTB | 0b10000000;
      PORTB = PORTB & 0b10111111;
         delay(2000);
      PORTB = PORTB & 0b01111111;
      PORTB = PORTB | 0b01000000;
     }
     else   
     {
          PORTB = PORTB | 0b01000000;
     }
}

Code 0-9: Studentische Lösung mit Registerbefehlen.

2. Bussysteme

Bussysteme -- 40_Mikrocontroller/06_UART/01_Bussysteme

3. Die UART Schnittstelle

UART - Universal Asynchronous Receiver Transmitter -- 40_Mikrocontroller/06_UART
UART -- 40_Mikrocontroller/06_UART/02_UART
RS232 -- 40_Mikrocontroller/06_UART/03_RS232
Hardware - Verbinden eines ATmega32 mit einem PC über die RS232 Schnittstelle -- 40_Mikrocontroller/06_UART/04_Hardware
Senden -- 40_Mikrocontroller/06_UART/05_Senden

4. Übung Datenaustausch zwischen Mikrocontroller und Arduino

  • Die Serielle Schnittstelle wird in der USB-Verbidnung zum PC emuliert.
  • Es existiert in der Arduino IDE ein "Serial Monitor" mit dem Daten zwischen IDE und Arduino ausgetauscht werden können.
  • Diese Schnittstelle eignet sich sehr gut, um eine Art Wartungsschnittstelle zu erstellen, die einen Einblick in das Funktionieren des Arduino ermöglicht.
  • Zunächst wird mit Hilfe der Beispiele auf der Arduino-Seite ein Programm entwickelt, das zyklisch "Hallo!" vom Arduino an den PC sendet.
  • Dann wird ein Programm entwickelt, bei dem durch Senden des Zeichens 1 vom PC aus eine LED beim Arduino an geht und mit 0 ausgeschaltet wird.

Damit die Übetragung nicht zu schnell läuft, wird die delay-Funktion benötigt.


void setup() 
{
    Serial.begin(9600);
}

void loop() 
{
    Serial.write('H');
    Serial.write('a');
    Serial.write('l');
    Serial.write('l');
    Serial.write('o');
    Serial.write('!');
    Serial.write('\n');
    delay(500);
}

Code 0-10: Im Unterricht entwickeltes Programm "Hallo!".

void setup() 
{
     DDRB  |= 0b10000000;
     PORTB &= 0b01111111;
     Serial.begin(9600);
}

void loop() 
{
    if(Serial.available())
    {
         int x = Serial.read();
         if(x=='1')
         {
             PORTB |= 0b10000000;
         }
         else if(x=='0')
         {
             PORTB &= 0b01111111;
         }
    }
  
}

Code 0-11: Im Unterricht entwickeltes Programm LED Fernsteuerung.

AUFGABE 1
  • Grundlage bildet wieder die Beschaltung mit zwei Schaltern bei PB4 und PB5 und zwei LEDs bei PB10 und PB11 (Bild 4-4 oben, wieder ohne den Entfernungssensor).
  • Zunächst: Schalter PB4 schaltet die LED bei PB6 an und aus, Schalter PB5 die LED bei PB7.
  • Wenn der Schalter jeweils geschlossen ist, soll die zugehörige LED lauchten und sonst aus sein.
  • Der PC soll nun ständig über den Zustand der Schalter informiert werden, deren Zustand binär kodiert wird:
Schalter PB5 geschlossen Schalter PB4 geschlossen an PC senden
NEIN NEIN 0
NEIN JA 1
JA NEIN 2
JA JA 3

Tabelle 0-1: Binäre Kodierung der Schalterzustände.

  • Setzen Sie das entsprechende System um.
AUFGABE 2
  • Die LEDs von Aufgabe 1 sollen nun "ferngesteuert" werden:
  • Der Code aus der Tabelle oben wird nun vom PC an den Arduino gesendet.
  • Die LEDs sollen entsprechend der Tabelle reagieren.
  • Die Schalter werden hier nicht benötigt.
AUFGABE 3
  • Lassen Sie sich einen Sharp Infrarot-Entfernungssensor aushändigen.
  • Finden Sie auf den Arduino Seiten heraus, wie das Auslesen von Analogwerten funktioniert (analogRead-Funktion).
  • Finden Sie auf den Arduino Seiten heraus, wie seriell ganze Zahlen gesendet werden können.
  • Setzen Sie ein System um, bei dem die eingelesenen Werte des Sensors am seriellen Monitor angezeigt werden.

#4 Di, 21.04.2026

Themen heute:

  1. Besprechung der Übungsaufgaben von letzter Woche
  2. Objektorientierte Programmierung mit dem Arduino Mikrocontroller
  3. Anwendungsbeispiel Bussysteme: Verbindung zu einem IMU-Sensor (MPU6050)
  4. Übungen

1. Besprechung der Übungsaufgaben von letzter Woche

void setup() 
{
   DDRD = DDRB | 0b11000000;
   // DDRD |= 0b11000000;
   PORTB = PORTB & 0b00111111;
   Serial.begin(9600);
}

void loop() 
{
    //   0   1   2   3 
    //  00  01  10  11
    if(Serial.available()>0)
    {
        int incomingByte = Serial.read();
        Serial.print("I recerived: ");
        Serial.println((char)incomingByte);

        if(incomingByte=='0')
        {
            PORTB = PORTB & 0b00111111;
        }
        else if(incomingByte=='1')
        {
            PORTB = PORTB & 0b01111111; //PB7 aus
            PORTB = PORTB | 0b01000000; //PB6 an            
        }
        else if(incomingByte=='2')
        {
            PORTB = PORTB & 0b10111111; //PB6 aus
            PORTB = PORTB | 0b10000000; //PB7 an            
        }
        else if(incomingByte=='3')
        {
            PORTB = PORTB | 0b11000000; //PB6 und PB7 an            
        }
        
    }
}

Code 0-12: Fernsteuern zweier LEDs studentische Lösung.

void setup() 
{
   DDRD = DDRB | 0b11000000;
   // DDRD |= 0b11000000;
   PORTB = PORTB & 0b00111111;
   Serial.begin(9600);
}

void loop() 
{
    //   0   1   2   3 
    //  00  01  10  11
    if(Serial.available()>0)
    {
        int incomingByte = Serial.read();
        Serial.print("I recerived: ");
        Serial.println((char)incomingByte);
        // '0'==48 '1'==49 '2'==50 '3'==51
        // incomingByte - '0'; =>
        //       0       1       2       3
        //      00      01      10      11
        //  00000011 ist
        //  11000000 soll
        incomingByte = incomingByte - '0'; // '0'==48
        //PORTB = incomingByte << 6;
        //Untere 6 Bits nicht manipulieren:
        PORTB |= (incomingByte << 6);
        PORTB &= (incomingByte << 6) + 0b00111111;
        
    }
}

Code 0-13: Zweite Lösung unter Verwendung von Bitshiftoperatoren.

2. Objektorientierte Programmierung mit dem Arduino Mikrocontroller

40_Mikrocontroller/08_OOP -- Motivation zu OOP.
40_Mikrocontroller/08_OOP/01_Probleme -- was es im Zusammenhang mit Mikrocontrollern bei OOP zu beachten gilt.
40_Mikrocontroller/08_OOP/02_Konzept -- Grundkonzept Singleton als UML-Klassendiagramm.

3. Anwendungsbeispiel Bussysteme: Verbindung zu einem IMU-Sensor (MPU6050)

Verwendung eines IMU vom Typ MPU6050 über das I2C (aus patentrechtlichen Gründen im Datenblatt TWI -- Two Wire Interface -- genannt) Bussystem genannt

  • IMU-Sensoren sind in Mobile Devices weit verbreitet.
  • Sie dienen beispielsweise dazu, die Orientierung des Gerätes im Raum zu ermitteln, Headtracking und Schritte zählen zu ermöglichen, das Benutzerverhalten zu erfassen.
  • Beim verwendeten Chip stehen drei orthogonale translatorische Beschleunigungen zur Verfügung und drei Winkelgeschwindigkeiten.
  • Der Abruf erfolgt über eine Anfrage per I2C
  • Beispielcode zum Testen des MPU6050, siehe hier:
96_Arduino/31_day_by_day -- siehe "Verwendung eines MPU6050 Beschleunigungssensors"
15_Einachser/02_Bauanleitung/06_MPU6050 -- Anwendungsfall Einachser
https://youtu.be/WnBl7eEdbMg -- Video zum Einachser

4. Übungen

Aufgabe 1 (gemeinsam)
-------------
|LED         |
-------------
|+on() : bool|
|+off(): bool|
-------------


Code 0-14: UML Klassendiagramm zur LED Klasse

  • Setzen Sie die im UML-Klassendiagramm dargestellte LED-Klasse um und testen sie.
30_Informatik3/02_UML/02_UML_Klassendiagramm

Variante:
#include "Led.h"

Led gruen(7);
Led rot(6);

void setup() 
{
     Serial.begin(9600);
}

void loop() 
{
     if(Serial.available())
     {
          int zeichen = Serial.read();
          if(zeichen=='r')
          {
               rot.on();
               gruen.off();
          }
          else if(zeichen=='g')
          {
               rot.off();
               gruen.on();
          }
     }
}

Code 0-15: Hauptprogramm.

class Led
{
    public:
       Led(int aktuellesBit)
       {
           meinBit = aktuellesBit;
       }

       void on()
       {
          PORTB |= (1<<meinBit);
       }
       void off()
       {
          PORTB &= ~(1<<meinBit); // ~ Tilde invertiert bitweise das Bitmuster
       }

    private:
       int meinBit;
};

Code 0-16: Klasse in Led.h

LEDoop2.zip -- Obige Variante.
Aufgabe 2
  • Zur leichteren Benutzung des IMU:
  • Kapseln sie dessen Funktionalität in einer Klasse, so, wie es im folgenden UML-Klassendiagramm dargestellt ist und testen es.
  • Lassen Sie sich für den Test die Beschleunigungswerte im Seriellen Monitor anzeigen.
-------------
|IMU         |
-------------
|+start()    |
|+acx(): int |
|+acy(): int |
|+acz(): int |
-------------


Code 0-17: UML Klassendiagramm zur IMU Klasse

Aufgabe 3
  • Auf Grundlage der in der Aufgabe 2 entwickelten objektorientierten Klasse, soll folgendes System umgesetzt werden:
  • Verkippwarnung: Solange die Platine mehr als 10 Grad verkippt wird, soll eine rote Warnleuchte angehen.
#include<math.h>
#include<Wire.h>

//MPU6050:
const int MPU=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ;
int x,y,z;

void setup() 
{
    //MPU6050
    Wire.begin();
    Wire.beginTransmission(MPU);
    Wire.write(0x6B);  // PWR_MGMT_1 register
    Wire.write(0);     // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);  
    Serial.begin(9600);

    pinMode(12,1);
    digitalWrite(12,0);
}

void loop() 
{
     // put your main code here, to run repeatedly:
     Wire.beginTransmission(MPU);
     Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
     Wire.endTransmission(false);
     Wire.requestFrom(MPU,6,true);  // request a total of 14 registers
     AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
     AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
     AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

     x = (AcX/163);
     if(x>100) x=100;
     if(x<-100) x=-100;

     y = (AcY/163);
     if(y>100) y=100;
     if(y<-100) y=-100;

     z = (AcZ/163);
     if(z>100) z=100;
     if(z<-100) z=-100;

     Serial.print(x);
     Serial.print(" ");
     Serial.print(y);
     Serial.print(" ");
     Serial.println(z);


     if(z<90)
        digitalWrite(12,1);
     else   
        digitalWrite(12,0);
     delay(200);
}

Code 0-18: Musterlösung Verkippwarner nicht objektorientiert.

OOP Lösung
#include<math.h>
//#include<Wire.h>
#include "IMU.h"

IMU imu; //  Singleton

int x,y,z;

void setup() 
{
    Serial.begin(9600);

    imu.start();

    pinMode(12,1);
    digitalWrite(12,0);
}

void loop() 
{
     // put your main code here, to run repeatedly:
     imu.update();

     x = (imu.getacx()/163);
     if(x>100) x=100;
     if(x<-100) x=-100;

     y = (imu.getacy()/163);
     if(y>100) y=100;
     if(y<-100) y=-100;

     z = (imu.getacz()/163);
     if(z>100) z=100;
     if(z<-100) z=-100;

     Serial.print(x);
     Serial.print(" ");
     Serial.print(y);
     Serial.print(" ");
     Serial.println(z);


     if(z<90)
        digitalWrite(12,1);
     else   
        digitalWrite(12,0);
     delay(200);
}

Code 0-19: Hauptprogramm.

#include<Wire.h>

class IMU
{
   private:
      //MPU6050:
      const int MPU=0x68;  // I2C address of the MPU-6050
      int16_t AcX,AcY,AcZ;
  
   public:
      void start()
      {
        //MPU6050
        Wire.begin();
        Wire.beginTransmission(MPU);
        Wire.write(0x6B);  // PWR_MGMT_1 register
        Wire.write(0);     // set to zero (wakes up the MPU-6050)
        Wire.endTransmission(true);          
      }

      void update()
      {
        Wire.beginTransmission(MPU);
        Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
        Wire.endTransmission(false);
        Wire.requestFrom(MPU,6,true);  // request a total of 14 registers
        AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
        AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
        AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)        
      }

      int getacx()
      {
           return AcX;
      }
      int getacy()
      {
           return AcY;
      }
      int getacz()
      {
           return AcZ;
      }
};

Code 0-20: IMU.h

IMUtest002.zip -- OOP Projekt.

#5 Di, 28.04.2026

Themen heute:

  1. Besprechung studentischer Lösungen zu Klasse für IMU und Verkippwarner.
  2. Wiederholung OOP
  3. Das Datenblatt zum ATmega32u4
  4. Register zu DIO im Datenblatt
  5. Einführung zu Timer
  6. Der 16-Bit Timer 1 im ATmega32u4 im Datenblatt
  7. PWM mittels Registerkonfiguration / PWM allgemein
  8. Übungen mit Modellbau-Servos

1. Besprechung studentischer Lösungen zu Klasse für IMU und Verkippwarner.

Siehe: Code 0-6: MPU6050 testen. Hier: 96_Arduino/31_day_by_day

2. Wiederholung OOP

40_Mikrocontroller/08_OOP
96_Arduino/24_OOP

3. Das Datenblatt zum ATmega32u4

96_Arduino
kramann.info/96_Arduino/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf

4. Register zu DIO im Datenblatt

96_Arduino/22_Universal/02_LED_Leiste
40_Mikrocontroller/03_DigitalIO
45_Mikro17/03_DigitalIO

5. Einführung zu Timer

45_Mikro17/04_Timer/01_Generierung

6. Der 16-Bit Timer 1 im ATmega32u4 im Datenblatt

45_Mikro17/04_Timer/02_Timer1_Servo

7. PWM mittels Registerkonfiguration / PWM allgemein

40_Mikrocontroller/04_PWM/01_Prinzip
40_Mikrocontroller/04_PWM/02_Nutzen
40_Mikrocontroller/04_PWM/08_LoesungUE3 -- Servos
45_Mikro17/04_Timer/02_Timer1_Servo

8. Übungen mit Modellbau-Servos

Aufgabe 1
  • Bauen Sie eine Servo-Schaltung gemäß des Arduino-Beispiels auf und testen den Beispielcode "sweep":
https://projecthub.arduino.cc/hockey1alex/servo-sweep-1a24d6
Aufgabe 2
  • Bauen Sie eine Servo-Schaltung passend zu folgendem Beispielcode auf und testen das Programm hier:
Code Code 0-1: Datei servofein.ino hier: 45_Mikro17/04_Timer/02_Timer1_Servo
Aufgabe 3
  • Kapseln Sie die Servo-spezifischen Programmteile aus Aufgabe 2 in einer Klasse MeinServo
  • Die Funktionalität des Programms soll gleich bleiben.
  • Überlegen Sie gut, was in die Klasse kommt und was im loop-Teil bleiben sollte.
  • Testen Sie Ihre Lösung.
Aufgabe 4
  • Suchen Sie mit Hilfe des Datenblatts nach Möglichkeiten eine noch genauere Servo-Ansteuerung hinzubekommen, als die von Aufgabe 2 und setzen sie um.

#6 Di, 05.05.2026

Themen heute: Vertiefung Timer Konfiguration

  1. Ergänzungen zur Analyse des PWM-Gebers mit Timer 1
  2. Möglichkeit einer genaueren Servo-Ansteuerung (Aufgabe 4 letzte Woche)
  3. Timer 1 und CTC-Mode
  4. Effiziente Echtzeit-Programmierung mittels State-Machine
  5. Übungen

1. Ergänzungen zur Analyse des PWM-Gebers mit Timer 1

  • Analyse aller beteiligten Konfigurationsregister

2. Möglichkeit einer genaueren Servo-Ansteuerung (Aufgabe 4 letzte Woche)

  • Überprüfung der Möglichkeit mit einer niedrigeren Vorteilung zu arbeiten

3. Timer 2 und CTC-Mode

45_Mikro17/10_ADW/02_Zaehler -- Timer als frei laufender Zähler

ACHTUNG: while(TCNT2<36); wird womöglich vom Compiler wegrationalisiert. Besser: while(TCNT2<36) PORTB|=PORTB;


4. Effiziente Echtzeit-Programmierung mittels State-Machine

  • Das Sweep-Beispiel bei Arduino ist extrem ineffizient programmiert, da es nicht möglich ist den Mikrocontroller neben dem Sweep noch andere Aufgaben erledigen zu lassen.
  • Ein besserer Ansatz wäre es eine Zustandsmaschine (State-machine) zu programmieren.
67_Echtzeitsysteme/12_Zustandsmaschine -- Konzept einer Zustandsmaschine umgesetzt mit switch und case.
  • Über eine Wait-Until-Funktionalität kann ein gleichmäßiger Abarbeitungstakt mit exaktem Timing für den Sweep umgesetzt werden, vergl. CTC-Beispiel weiter oben.
  • Zusätzlich könnte durch eine LED signalisiert werden, wenn die zur Verfügung gestellte Zeit überschritten wird.

5. Übungen

Aufgabe 1 gemeinsam
  • Verbesserung des Sweep-Beispiels mittels State-Machine und Wait-Until-Funktionalität unter Verwendung von Timer 1 und 2.
Aufgabe 2
  • Mini Gimbal
  • Ein Servo 1 wird liegend fest mit dem Untergrund verbunden.
  • Servo 1 führt zyklisch einen Sweep von 0..30 Grad und zurück aus.
  • Ein Servo 2 ist mit Servo 1 über zwei "Knochen" miteinander verbunden (Verbindung mittlels 2 1mm Schrauben)
  • Auf Servo 2 ist der MPU6050 befestigt.
  • Das Gehäuse von Servo 2 soll mittels einer Gegenbewegung zu Servo 1 immer waagerecht gehalten werden.
  • Die notwendige Gegenbewegung wird mittels einer Regelung umgesetzt, die über den MPU6050 erfolgt.

HINWEISE: Arbeiten Sie immer zu zweit an dem Thema. Eine Entwurfs-Skizze wird im Unterricht entwickelt. Gliedern Sie die Aufgabe in Teilzielen auf und arbeiten diese nacheinander ab.

#7 Di, 12.05.2026

#8 Di, 19.05.2026

#9 Di, 26.05.2026

#10 Di, 02.06.2026

#11 Di, 09.06.2026

#12 Di, 16.06.2026

#13 Di, 23.06.2026 -- PROBE E-Test

#14 Di, 30.06.2026 -- semesterbegleitende PRÜFUNG (E-Test)