kramann.info
© Guido Kramann

Login: Passwort:










kramann.info
© Guido Kramann

Login: Passwort:




Grundlagen der Mikrocontrollertechnik im Sommersemester 2025

(EN google-translate)

(PL google-translate)

  • Hier bei "day by day" werden chronologisch im Verlauf des Semesters die behandelten Inhalte vermerkt.
  • Meistens werden Links innerhalb von kramann.info angegeben, wo der jeweils behandelte Stoff dargestellt wird.
  • Zur Orientierung finden Sie auf kramann.info auch noch das "day by day" der gleichen Lehrveranstaltung vom vorangehenden Jahr.
  • Die Prüfung in diesem Fach ist eine Klausur in elektronischer Form (E-Test)
  • Die folgenden vorab angegebenen Links stellen Quellen dar, aus denen die hier behandelten Inhalte genommen werden:

96_Arduino
40_Mikrocontroller
45_Mikro17
95_ETEST -- Hinweise zu der elektronischen Prüfungsform "E-Test"

#1 Do 27.03.2025

Die Lehrveranstaltung Grundlagen der Mikrocontrollertechnik richtet sich an Studierende der Ingenieurwissenschaften im vierten Semester. Es geht um die Programmierung von Mikrocontrollern, insbesondere um die Programmierung der internen Peripherie eines Mikrocontrollers. Unter dem Begriff "interne Peripherie" werden hier digitale Ein- und Ausgänge, Bussysteme, Timer, Analog- zu Digitalwandler und PWM-Geber zusammengefaßt. Im Wesentlichen soll die Konfiguration dessen, was in der Vorlesung mit interner Peripherie erlernt werden, sowie die Entwicklung von Software, die dann Gebrauch von dieser internen Peripherie macht. Die Programmierung erfolgt in C und C++. Für den leichten Einstieg werden zu Beginn die Arduino-IDE und die dort verfügbaren Befehle verwendet. Im weiteren Verlauf der Lehrveranstaltung soll aber auch die direkte Konfiguration von Registern erlernt werden und in diesem Zusammenhang der Gebrauch von Datenblättern zu Mikrocontrollern. In der Lehrveranstaltung und den zugehörigen Übungen kommt der Arduino Micro zum Einsatz. Jedoch wird in allgemeineren Betrachtungen auch auf andere Mikrocontroller verwiesen.


Einführend sollen die nachfolgenden Fragen behandelt werden:

Teil 1: Klären einiger grundlegender Fragen zu Mikrocontrollern
Motivation / Diskussion ... Grey Walter's tortoises 1949
  1. Was ist ein Mikrocontroller?
  2. Wozu werden Mikrocontroller verwendet?
  3. Was ist ein engebettetes System?
  4. Wer stellt Mikrocontroller her?
  5. Wie unterscheidet sich ein Mikrocontroller von einem PC?
  6. Wie zeichnet sich ein Mikrocontroller-Programm aus?
  7. Was ist ein Cross-Compiler?
  8. Was ist Maschinen nahes Programmieren?
  9. Worin liegt der Sinn darin, höhere Programmiersprachen wie C oder C++ zu verwenden?
1.1 Mikrocontroller auf Wikipedia
1.2 Foto Dual In Line DIL Bauweise eines ATmega32 von Atmel.
  • 2. 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.

5.1 Alan Turings Grundkonzept
5.2 Die unterschiedliche Architektur beim PC und beim Mikrocontroller
6. Wesentliches Merkmal eines Mikrocontroller-Programms: Die Loop-Funktion und die Manipulation von Registern.
  • 7. Mikrocontroller besitzen in der Regel keine Benutzerschnittstelle wie ein PC. Das Entwickeln und Kompilieren der Programme für einen Mikrocontroller erfolgt darum auf einem PC mit einer Entwicklungsumgebung und einem Cross-Compiler.
8. Exkurs: Programmentwurf in Assembler.

9. Höhere Programmiersprachen kommen zum Einsatz um die Wartbarkeit und Transparenz von Programmen zu verbessern.

Teil 2: Vorbereitungen auf die erste Übung
  1. Booten und Verwenden der (Linux-) Xubuntu-Distribution auf den PC-Pool-Rechnern
  2. Verwendung der Arduino-IDE
  3. Konfiguration der Arduino-IDE für einen über USB verbundenen Arduino Micro - Mikrocontroller
  4. Schreiben eines Programms
  5. Kompilieren eines Programms
  6. Übertragen eines Programms auf den Mikrocontroller
  7. Ansteuern digitaler Ein- und Ausgänge über Arduino-Befehle
  8. Vorbesprechung der ersten Übungsaufgaben
96_Arduino -- Überblick zum Arduino Micro
96_Arduino/01_Lauflicht -- Hardware (Steckboard mit Fritzing dargestellt) und Software (C / Arduino-Befehle) für ein "Lauflicht".
Im Verlauf des Unterrichts entstandene Quelltexte:
void setup() 
{
    pinMode(1,OUTPUT);
}

void loop() 
{
    digitalWrite(1,HIGH);
    delay(1000);
    digitalWrite(1,LOW);
    delay(1000);
}

Code 0-1: Blinkende LED

void setup() 
{
    pinMode(1,OUTPUT);
    pinMode(2,INPUT);
    digitalWrite(2,HIGH); //Pullup aktivieren, intern auf +5V setzen
}
int x;
void loop() 
{
    x = digitalRead(2);
    if(x<=0)
    {
        digitalWrite(1,HIGH);
        delay(1000);
        digitalWrite(1,LOW);
        delay(1000);
    }    
}

Code 0-2: Blinkende LED mit Taster

void setup() 
{
    pinMode(1,OUTPUT);
    pinMode(2,INPUT);
    digitalWrite(2,HIGH); //Pullup aktivieren, intern auf +5V setzen
}
int x;
void loop() 
{
    x = digitalRead(2);
    if(x<=0)
    {
        //digitalWrite(1,HIGH);
        //PORTD = 8;
        PORTD = 0b00001000;
        delay(1000);
        //digitalWrite(1,LOW);
        PORTD = 0;
        delay(1000);
    }    
}

Code 0-3: Blinkende LED unter Verwendung von Register-Befehlen

Programmieren mit Hilfe von ChatGPT (https://chat.openai.com/chat 21.03.2023):

Schreibe ein Arduino-Programm für den Arduino Micro, bei dem eine LED auf dem digitalen Ausgang D12 mit einem Hertz zum Blinken gebracht wird.

void setup() {
  pinMode(12, OUTPUT); // setze digitalen Ausgang D12 als Ausgang
}

void loop() {
  digitalWrite(12, HIGH); // schalte LED an
  delay(500); // warte 500 Millisekunden
  digitalWrite(12, LOW); // schalte LED aus
  delay(500); // warte weitere 500 Millisekunden
}

Code 0-4: Antwort von ChatGPT

"Das Programm setzt den digitalen Ausgang D12 als Ausgangspin und verwendet die digitalWrite()-Funktion, um die LED ein- und auszuschalten. Das Programm verwendet auch die delay()-Funktion, um eine Pause zwischen den Zustandsänderungen der LED einzufügen. In diesem Fall warten wir 500 Millisekunden (0,5 Sekunden) zwischen dem Einschalten und Ausschalten der LED, um eine Frequenz von einem Hertz zu erreichen. "

...und Kommentar von ChatGPT



ÜBUNG: Bauen Sie eine Arduino-Schlatung für Blinken auf und flashen Sie nachfolgende Programme.


Im Unterricht entstandene Programme
void setup() 
{
    pinMode(12,OUTPUT);
}

void loop() 
{
    digitalWrite(12,1);
    delay(500);
    digitalWrite(12,0);
    delay(500);
}

Code 0-5: Blinken auf digitalen Pin 12 mittels Arduino-Befehlen.

void setup() 
{
    //pinMode(12,OUTPUT);
    DDRD = 0b01000000;
}

void loop() 
{
    //digitalWrite(12,1);
    PORTD = 0b01000000;
    delay(500);
    //digitalWrite(12,0);
    PORTD = 0b00000000;
    delay(500);
}

Code 0-6: Blinken auf digitalen Pin 12 mittels Registerbefehlen.

#2 Do 03.04.2025

Blinken: Umsetzung mit Arduino-Befehlen und alternativ mit Register-Befehlen

// Definiere den Pin für die LED
const int ledPin = 11;

void setup() 
{
  // Setze den Pin für die LED als Ausgang
  //pinMode(ledPin, OUTPUT);
  DDRB = 0b10000000; //PB7 als Ausgang konfigurieren.
  //DDRB = 128;
}

void loop() 
{
  // Schalte die LED ein
  //digitalWrite(ledPin, HIGH);
  PORTB = 0b10000000;  // 5 Volt auf Digitalpin 11 'rausschicken, bzw. auf PB7
  // Warte für 500 Millisekunden (Halbe Periode)
  delay(500);
  // Schalte die LED aus
  //digitalWrite(ledPin, LOW);
  PORTB = 0b00000000;
  // Warte für weitere 500 Millisekunden (andere Hälfte der Periode)
  delay(500);
}

Code 0-7: Blinken auf PB7 mit Registerbefehlen.

Siehe auch:

96_Arduino/22_Universal/02_LED_Leiste
96_Arduino

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-8: Nur höchstwertigstes Bit manipulieren (PB7), mit Hilfe von Bitmasken und Bitoperationen.

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
  //DDRB = DDRB | (1<<7);  //Verschiebe die 1 sieben mal nach links:
  // 0b00000001 << 7 => 0b10000000
  // 
  //DDRB = DDRB | (1<<PB7);
  DDRB |= (1<<PB7); //bedeutet das Gleiche, wie Zeile darüber, Kurzschreibweise
}

