Grundlagen der Mikrocontrollertechnik im Sommersemester 2025
(EN google-translate)
(PL google-translate)
|
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
|
1.2 Foto Dual In Line DIL Bauweise eines ATmega32 von Atmel.
|
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.
|
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
|
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
...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:
|
Aufgabe 2:
|
96_Arduino/22_Universal/02_LED_Leiste
|
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
|
esp32swarm -- ein Schwarmvehikel auf der Basis eines esp32c3 super mini -- 05_esp32AV/30_esp32swarm
Verwendete interne Peripherie:
|
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
|
Der Analog/Digital-Wandler (ADW) des ATmega32 -- 40_Mikrocontroller/09_ADW
Verwendung des Analog/Digital-Wandlers -- 40_Mikrocontroller/09_ADW/01_ADW
Sharp Entfernungssensor -- 05_esp32AV/30_esp32swarm/04_Sensorik
BITTE NIE VERPOLEN!!!!
|
4. Digitaler Eingang
|
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
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
|
Aufgabe 2
|
Aufgabe 3
|
|
#4 Do 24.04.2025
Projekt + Variation + Präsentation
|
Aufgabenstellung in Kurzfassung
|
* Ü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
Ü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)
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:
96_Arduino -- Pin Layout Arduino Micro.
|
//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
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
|
$ 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
|
#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.
|
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:
|
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
|
A Theoretischer Teil
|
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
|
96_Arduino/31_day_by_day -- siehe "Verwendung eines MPU6050 Beschleunigungssensors"
15_Einachser/02_Bauanleitung/06_MPU6050 -- Anwendungsfall Einachser
B Praktischer Teil
|
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
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
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
|
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.
Bild 0-3: Arduinoschaltung.
void setup()
{
//...vervollständigen
}
void loop()
{
//...vervollständigen
}
Code 0-33: Grundaufbau des Mikrocontroller-Programms
|
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.
Bild 0-4: timer1.
Bild 0-5: a3.
Bild 0-6: a2.
Timer/Counter1 Control Register B - TCCR1B:
Bild 0-7: tccy.
Fortsetzung der Aufgabe "Kür":
|
4. Arbeitsphase
5. Besprechung der Übungsaufgaben
Nachtrag zu Aufgabe 5
|
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
|
#12 Do 26.06.2025
Thema: Intermezzo -- Objektorientierte Programmierung bei der Simulation von Schwarmrobotik
|
Konzept für ein Fahrzeug, siehe 05_esp32AV
"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
Am Beispiel des Verhaltens von Schwärmen von Staren, lässt sich das Konzept "Schwarmverhalten" sehr anschaulich erfassen.
Wissenschaftlich wird das Verhalten als "Flocking" bezeichnet und algorithmisch beschrieben:
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://www.researchgate.net/publication/36146886_Ant_Colony_Optimization
2. Schwarmrobotik
3. Anwendungsgebiete in der Technik
4. Simulation von Roboterschwärmen
Schwarmvehikel007.zip -- Blockade des Antriebs wird erfasst und verarbeitet.
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"
|
|
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.
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
|
SchwarmOOP005.zip
SchwarmOOP06.zip
SchwarmOOP007.zip -- Zufallsbewegung fertig