void loop() {
  //PORTB = PORTB | 0b10000000;  // 5 Volt auf Digitalpin 11 'rausschicken, bzw. auf PB7
  PORTB |= (1<<PB7);
  delay(500);
  //PORTB &= (0<<PB7); // PORTB = PORTB & 0b00000000  ...ist nicht das, was wir wollen!!
  PORTB &= ~(1<<PB7);  // PORTB = PORTB & ~(0b10000000), passt, weil: ~(0b10000000) == ~(0b01111111)

  // (1<<0) == 1 == 2^0
  // (1<<1) == 2 == 2^1
  // (1<<2) == 4 == 2^2
  // (1<<3) == 8 == 2^3
  // ...
  // (1<<7) == 128 == 2^7 
  
  delay(500);
}

Code 0-9: Verwendung des Linksshift-Operators.

siehe auch:

40_Mikrocontroller/03_DigitalIO h5 ÜBUNG

Aufgabe 1:

  • Vollziehen Sie die Varianten in den obigen Beispielen praktisch nach.

Aufgabe 2:

  • An dem Schaltplan LED-Leiste ist zu erkennen, wo die Bits von PORT B sitzen.
  • Sie werden in der natürlichen Reihenfolge mit angeschlossenen LEDs herausgeführt.
  • Bauen Sie die Schaltung auf:
96_Arduino/22_Universal/02_LED_Leiste
  1. Programmieren Sie dann ein Lauflicht auf der Basis von Arduino-Befehlen.
  2. Versuchen Sie danach alternativ das Lauflicht mittels Bitshift-Befehlen umzusetzen.
  3. Kür: Programmieren dann andere Blinkfolgen, wie beispielsweise das hin- und herlaufen des Lichts bei den Zylonen-Robotern in Battlestar Galactica:
Cylons - https://www.youtube.com/watch?v=YPL7QPCfVZc
Studentische Lösungen
//Lauflicht mit Bitshift-Befehlen:
void setup() 
{
  //ganzer Port B als Ausgang:
  DDRB = 0b11111111;
  //DDRB = 255;
} 

void loop() 
{
  PORTB |= (1<<PB0);
  delay(250);
  PORTB &= ~(1<<PB0);
  PORTB |= (1<<PB1);
  delay(250);
  PORTB &= ~(1<<PB1);
  PORTB |= (1<<PB2);
  delay(250);
  PORTB &= ~(1<<PB2);
  PORTB |= (1<<PB3);
  delay(250);
  PORTB &= ~(1<<PB3);
  PORTB |= (1<<PB4);
  delay(250);
  PORTB &= ~(1<<PB4);
  PORTB |= (1<<PB5);
  delay(250);
  PORTB &= ~(1<<PB5);
  PORTB |= (1<<PB6);
  delay(250);
  PORTB &= ~(1<<PB6);
  PORTB |= (1<<PB7);
  delay(250);
  PORTB &= ~(1<<PB7);
  delay(250);
}

Code 0-10: Lösung 1

//Kür:
void setup()
{
  //ganzer Port B als Ausgang:
  DDRB = 0b11111111;
  //DDRB = 255;

  
}

void loop()
{

 for ( int i=0;i<7;i++)
 {
    PORTB |= (1<<i);
    delay(100);
    PORTB &= ~(1<<i);
 }

 for ( int i=7;i>0;i--)
 {
    PORTB |= (1<<i);
    delay(100);
    PORTB &= ~(1<<i);
 }
 

}

Code 0-11: Lösung 2

void setup() {
  // put your setup code here, to run once:
DDRB = 0b11111111;
//DDRB = 255;

//PB0 <=> 17
//PB1 <=> 15
//PB2 <=> 16
//PB3 <=> 14
pinMode(17, OUTPUT); //PB0
pinMode(15, OUTPUT); //PB1
pinMode(16, OUTPUT); //PB2
pinMode(14, OUTPUT); //PB3
pinMode(8, OUTPUT); //PB4
pinMode(9, OUTPUT); //PB5
pinMode(10, OUTPUT); //PB6
pinMode(11, OUTPUT); //PB7
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(17, HIGH);
  delay(100);
  digitalWrite(17, LOW);
  digitalWrite(15, HIGH);
  delay(100);
  digitalWrite(15, LOW);
  digitalWrite(16, HIGH);
  delay(100);
  digitalWrite(16, LOW);
  digitalWrite(14, HIGH);
  delay(100);
  digitalWrite(14, LOW);
  digitalWrite(8, HIGH);
  delay(100);
  digitalWrite(8, LOW);
  digitalWrite(9, HIGH);
  delay(100);
  digitalWrite(9, LOW);
  digitalWrite(10, HIGH);
  delay(100);
  digitalWrite(10, LOW);
  digitalWrite(11, HIGH);
  delay(100);
  digitalWrite(11, LOW);
  delay(500);
  digitalWrite(17, HIGH);
  digitalWrite(15, HIGH);
  digitalWrite(16, HIGH);
  digitalWrite(14, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  delay(500);
  digitalWrite(17, LOW);
  digitalWrite(15, LOW);
  digitalWrite(16, LOW);
  digitalWrite(14, LOW);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  digitalWrite(10, LOW);
  digitalWrite(11, LOW);
  delay(500);


  digitalWrite(11, HIGH);
  delay(100);
  digitalWrite(11, LOW);
  digitalWrite(10, HIGH);
  delay(100);
  digitalWrite(10, LOW);
  digitalWrite(9, HIGH);
  delay(100);
  digitalWrite(9, LOW);
  digitalWrite(8, HIGH);
  delay(100);
  digitalWrite(8, LOW);
  digitalWrite(14, HIGH);
  delay(100);
  digitalWrite(14, LOW);
  digitalWrite(16, HIGH);
  delay(100);
  digitalWrite(16, LOW);
  digitalWrite(15, HIGH);
  delay(100);
  digitalWrite(15, LOW);
  digitalWrite(17, HIGH);
  delay(100);
  digitalWrite(17, LOW);
  delay(500);
  digitalWrite(17, HIGH);
  digitalWrite(15, HIGH);
  digitalWrite(16, HIGH);
  digitalWrite(14, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  delay(500);
  digitalWrite(17, LOW);
  digitalWrite(15, LOW);
  digitalWrite(16, LOW);
  digitalWrite(14, LOW);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  digitalWrite(10, LOW);
  digitalWrite(11, LOW);
  delay(500);
  
}

Code 0-12: Lösung 3 -- Nur Arduino-Befehle

#3 Do 10.04.2025

Themen

Digitaler Eingang +

  1. Schwarmvehikel im Master
  2. Bussysteme und UART
  3. Analoger Eingang
  4. Digitaler Eingang
  5. Objektorientierte Programmierung
  6. Übungen

1. Schwarmvehikel im Master

  • Horizonterweiterung: Was ist ein Schwarmvehikel und welche interne Peripherie ist bei einem Schwarmvehikel in Benutzung?
Stare -- https://www.youtube.com/watch?v=S4dRLomlTn4
Swarm-bots: Self-assembly and Cooperative Transport -- https://www.youtube.com/watch?v=seGqyO32pv4
esp32swarm -- ein Schwarmvehikel auf der Basis eines esp32c3 super mini -- 05_esp32AV/30_esp32swarm

Verwendete interne Peripherie:

  • Serielle Schnittstelle zum PC (UART)
  • Bussystem für WiFi-Verbindung
  • Analog-Eingang für Entfernungssensor
  • Analog-Eingang für Bodensensor
  • PWM-Ausgang für Antrieb

2. Bussysteme und UART

UART - Universal Asynchronous Receiver Transmitter -- 40_Mikrocontroller/06_UART
Bussysteme -- 40_Mikrocontroller/06_UART/01_Bussysteme
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
void setup() 
{
    Serial.begin(9600);
}
int x=0;
void loop() 
{
    Serial.print("Hallo ");
    Serial.println(x);
    delay(200);
    x++;
}

Code 0-13: VON Arduino AN PC senden mittels Arduino-Befehlen.

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

void loop() 
{
   if(Serial.available())
   {
       char c = Serial.read();

       if(c=='1')
       {
           Serial.println("Es wurde die 1 gedrueckt.");
       }
       else if(c=='0')
       {
           Serial.println("Es wurde die 0 gedrueckt.");
       }
   }
}

Code 0-14: VOM PC ein Zeichen empfangen.

import processing.serial.*;

Serial myPort;  // Create object from Serial class
int val;        // Data received from the serial port

void setup() 
{
  size(200, 200);
  String portName = Serial.list()[0];
  println("Verbindung mit "+portName);
  myPort = new Serial(this, portName, 9600);
}

void draw() 
{
  background(255);
  String s=""; 
  while ( myPort.available() > 0) 
  {  // If data is available,
     char val = (char)myPort.read();
     s+=""+val;
     
  }
  if(s.length()>0) println(s);
}


public void keyPressed()
{
    if(key=='0')
    {
         myPort.write('0');
    }
    else if(key=='1')
    {
         myPort.write('1');
    }
}

Code 0-15: Minimales Processing-Programm, um am PC mit dem Arduino zu kommunizieren, siehe auch processing.org.

3. Analoger Eingang

  • Als Arduino-Befehl steht "analogRead(int nummer)" zur Verfügung.
  • Was dahinter steckt:
Der Analog/Digital-Wandler (ADW) des ATmega32 -- 40_Mikrocontroller/09_ADW
Verwendung des Analog/Digital-Wandlers -- 40_Mikrocontroller/09_ADW/01_ADW
Beispiel auf Arduino Seite -- https://www.arduino.cc/reference/tr/language/functions/analog-io/analogread/
Sharp Entfernungssensor -- 05_esp32AV/30_esp32swarm/04_Sensorik

BITTE NIE VERPOLEN!!!!


  • ROT: +5Volt
  • SCHWARZ: Ground (0Volt)
  • GELB: Analogausgang

4. Digitaler Eingang

  • 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

5. Objektorientierte Programmierung

OOP -- 96_Arduino/24_OOP
BEISPIELPROGRAMME

6. Übungen

Grundschaltung für alle Übungsteile.

Bild 0-1: Grundschaltung für alle Übungsteile.

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-16: 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-17: Register-Befehls-Variante.

Aufgabe 1
  • Schreiben Sie ein Programm, bei dem über Zeichen, die in den seriellen Monitor eingegeben werden, die rote LED ein- und ausgeschaltet werden kann.
Aufgabe 2
  • Realisieren Sie eine Schaltung, die der Logik einer Fussgängerampel entspricht.
  • Durch Drücken des oberen Tasters sollen die LEDs temporär von rot auf grün umspringen.
  • Setzen Sie die gleiche Aufgabe nun vorwiegend unter Verwendung von Registerbefehlen um.
Aufgabe 3
  • Die LEDs sollen warnen, wennn jemand dem Entfernungssensor zu nahe kommt.
  • Solange das der Fall ist, soll die rote LED leuchten, sonst die grüne.
  • Variante: Die rote LED soll schnell blinken, wenn gewarnt werden soll.

#4 Do 24.04.2025

Projekt + Variation + Präsentation

  • Bisher wurden Inhalte präsentiert und in nachfolgenden Übungen vertieft.
  • Nun soll etwas selbstständiger in Gruppen gearbeitet werden.
  • Dazu werden zunächst Zweiergruppen gebildet.
  • Diese wählen sich eines der nachfolgenden Themen.
  • Die Themen sind existierende fertige Arduino-Projekte auf kramann.info, die von den Gruppen nachgebaut, analysiert, variiert und präsentiert werden sollen.
  • Auf Moodle gibt es einen Upload-Link für die Projektdateien und ggf. auch für die Präsentationen.
  • Zeithorizont: Auswahl und Start sofort. Präsentationen auch ab heute, sofern möglich, 10-15min mit anschließenden Fragen und Ergänzungen durch die Lehrkraft.
  • Es ist denkbar, dass eine Gruppe mehrere Themen nach und nach bearbeitet.
  • Als letzten Punkt sollten alle Gruppen auch eine Übung für alle anderen vorbereiten.*

Aufgabenstellung in Kurzfassung
  1. System verstehen
  2. Eine Variante nachbauen und testen
  3. Eigene Variation entwickeln, umsetzen und testen
  4. Theorie und Ergebnisse präsentieren
  5. Übung für alle vorstellen und überwachen*

* Übungen sind teilweise bereits in den Projekten verfügbar. Sie können diese gerne übernehmen, bzw. modifizieren.



Siehe zu Thema 1,2,3 auch:

40_Mikrocontroller/04_PWM ...mit Unterkapiteln.
Thema #1 Verwendung eines Motortreibers und eines DC-Motors: 96_Arduino/12_Motor_PWM1

Thema #2 Steuerung der Motoraktivität vom PC aus: 96_Arduino/13_Motor_PWM2_seriell

Thema #3 Verwendung der nativen PWM-Ausgänge zur Steuerung des Motors: 96_Arduino/14_Motor_PWM3_analogWrite

Thema #4 (anspruchsvoll) Realisierung eines Schedulers in Arduino-Projekten 96_Arduino/15_Scheduler

Thema #5 Verwendung eines inkrementellen Drehgebers mit einem Arduino Micro: 96_Arduino/16_Drehgeber

Thema #6 (anspruchsvoll) Objektorientierte Programmierung mit Arduino: 96_Arduino/24_OOP

Thema #7 Tonerzeugung über Toggle-Ausgängen im CTC-Mode : 96_Arduino/28_CTC

Thema #8 (anspruchsvoll) Erzeugung von Tonhöhen mit den Timern 0, 1 oder 3 des Arduino Micro: 96_Arduino/29_Tonerzeugung

Thema #9 (erfordert spezielle Hardware) Ansteuerung eines ASCII-fähigen LED-Displays: 96_Arduino/27_CompBoard/02_ASCIIDisplay

Thema #10 (muss von ATmega auf Arduino übertragen werden / erfordert spezielle Hardware) Verwendung einer Tastenmatrix: 96_Arduino/27_CompBoard/01_Tastenmatrix

Thema #11 (siehe "#3 Fr 14.04.2023") Drehkodierer steuert Sieben-Segment-Anzeige an: 03_SoSe2024/03_Mik_11_04_2024

Thema #12 (siehe "Übungen", anspruchsvoll, spezielle Hardware erforderlich) Ansteuerung einer 4-fach-7-Segment-Anzeige: 03_SoSe2024/06_Mik_02_05_2024

Thema #13 (siehe "3. Verwendung der seriellen Schnittstelle mittels der Arduino-Library ") Serielle Verbindung zweier Arduino Micro: 03_SoSe2024/07_Mik_16_06_2024

Thema #14 Ansteuerung einer fertig aufgebauten Motortreiber-Platine 03_SoSe2024/10_Mik_05_06_2024

Thema #15 Ansteuerung eines Modellbauservos : 45_Mikro17/06_Servo

Siehe dazu auch:

40_Mikrocontroller/04_PWM/05_Servos
40_Mikrocontroller/04_PWM/08_LoesungUE3

#5 Do 07.05.2025

FORTSETZUNG Projekt + Variation + Präsentation (s.o.)

Themen

  1. Präsentation und Übung zu Thema #13: Serielle Verbindung zweier Arduino Micro
  2. Fortsetzung der Projektarbeiten

1. Präsentation und Übung zu Thema #13: Serielle Verbindung zweier Arduino Micro

ÜBUNG zu Thema #13: thema13-2arduinos.pdf
ÜBUNG

Verändern Sie das Programm so, dass Sie beliebig viele Ziffern eingeben können und jede Ziffer wird als Zahl interpretiert und es soll 10 addiert werden. Das Ergebnis der Addition soll bei "Antwort" ausgegeben werden.

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
}
void loop()
{
  if (Serial.available())
  {
    char c=Serial.read();
    Serial1.write(c);
    Serial.print("Frage: ");
    Serial.println(c);
  }
  if (Serial1.available())
  {
    char antwort = Serial1.read();
    Serial.print("Antwort: ");
    Serial.println(antwort);
  }
}

Code 0-18: Arduino 1 -- Ausgangsprogramm

void setup()
{
   Serial1.begin(9600);
}
void loop()
{
  if(Serial1.available())
  {
    char c = Serial1.read();
    Serial1.write(c+1);
  }
}

Code 0-19: Arduino 2 -- Ausgangsprogramm

Studentische_Loesung_seriell.zip

2. Fortsetzung der Projektarbeiten


#6 Do 15.05.2025

Themen

  1. Einführung in die objektorientierte Programmierung bei Mikrocontrollern (entspricht Thema #6)
  2. Präsentation und Übung zu Projekt #9: Ansteuerung eines LCD-Displays (Hardware geändert)
  3. Präsentation zu Projekt #5 Verwendung eines inkrementellen Drehgebers mit einem Arduino Micro
  4. Fortsetzung der Projektarbeiten

1. Einführung in die objektorientierte Programmierung bei Mikrocontrollern (entspricht Thema #6)

96_Arduino/24_OOP
45_Mikro17/05_OOP
Klasse_vektor.zip -- Unterrichtsbeispiel 1
Klasse_PortB.zip -- Unterrichtsbeispiel 2

2. Präsentation und Übung zu Projekt #9: Ansteuerung eines LCD-Displays (Hardware geändert)


//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

int x=1;
int potPin = A0;
int volt;

void setup()
{
 
  lcd.init();                      // initialize the lcd 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Herzlich Willkommen");
  delay(3000);
  lcd.setCursor(2,1);
  lcd.print("Vielen Dank");
  lcd.setCursor(1,2);
  lcd.print("fuer die Nutzung");
  lcd.setCursor(1,3);
  lcd.print("unseres Produktes");
  delay(2500);
}

void loop()
{
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("Digital-Voltmeter");
  volt = analogRead(potPin);
  lcd.setCursor(1,2);
  lcd.print("Spannung:");
  lcd.setCursor(11,2);
  lcd.print(volt);
  lcd.setCursor(16,2);
  lcd.print("mV");
  delay(200);
  
}

Code 0-20: Studentisches Beispiel-Projekt Voltmeter.

Studentische ÜBUNG

ANSCHLUSS: Verbinden Sie die beschrifteten Anschlüsse +5Volt, GND, SDA, SCL passend mit dem Arduino Micro.


siehe auch:

https://www.make-it.ca/i2c-lcd-display-on-arduino/
96_Arduino -- Pin Layout Arduino Micro.
  • Aufgabe: Vervollständigen Sie den Quellcode, sodass auf Ihrem Display in der ersten Zeile eine Begrüßung, in der zweiten Zeile das heutige Datum und in der dritten Zeile ihr Gruppenname steht.
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display


void setup()
{
 
  lcd.init();                      // initialize the lcd 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Herzlich Willkommen");
  delay(3000);
  lcd.setCursor(2,1);
  lcd.print("Vielen Dank");
  lcd.setCursor(1,2);
  lcd.print("fuer die Nutzung");
  lcd.setCursor(1,3);
  lcd.print("unseres Produktes");
  delay(2500);
  lcd.clear();
}

void loop()
{
  
}

Code 0-21: ÜBUNG

3. Präsentation und Übung zu Projekt #5 Verwendung eines inkrementellen Drehgebers mit einem Arduino Micro

02_SoSe2025/02_MIK_day_by_day/Aufgabe_Drehgeber.pdf -- Studentische Übung zum inkrementellen Drehgeber
02_SoSe2025/02_MIK_day_by_day/Stepper Motor_28BYJ_48_5V.pdf -- Datenblatt Schrittmotor

4. Fortsetzung der Projektarbeiten


#7 Do 22.05.2025

Themen

  1. Erzeugung von PWM-Signalen mit Hilfe des Timers 1 und Ansteuerung eines Modellbau-Servos mit Hilfe von Registerbefehlen
  2. Fortsetzung Objektorientierte Programmierung am Beispiel eines Servos.
  3. Präsentationen?
  4. Fortsetzung der Projektarbeiten

1. Erzeugung von PWM-Signalen mit Hilfe des Timers 1 und Ansteuerung eines Modellbau-Servos mit Hilfe von Registerbefehlen

Hinweise zur Ansteuerung eines Modellbau-Servos mittels PWM-Signalen, siehe Schaubilder hier: 40_Mikrocontroller/04_PWM/08_LoesungUE3
02_SoSe2025/02_MIK_day_by_day/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf
  • Siehe Formel, Seite 126.
  • Siehe Tabelle 14-4 zum Einstellen von WGM1, Seite 133, insbesondere Mode 8.
  • Einstellen von N: Tabelle 14-6, Seite 134.
  • Einstellen des Zählermodes: Tabelle 14-3, Seite 132.

$ f_OC1= \frac {f_clk}{2 \cdot N \cdot TOP} $

Formel 0-1: Frequenz einer Periode eines Phase- und Frequenz- korrekten PWM-Signals mit Timer 1 & N: Vorteilung & TOP: Eingestellte Zähl-Obergrenze.


ÜBUNG
  • Finden Sie im nachfolgenden Programm die Registerbefehle, die den Mode 8 festlegen.
  • Finden Sie im nachfolgenden Programm die Registerbefehle, die die PWM-Frequenz (ganze Periode) auf 80Hz setzen.
  • Finden Sie heraus, wo und wie die beiden Servos angeschlossen werden müsssen, die von nachfolgendem Programm angesteuert werden.
  • Testen Sie das nachfolgende Programm.
  • Verändern Sie das Programm so, dass ein Sweep umgesetzt wird (Vergleiche Servo Sweep auf Arduino-Seite)
  • Gemeinsam: Objektorientierte Variante des nachfolgenden Codes entwickeln.
#define WMIN 1000
#define WMITTE 1500
#define WMAX 2000
#define SCHRITTE 1000

//Mode 8 (vergleiche Datenblatt zum ATmega32u4, der im Arduino Micro verbaut ist)
//Phasen- und Frequenz-korrekt
//WGM1   3 2 1 0
//       1 0 0 0
//ICR1=..... TOP
//fpwm = fclk/(2*N*TOP)
//Vorteilung
//N=8
//80Hz = 16000000/(2*8*TOP)
//TOP = 16000000/(2*8*80Hz)=12500

//dt==1000ms*(1/80Hz)/12500 == 0,001ms (1 Schritt == 0,001ms)
//=>
//1ms == 1000 Schritte
//1,5ms == 1500 Schritte
//2ms == 2000 Schritte
void setup() 
{
       TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<COM1C1) | (0<<COM1C0) | (0<<WGM11) | (0<<WGM10);
       TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10); //Vort. 256, s.S. 125
       
       ICR1=12500;
       
       DDRB |= (1<<PB5); //OCR1A
       DDRB |= (1<<PB6); //OCR1B
       OCR1A = WMITTE; //PWM-Breite auf Mitte setzen.  
       OCR1B = WMITTE; //PWM-Breite auf Mitte setzen.  
}

void loop() 
{
       OCR1A = WMAX; 
       OCR1B = WMAX; 
       
       delay(3000);
    
       OCR1A = WMITTE; 
       OCR1B = WMITTE; 
       
       delay(3000);
    
       OCR1A = WMIN; 
       OCR1B = WMIN; 
       
       delay(3000);
    
}

Code 0-22: Beispielprojekt.


Varianten an studentischen Lösungen


#define WMIN 1000
#define WMITTE 1500
#define WMAX 2000
#define SCHRITTE 1000

//Mode 8 (vergleiche Datenblatt zum ATmega32u4, der im Arduino Micro verbaut ist)
//Phasen- und Frequenz-korrekt
//WGM1   3 2 1 0
//       1 0 0 0
//ICR1=..... TOP
//fpwm = fclk/(2*N*TOP)
//Vorteilung
//N=8
//80Hz = 16000000/(2*8*TOP)
//TOP = 16000000/(2*8*80Hz)=12500

//dt==1000ms*(1/80Hz)/12500 == 0,001ms (1 Schritt == 0,001ms)
//=>
//1ms == 1000 Schritte
//1,5ms == 1500 Schritte
//2ms == 2000 Schritte
void setup()
{
       TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<COM1C1) | (0<<COM1C0) | (0<<WGM11) | (0<<WGM10);
       TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10); //Vort. 256, s.S. 125
      
       ICR1=12500;
      
       DDRB |= (1<<PB5); //OCR1A
       DDRB |= (1<<PB6); //OCR1B
       OCR1A = WMITTE; //PWM-Breite auf Mitte setzen. 
       OCR1B = WMITTE; //PWM-Breite auf Mitte setzen. 
}

void loop()
{
   for(int i=1000; i<2000; i++)
   {
       OCR1A = i;
       OCR1B = i;
       delay(2);
   }
   
}

Code 0-23: Studentische Lösung 1.

#define WMIN 1000
#define WMITTE 1500
#define WMAX 2000
#define SCHRITTE 1000

int pos = 0;

void setup() 
{
       TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<COM1C1) | (0<<COM1C0) | (0<<WGM11) | (0<<WGM10);
       TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10); //Vort. 256, s.S. 125
       
       ICR1=12500;
       
       DDRB |= (1<<PB5); //OCR1A
       DDRB |= (1<<PB6); //OCR1B
       OCR1A = WMITTE; //PWM-Breite auf Mitte setzen.  
       OCR1B = WMITTE; //PWM-Breite auf Mitte setzen.

       
}

void loop() 
{
       for(pos = WMIN; pos <= WMAX; pos += 5)
       {
        OCR1A = pos;
        delay(15);
       }

      for(pos = WMAX; pos >= WMIN; pos -= 5)
       {
        OCR1A = pos;
        delay(15);
       }
    
}

Code 0-24: Studentische Lösung 2.

2. Fortsetzung Objektorientierte Programmierung am Beispiel eines Servos.

3. Präsentationen


Studentisches Projekt: Pulsweitenmodulation selber programmieren


Originalcode:
int zaehler = 0;

int xPWM = 0;

void setup() 
{
  // put your setup code here, to run once:
  pinMode(9,OUTPUT);   
  pinMode(4, OUTPUT);  
  pinMode(3, OUTPUT);  
  
  pinMode(13, OUTPUT); //Board LED 
  
  //Eine Richtung festlegen und PWM aus:
  digitalWrite(4,HIGH);
  digitalWrite(9,LOW);
  digitalWrite(3,LOW);

  //LED aus  
  digitalWrite(13,LOW);
}

void loop() 
{
    digitalWrite(3,HIGH); //20 Ticks == 0,02 Sekunden entspricht 50Hz
    delay(xPWM);
    digitalWrite(3,LOW);
    delay(20-xPWM);
    
    if(zaehler==0)
    {
        digitalWrite(13,HIGH);
        
        xPWM++;
        xPWM%=20;
    }        
    else if(zaehler==25)
        digitalWrite(13,LOW);
        
    zaehler++;
    zaehler%=50;  //eine Sekunde == 50 PWM-Perioden
}

Code 0-25: Originalcode.

Erklärung:

Der Code steuert einen Gleichstrommotor über eine L293-Motortreiberbrücke. Dabei wird eine feste Richtung eingestellt, und der Motor wird durch ein manuell erzeugtes PWM-Signal an Pin 3 mit variierender Pulsweite (xPWM) angesteuert.

  • Pin 4 und 9 bestimmen die Drehrichtung des Motors (in diesem Fall: vorwärts fest eingestellt).
  • Pin 3 ist für die PWM-Ansteuerung des Motors (Enable-Pin).
  • Pin 13 ist eine LED auf dem Board zur Statusanzeige.
  • Alle 20 ms wird ein PWM-Zyklus durchgeführt:
  • Pin 3 wird für xPWM ms auf HIGH gesetzt => Motor läuft
  • Dann für 20 - xPWM ms auf LOW gesetzt => Motor steht
  • So entsteht eine PWM-Frequenz von 50 Hz (20 ms pro Periode).
  • Der PWM-Wert xPWM wird nur einmal pro Sekunde erhöht (zaehler == 0).
  • Wenn xPWM 0 ist, wird die LED an Pin 13 eingeschaltet, bei zaehler == 25 wieder aus.

Der Motor startet bei 0 % Tastverhältnis (steht) und wird jede Sekunde ein kleines Stück schneller, bis xPWM wieder bei 0 ist (wegen % 20). Dadurch ergibt sich ein langsames Hochdrehen mit Wiederholung.

Variante: Der Motor dreht immer schneller in eine Richtung, dann wird langsamer und dann dreht immer schneller in die andere Richtung und so weiter und so fort:

int zaehler = 0;
int xPWM = 0;
bool rampingUp = true;
bool forward = true;

void setup() {
  pinMode(9, OUTPUT);  
  pinMode(4, OUTPUT);  
  pinMode(3, OUTPUT);  
  pinMode(13, OUTPUT); 

  
  digitalWrite(4, HIGH);
  digitalWrite(9, LOW);
  digitalWrite(3, LOW);
  digitalWrite(13, LOW);
}

void loop() {
  digitalWrite(3, HIGH);
  delay(xPWM);
  digitalWrite(3, LOW);
  delay(20 - xPWM);

  if (zaehler == 0) {
    digitalWrite(13, HIGH);  

    if (rampingUp) {
      xPWM++;
      if (xPWM >= 19) rampingUp = false;
    } else {
      xPWM--;
      if (xPWM <= 0) {
        rampingUp = true;

        
        forward = !forward;
        if (forward) {
          digitalWrite(4, HIGH);
          digitalWrite(9, LOW);
        } else {
          digitalWrite(4, LOW);
          digitalWrite(9, HIGH);
        }
      }
    }
  }

  zaehler++;
  zaehler %= 50;
}

Code 0-26: Variante.

Variation: Schalten der LEDs in Parallelschaltung, sodass: Eine LED leuchtet auf, wenn der Motor in eine Richtung läuft, eine andere leuchtet auf, wenn er in eine andere Richtung läuft.

Übung:
  • Erweitern Sie das bestehende System, indem Sie:
  • Einen Taster einbauen, der die Richtung des Motors wechselt.
  • #hl
  • MUSTERLÖSUNG: forward = !forward; auskommentieren und statt dessen durch Taster steuern
int zaehler = 0;
int xPWM = 0;
bool rampingUp = true;
bool forward = true;

void setup() {
  pinMode(9, OUTPUT);  
  pinMode(4, OUTPUT);  
  pinMode(3, OUTPUT);  
  pinMode(13, OUTPUT); 

  
  digitalWrite(4, HIGH);
  digitalWrite(9, LOW);
  digitalWrite(3, LOW);
  digitalWrite(13, LOW);

  //TASTER EINRICHTEN
  pinMode(10,INPUT);
  digitalWrite(10,HIGH); //Pullup setzen
}

void loop() {

  if(digitalRead(10)==LOW)
  {
      forward = !forward;
      delay(200);
  }
  
  digitalWrite(3, HIGH);
  delay(xPWM);
  digitalWrite(3, LOW);
  delay(20 - xPWM);

  if (zaehler == 0) {
    digitalWrite(13, HIGH);  

    if (rampingUp) {
      xPWM++;
      if (xPWM >= 19) rampingUp = false;
    } else {
      xPWM--;
      if (xPWM <= 0) {
        rampingUp = true;

        
        //forward = !forward;
        if (forward) {
          digitalWrite(4, HIGH);
          digitalWrite(9, LOW);
        } else {
          digitalWrite(4, LOW);
          digitalWrite(9, HIGH);
        }
      }
    }
  }

  zaehler++;
  zaehler %= 50;
}

Code 0-27: Musterlösung.


ENDE


4. Fortsetzung der Projektarbeiten


#9 Do 05.06.2025

Themen

  • Wir werden uns heute damit befassen ein etwas komplexeres System herzustellen.
  • Es geht um eine Tonsteuerung mittels eines IMU (Inertia Measurement Unit, Typ: MPU6050), sprich, Beschleunigungen und Winkelgeschwindigkeiten werden gemessen.
  • Die Töne werden als Rechteckschwingungen mittels eines oder mehrerer Timer im CTC-Mode erzeugt und stehen auf einem oder mehreren PWM-fähigen digitalen Ausgängen zur Verfügung.
  • Um die Komplexität beim Umgang mit mit der Tonerzeugung zu verringern, soll ein objektorientierter Ansatz gewählt werden.
  • Die Aufgabe wird in viele Teilschritte zerlegt, womit die Themen für heute gegeben wären:
A Theoretischer Teil
  1. Vorstellung von Thema #7 Tonerzeugung über Toggle-Ausgängen im CTC-Mode : 96_Arduino/28_CTC
  2. Ergänzungen zur Darstellung von Thema #7, insbesondere Entwurf zu einer objektorientierten Herangehensweise
  3. Verwendung eines IMU vom Typ MPU6050 über das I2C (aus patentrechtlichen Gründen im Datenblatt TWI -- Two Wire Interface -- genannt) Bussystem genannt

1. Vorstellung von Thema #7 Tonerzeugung über Toggle-Ausgängen im CTC-Mode : 96_Arduino/28_CTC

96_Arduino/28_CTC

gemeinsamer Blick ins Datenblatt zum ATmega32u4.


2. Ergänzungen zur Darstellung von Thema #7, insbesondere Entwurf zu einer objektorientierten Herangehensweise

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.

Angaben zum zerstörungsfreien Anschluss eines Lautsprechers



Entwurf einer sinnvollen Struktur im Zusammenhang mit der Tonerzeugung im CTC-Mode.


3. 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
B Praktischer Teil
  1. Testen Sie den MPU6050 mittels des Beispiels
  2. Testen Sie die Tonerzeugung auf der Basis der Beispiele
  3. Entwickeln Sie ein Konzept zur Verbindung zwischen IMU und Tonerzeuger
  4. Kapseln Sie den Tonerzeuger in eine Klasse
  5. Setzen Sie Ihr Konzept um und testen und Präsentieren es.
Test zur Tonerzeugung mit 440Hz -- Ausgangspunkt für Ihr Projekt
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-28: Test zur Tonerzeugung mit 440Hz -- Ausgangspunkt für Ihr Projekt.

Musterlösung zur OOP Umsetzung (studentische Lösung)
mpu.zip
#include<math.h>
#include<Wire.h>
#include "tongenerator.h"

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

tongenerator n;



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);

  n.start();

}

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;

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

     delay(200);

     
  

     

}


Code 0-29: mpu.ino

class tongenerator
{
  public:

  const  unsigned int LOOKUP_OCR1[128] = {
  61155, 57723, 54483, 51425, 48539, 45814, 43243, 40816, 38525, 36363, 
  34322, 32395, 30577, 28861, 27241, 25712, 24269, 22907, 21621, 20407, 
  19262, 18181, 17160, 16197, 15288, 14430, 13620, 12855, 12134, 11453, 
  10810, 10203, 9630, 9090, 8580, 64792, 61155, 57723, 54483, 51425, 
  48539, 45814, 43243, 40816, 38525, 36363, 34322, 32395, 30577, 28861, 
  27241, 25712, 24269, 22907, 21621, 20407, 19262, 18181, 17160, 16197, 
  15288, 14430, 13620, 12855, 12134, 11453, 10810, 10203, 9630, 9090, 
  8580, 8098, 7644, 7214, 6809, 6427, 6066, 5726, 5404, 5101, 
  4815, 4544, 4289, 4049, 3821, 3607, 3404, 3213, 3033, 2862, 
  2702, 2550, 2407, 2272, 2144, 2024, 1910, 1803, 1702, 1606, 
  1516, 1431, 1350, 1275, 1203, 1135, 1072, 1011, 955, 901, 
  850, 803, 757, 715, 675, 637, 601, 567, 535, 505, 
  477, 450, 425, 401, 378, 357, 337, 318};

  const unsigned int LOOKUP_N1[128] = {
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
  2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1, 1, 1};

  void start()
  {
    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); 
    
  }

  int x=0, y=0;


    

  void dreh(int midi)
  {
    if (midi<0)
      midi = midi*-1;

    TCCR1B &= 248; //unteren drei Bit löschen
    TCCR1B |= LOOKUP_N1[midi];
    OCR1A=LOOKUP_OCR1[midi];
  
  }
};


Code 0-30: tongenerator.h


#10 Do 12.06.2025


Die heutige Lehrveranstaltung findet online statt. Der Link für die Videokonferenz wurde per E-Mail verschickt.


Themen

  1. Organisatorisches
  2. Quiz
  3. Übungsaufgaben
  4. Arbeitsphase
  5. Besprechung der Übungsaufgaben

1. Organisatorisches

  • Mikrocontrollertechnik aktuell online abzuhalten, hat hoffentlich zur Entspannung der Situation wegen der aktuellen Beschränkungen im Bahnverkehr geführt.
  • Die Lehrveranstaltungen während des restlichen Semesters finden aber wieder in Präsenz statt.
  • Insbesondere findet in der kommenden Woche, am Donnerstag den 19.06. der nicht bewertete Probe-E-Test statt...
  • ...und am Donnerstag den 03.07. die semesterbegleitende KLAUSUR in elektronischer Form.
  • Da es aber sein kann, dass Einzelne kommende Woche nicht kommen, orientiert sich die Aufgabenstruktur der folgenden Übung bereits an dem Aufbau einer Prüfung.

2. Quiz

  1. Wie unterscheiden sich PWM und CTC-Mode (CTC == Clear Timer on Compare Match) voneinander?
  2. Welche Arten von Einstellungen müssen über Registerkonfigurationen im Zusammenhang mit PWM vorgenommen werden?
  3. Was bedeutet die Abkürzung IMU und welchem Zweck dient das?
  4. Wie kann gezielt das Bit, das der Wertigkeit 2^3 entspricht im Register PORTB gesetzt werden, ohne andere Bits zu beeinflussen?
  5. Welche zwei Bedeutungen hat das, wenn man dieses Bit in PORTB setzt?
  6. Wie kann das gleiche Bit gelöscht werrden, ohne andere Bits zu beeinflussen?

3. Übungsaufgaben


Die Aufgaben werden vorbesprochen, dann erfolgt eine Arbeitsphase und zu einem vereinbarten Zeitpunkt kommen wir wieder zusammen und besprechen alles.


Aufgabe 1


Geben Sie als Dezimalzahl an, was die nachfolgenden Bitoperationen ergeben. Beispiel: 0b11110000 + 0b00001111 = 0b11111111 entspricht dezimal 255. Sie müßten dann 255 eintragen.

(0b10101010 | 0b00010101) ergibt als Dezimalzahl:


(0b00001001 & 0b10101011) ergibt als Dezimalzahl:


~(0b11001100 | 0b00110000) ergibt als Dezimalzahl:

Aufgabe 2

Arduino-Micro Pinlayout.

Bild 0-2: Arduino-Micro Pinlayout.

Vervollständigen Sie das nachfolgende Arduino-Micro-Programm so, dass am digitalen Ausgang Nr. 11 zyklisch für eine Sekunde ein High-Pegel (+5Volt) anliegt, gefolgt von einem Low-Pegel, ebenfalls für eine Sekunde. Das Programm beginnt mit einem High-Level. Verwenden Sie die Arduino-Bibliotheks-Befehle.



void setup()
{
    //...vervollständigen
}

void loop()
{
    //...vervollständigen
}


Code 0-31: Grundaufbau des Mikrocontroller-Programms

  1. Versuchen Sie die Aufgabe zunächst ohne Hilfsmittel zu lösen, erzeugen Sie insbesondere in der Arduino IDE ein entsprechendes Projekt und kodieren die Lösung.
  2. Kompilieren Sie dann Ihr Programm und korrigieren ggf. Syntaxfehler.
  3. Bauen Sie dann je nach Mögloichkeit (Mikrocontroller-Box ausgeliehen) die entsprechende Schaltung auf, übertragen das Maschinenprogramm und überprüfen, ob das System so wie erwartet funktioniert.
  4. Skizzieren Sie auch noch den Stromlaufplan Ihrer Schaltung auf einem Blatt Papier.

Aufgabe 3

Betrachten Sie erneut die Angaben aus Aufgabe 2. Vervollständigen Sie das nachfolgende Programm so, dass es das gleiche macht, wie das Programm aus Aufgabe 2. Verwenden Sie aber jetzt Port-Befehle zur Konfiguration der Register des Mikrocontrollers anstatt Arduino-Befehle. Eine Ausnahme stellt die Realisierung der Pausen dar. Diese kann wie oben erfolgen.

HINWEIS: Die Bitzuordnung der verwendeten Pins zu PORTB ist im Bild oben mit vermerkt (PB 4 5 6 7). Die Aufgabe soll so gelöst werden, dass keine Registerbits geändert werden, die nicht benötigt werden. Der Zustand aller nicht benötigten Registerbits gilt als unbekannt.


void setup()
{
    //...vervollständigen
}

void loop()
{
    //...vervollständigen
}


Code 0-32: Grundaufbau des Mikrocontroller-Programms

Aufgabe 4

Betrachten Sie nachfolgenden Schaltplan mit einem Arduino-Micro. Ergänzen Sie das zugehörige Mikrocontroller C-Programm so, dass die LED nur leuchtet, wenn gleichzeitig Taster 1 (T1) und Taster 2 (T2) gedrückt sind.

HINWEIS: Verwenden Sie nur Registerbefehle. Die Bitzuordnung der verwendeten Pins zu PORTB ist im Bild mit vermerkt (PB 4 5 6 7). Die Aufgabe soll so gelöst werden, dass keine Registerbits geändert werden, die nicht benötigt werden. Der Zustand aller nicht benötigten Registerbits gilt als unbekannt.

Arduinoschaltung.

Bild 0-3: Arduinoschaltung.


void setup()
{
    //...vervollständigen
}

void loop()
{
    //...vervollständigen
}


Code 0-33: Grundaufbau des Mikrocontroller-Programms

  1. Versuchen Sie die Aufgabe zunächst ohne Hilfsmittel zu lösen, erzeugen Sie insbesondere in der Arduino IDE ein entsprechendes Projekt und kodieren die Lösung.
  2. Kompilieren Sie dann Ihr Programm und korrigieren ggf. Syntaxfehler.
  3. Bauen Sie dann je nach Mögloichkeit (Mikrocontroller-Box ausgeliehen) die entsprechende Schaltung auf, übertragen das Maschinenprogramm und überprüfen, ob das System so wie erwartet funktioniert.
  4. Skizzieren Sie auch noch den Stromlaufplan Ihrer Schaltung auf einem Blatt Papier.

Aufgabe 5

Im so genannten Normal-Mode (siehe Tabellen unten) zählt der 16-Bit-Timer 1 mit einer Taktrate hoch, die der Taktfrequenz des Mikrocontrollers geteilt durch eine Vorteilung N entspricht.

Man kann den Zählerstand über das Register TCNT1 abrufen und ihn auch im eigenen Programm ändern.

Als Ersatz für die Zeile delay(1000), könnten dann im loop()-Bereich eines Programms die folgenden beiden Zeilen stehen:



while(TCNT1<250000) PORTB|=0; 
TCNT1=0;


Code 0-34: Zeilen in loop() beim selbst programmierten delay(1000).

Die Taktfrequenz des Arduino-Micro ist 16MHz.

Welche Vorteilung N muß für den Timer 1 eingestellt werden (Zahl angeben)? Hinweise: Siehe Tabellen weiter unten.


Wie müssen die Befehle lauten, die diese Vorteilung festsetzen, ohne andere Registerbits zu verändern? Hinweise: Siehe Tabellen weiter unten.

timer1.

Bild 0-4: timer1.

a3.

Bild 0-5: a3.

a2.

Bild 0-6: a2.

Timer/Counter1 Control Register B - TCCR1B:

tccy.

Bild 0-7: tccy.


Fortsetzung der Aufgabe "Kür":


  1. Aktivieren Sie nun unter Zuhilfenahme des Datenblatts zum ATmega32u4 tatsächlich den Normal Mode für den Timer 1.
  2. Stellen Sie die Vorteilung gemäß obiger Aufgabe ein.
  3. Modifizieren Sie die Aufgabe so, dass Sie auf dem digitalen Ausgang PB4 Blinken mit 0,5Hz erzeugen.
  4. Ist die Blinkfrequenz ganz genau 0,5Hz?

4. Arbeitsphase

5. Besprechung der Übungsaufgaben

Nachtrag zu Aufgabe 5
  • die 250000 wird nie erreicht, weil der Zäher nur bis 2^16-1=65534 zählen kann.
  • Lösung: Vorteilung auf 1024 setzen, TCNT1<15625
unsigned char akku;
void setup() 
{
        DDRB |= 0b10000000;  //PB7 statt PB4
        TCCR1A &= 0b11111100;        
        TCCR1B &= 0b11100101;
        TCCR1B |= 0b00000101;  //101 => 1024 als Vorteilung          
}

void loop() 
{
        PORTB|=0b10000000;
  
        //while(TCNT1<250000) PORTC|=0; //Kann NIE erreicht werden!!!
        while(TCNT1<15625) PORTC|=0; //Kann NIE erreicht werden, Maximum; 64364!!!
        TCNT1=0;

        PORTB&=~0b10000000;
        
        //while(TCNT1<250000) PORTC|=0;
        while(TCNT1<15625) PORTC|=0; 
        TCNT1=0;
}

Code 0-35: Mögliche Lösung zu Aufgabe 5.


#11 Do 19.06.2025

Themen

  1. Präsentation zu Thema #7 Tonerzeugung über Toggle-Ausgängen im CTC-Mode : 96_Arduino/28_CTC
  2. Probe-E-Test
  3. Besprechung des Probe-E-Tests
  4. Übung zu Thema #7(?)

#12 Do 26.06.2025

Thema: Intermezzo -- Objektorientierte Programmierung bei der Simulation von Schwarmrobotik

  • Derzeit läuft ein Masterkurs, bei dem Schwarmvehikel sowohl gebaut als auch simuliert werden.
  • Um die Entwicklungszeit zu beschleunigen, übermitteln die Hardware-Fahrzeuge ihre Sensordaten an einen PC und erhalten individuell dazu passend von dort in Echtzeit Befehle zur Motorsteuerung.
  • Dies setzt voraus, dass jedes Vehikel in der PC-Software individuell repräsenterit wird.
  • Dies gelingt PC-seitig insbesondere durch die Verwendung objektorientierter Programmierung in Java/Processing.

Konzept für ein Fahrzeug, siehe 05_esp32AV


"Linien-Kriechen": https://youtu.be/SVcHWJRBFwU

"Linienverfolgung mit P-Regler": https://youtu.be/qLYiJC4uyPc

"PI-Regler": https://youtu.be/YS-1RRLGtgQ

Konzept für Schwarmfahrzeuge a) -- 05_esp32AV/30_esp32swarm

Konzept für Schwarmfahrzeuge b) -- 05_esp32AV/30_esp32swarm/01_Konzept

Der Termin heute bietet die Gelegenheit, die Relevanz eines bereits behandelten Themas (Objektorientierte Programmierung) anhand eines spannenden Beispiels (Schwarmrobotik) aufzuzeigen und praktische Ansätze dazu aufzuzeigen:

Einzelthemen

  1. Schwarmintelligenz in der Natur
  2. Schwarmrobotik
  3. Anwendungsgebiete in der Technik
  4. Simulation von Roboterschwärmen
  5. Zelluläre Automaten
  6. Java / Processing
  7. Klassen und Objekte mit Java / Processing
  8. Objektorintierte Programmierung von Schwarmindividuen mit Verhaltensregeln
  9. ÜBUNG
  10. Fragenbeantwortung zur anstehenden Prüfung kommende Woche

1. Schwarmintelligenz in der Natur

Am Beispiel des Verhaltens von Schwärmen von Staren, lässt sich das Konzept "Schwarmverhalten" sehr anschaulich erfassen.

Schwarmverhalten von Staren -- https://www.youtube.com/watch?v=S4dRLomlTn4

Wissenschaftlich wird das Verhalten als "Flocking" bezeichnet und algorithmisch beschrieben:

"Flocking" -- https://en.wikipedia.org/wiki/Swarm_behaviour

Ein prominentes Beispiel für "Schwarmintelligenz" findet sich im Verhalten von Ameisen, wenn es ihnen als Gemeinschaft gelingt, "Straßen" zu bilden, die eine möglichst kurze Verbindung zwischen einem Futterplatz und dem bau bilden.

Dabei wurde herausgefunden, dass bei dem gemeinschaftlichen etablieren des besten Weges, das Ausschütten von Duftstoffen (Pheromone) eine wichtige Rolle spielt.

Ein Optimierungsalgorithmus, der sich an diesem Prinzip orientiert, wurde u.a. von Marco Dorigo entwickelt, siehe beispielsweise:

https://en.wikipedia.org/wiki/Ant_colony_optimization_algorithms
https://www.researchgate.net/publication/36146886_Ant_Colony_Optimization

2. Schwarmrobotik

3. Anwendungsgebiete in der Technik

Artikel bei Researchgate: Gabriele Valentini, Davide Brambilla, Heiko Hamann, and Marco Dorigo: Collective Perception of Environmental Features in a Robot Swarm: https://www.researchgate.net/profile/Gabriele-Valentini/publication/307144418_Collective_Perception_of_Environmental_Features_in_a_Robot_Swarm/links/5b0360d94585154aeb071ec9/Collective-Perception-of-Environmental-Features-in-a-Robot-Swarm.pdf
Collective Perception of Environmental Features in a Robot Swarm -- https://www.youtube.com/watch?v=0KJO4wh-SMc

4. Simulation von Roboterschwärmen

Schwarmvehikel007.zip -- Blockade des Antriebs wird erfasst und verarbeitet.

Screenshot zu Processing-Projekt Schwarmvehikel007: Blockade des Antriebs eines der Vehikel wird mit einem roten B angezeigt.

Bild 0-8: Screenshot zu Processing-Projekt Schwarmvehikel007: Blockade des Antriebs eines der Vehikel wird mit einem roten B angezeigt.

5. Zelluläre Automaten -- Schwarmintelligenz programmieren


Siehe Wikipedia "Game of Life"


https://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens
  • Ein einfaches System "intelligenter Partikel" soll programmiert werden:
  • Rote Partikel in einem einfachen "Schachbrettraster" haben die Aufgabe grüne Partikel zu ernten.
  • Dies gelingt genau dann, wenn sich um einen grünen Partikel genau 4 rote an den Kanten gruppieren.
  • Die roten Partikel bewegen sich von Zeitschritt zu Zeitschritt immer ein Feld in eine zufällige Richtung weiter.
  • Um die Aufgabe lösen zu können, wird folgende Zusatzregel eingefügt: Solche roten Partikel bewegen sich nicht mehr, wenn sie einen grünen als Nachbarn haben.
  • Da in dem Moment, wenn vier rote um einen grünen Partikel platziert sind, der grüne entfernt wird (Ernte), erlangen diese grünen Partikel danach wieder Bewegungsfreiheit.
  • Nachfolgend findet sich eine vollständige Implementierung dieses Algorithmus und auch einer Visualisierung mit Hilfe von Processing (siehe processing.org):
import java.util.Random;
//Random zufall = new Random(System.currentTimeMillis());
Random z = new Random(0);

int[][] m = new int[60][60];

public boolean istGeerntet(int i, int k, int[][] m)
{
     if(m[i-1][k]==1 && m[i+1][k]==1
     && m[i][k+1]==1 && m[i][k-1]==1)  
         return true;
     else
         return false;
}

public boolean mussStehen(int i, int k, int[][] m)
{
     if(i>0 && m[i-1][k]==2) return true;
     if(i<m.length-1 && m[i+1][k]==2) return true;
     if(k>0 && m[i][k-1]==2) return true;
     if(k<m.length-1 && m[i][k+1]==2) return true;
     return false;
}

public void schritt(int[][] m)
{
    for(int ii=0;ii<m.length*m.length;ii++)
    {
                  int i = z.nextInt(m.length);
                  int k = z.nextInt(m.length);
                  if(m[i][k]==2)
                  {
                       if(istGeerntet(i,k,m))
                          m[i][k]=0;
                  }
                  else if(m[i][k]==1)
                  {
                       if(!mussStehen(i, k, m))
                       {
                           if(z.nextBoolean())
                           {
                                if(z.nextBoolean())
                                {
                                    if(i+1<m.length-1 && m[i+1][k]==0)
                                    {
                                        m[i][k]=0;
                                        m[i+1][k]=1;
                                    }
                                }
                                else
                                {
                                    if(i-1>=0 && m[i-1][k]==0)
                                    {
                                        m[i][k]=0;
                                        m[i-1][k]=1;
                                    }
                                }
                           }
                           else
                           {
                                if(z.nextBoolean())
                                {
                                    if(k+1<m.length-1 && m[i][k+1]==0)
                                    {
                                        m[i][k]=0;
                                        m[i][k+1]=1;
                                    }
                                }
                                else
                                {
                                    if(k-1>=0 && m[i][k-1]==0)
                                    {
                                        m[i][k]=0;
                                        m[i][k-1]=1;
                                    }
                                }
                           }
                       }
                  }
    }
}

public void setup()
{
    for(int i=0;i<300;i++)
       m[z.nextInt(m.length)][z.nextInt(m.length)]=1;
    for(int i=0;i<100;i++)
       m[z.nextInt((m.length)/3)*3+1][z.nextInt((m.length)/3)*3+1]=2;
       
    size(600,600);
    frameRate(30);
}

public void draw()
{
    schritt(m);
    
    
    for(int i=0;i<m.length;i++)
    {
          for(int k=0;k<m[i].length;k++)
          {
                float x = (float)k*width/(float)m.length;
                float y = (float)i*width/(float)m.length;
                
                if(m[i][k]==0)
                   fill(0);
                else if(m[i][k]==1)
                   fill(255,0,0);
                else
                   fill(0,255,0);
                   
                rect(x,y,width/(float)m.length,width/(float)m.length);   
                
          }
    }
    
}

Code 0-36: "Fresser" -- einfaches Beispiel für Schwarmverhalten als Stand-Alone-Simulation mit Processing.

Szene aus

Bild 0-9: Szene aus "Fresser".

5. Java / Processing -- im Unterricht erarbeitet

6. Klassen und Objekte mit Java / Processing -- im Unterricht erarbeitet

7. Objektorientierte Programmierung von Schwarmindividuen mit Verhaltensregeln -- im Unterricht erarbeitet

8. ÜBUNG -- im Unterricht erarbeitet

9. Fragenbeantwortung zur anstehenden Prüfung kommende Woche

SchwarmOOP002.zip
SchwarmOOP003.zip
SchwarmOOP004.zip
  • Studentische Lösungen:
SchwarmOOP005.zip
SchwarmOOP06.zip
SchwarmOOP007.zip -- Zufallsbewegung fertig