Realisierung eines Schedulers in Arduino-Projekten
(EN google-translate)
(PL google-translate)
Nachfolgend soll in mehreren Schritten aufgezeigt werden, wie ein Scheduler innerhalb eines Arduino-Projektes aufgebaut werden kann. Verwiesen wird hierbei auf die Materialien in Echtzeitsysteme 2, wo dies direkt auf einem ATmega32 erfolgt:

Als Beispielprojekt soll ein Metronom realisiert werden, das fest auf 120 BPM (Beats per minute) eingestellt ist und diesen möglichst genau einhalten soll.
Es soll auf den ersten von vier Schlägen einen hohen Pieps und auf den anderen einen tieferen Pieps von sich geben. Eine Kette von vier LEDs zeigt den aktuellen Schlag an.
Alle Projekte finden sich in folgendem .zip-File:
Zuordnung zwischen Timern und PWM-Ausgängen beim Arduino-Micro
|
Digitaler Ausgang Nr. | Pin-Bezeichnung Mikrocontroller | Zugeordneter Timer | Bit |
---|---|---|---|
3 | OC0B | Timer 0 | 8 |
5 | OC3A ~OC4A | Timer 3 und 4 | 3:16Bit 4:10Bit-Highspeed |
6 | OC4D | Timer 4 | 10Bit |
9 | OC1A ~OC4B | Timer 1 und 4 | 1:16Bit 4:10Bit-Highspeed |
10 | OC1B ~OC4B | Timer 1 und 4 | 1:16Bit 4:10Bit-Highspeed |
11 | OC0A ~OC1C | Timer 0 und 1 | 0:8Bit 1:16Bit |
13 | OC4A | Timer 4 | 4:10Bit-Highspeed |
Tabelle 0-1: Zuordung zwischen digitalem Ausgang und Timer
|

sched001_blink - Ausgangspunkt, Blinken auf Ausgang 2
int zustand = 0; void setup() { pinMode(2,OUTPUT); } void loop() { digitalWrite(2,1); delay(500); digitalWrite(2,0); delay(500); }
Code 0-1: sched001_blink.
CTC-Mode für Timer1
Register | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
---|---|---|---|---|---|---|---|---|
TCCR1A: | COM1A1 | COM1A0 | COM1B1 | COM1B0 | COM1C1 | COM1C0 | WGM11 | WGM10 |
TCCR1B: | ICNC1 | ICES1 | - | WGM13 | WGM12 | CS12 | CS11 | CS10 |
TCCR3A: | COM3A1 | COM3A0 | COM3B1 | COM3B0 | COM3C1 | COM3C0 | WGM31 | WGM30 |
TCCR3B: | ICNC3 | ICES3 | - | WGM33 | WGM32 | CS32 | CS31 | CS30 |
Tabelle 0-2: Konfigurationsregister zu Timer 1 und 3
WGM13=1 WGM12=1 WGM11=0 WGM10=0 darum (Mode 12 laut Tabelle, S.123 Datenblatt): TCCR1B |= (1<<WGM13); TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); 16MHz-Quarz. Vorteilung: 64, dann 250000Hz Zählung: TCCR1B &= ~(1<<CS12); TCCR1B |= (1<<CS11); TCCR1B |= (1<<CS10); Setzen der oberen Zählgrenze, die den Interrupt dann auslöst: ICR1=250; //damit 1kHz Interrupt. Setzen der Vorteilung: 16MHz Quarz. Vorteilung 16 Tabelle Seite 390 Datenblatt: TIMSK1 |= (1<<ICIE1);
Code 0-2: Einstellung für CTC-Mode bei Timer1 und Interrupt "on compare match"
Aufblitzen mit 2Hz == 120BPM
void setup() { TCCR1B |= (1<<WGM13); //Mode 12 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //256: 62500Hz TCCR1B |= (1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B &= ~(1<<CS10); ICR1=31250; //2Hz TIMSK1 |= (1<<ICIE1); //Mode 12 pinMode(2,OUTPUT); pinMode(4,OUTPUT); } void loop() { if(TCNT1<2000) digitalWrite(2,1); else digitalWrite(2,0); }
Code 0-3: sched003_timer1: Aufblitzen mit 2Hz == 120BPM
sched004_metronom
Umsetzung des Metronoms ohne Interrups
bool AN=false; void setup() { TCCR1B |= (1<<WGM13); //Mode 12 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //1024: 15625Hz TCCR1B |= (1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B |= (1<<CS10); ICR1=31250; //0,5Hz == 4 Schläge! // ICR1=15000; //0,5Hz == 4 Schläge! TIMSK1 |= (1<<ICIE1); //Mode 12 //4 LEDs: pinMode(2,OUTPUT); pinMode(4,OUTPUT); pinMode(6,OUTPUT); pinMode(8,OUTPUT); //1 Tonausgang, der nicht auf Timer1 basieren darf! pinMode(13,OUTPUT); } void loop() { if(TCNT1<500) //4 Schritte: 31250/4 == 7812.5 { digitalWrite(2,1); if(!AN) { tone(13,1720); AN=true; } } else if(TCNT1>7812 && TCNT1<8112) //2000+7812 { digitalWrite(4,1); if(!AN) { tone(13,880); AN=true; } } else if(TCNT1>15625 && TCNT1<15925) //2000+7812 { digitalWrite(6,1); if(!AN) { tone(13,880); AN=true; } } else if(TCNT1>23437 && TCNT1<23737) //2000+7812 { digitalWrite(8,1); if(!AN) { tone(13,880); AN=true; } } else { digitalWrite(2,0); digitalWrite(4,0); digitalWrite(6,0); digitalWrite(8,0); if(AN) { tone(13,0); AN=false; } } }
Code 0-4: sched004_metronom
Zusatz-LED bei Digital-Pin 12 durch Interrupt-Routine gesteuert
#include<avr/interrupt.h> volatile bool AN=false; volatile bool ZUSTAND=false; //SIGNAL(SIG_OUTPUT_COMPARE1) //ISR(SIG_OUTPUT_COMPARE1) //ISR(TIMER1_COMP_vect) ISR(TIMER1_COMPA_vect) { if(ZUSTAND) digitalWrite(12,ZUSTAND); else digitalWrite(12,ZUSTAND); ZUSTAND=!ZUSTAND; } void setup() { // TCCR1B |= (1<<WGM13); //Mode 12 TCCR1B &= ~(1<<WGM13); //Mode 4 TCCR1B |= (1<<WGM12); TCCR1A &= ~(1<<WGM11); TCCR1A &= ~(1<<WGM10); //1024: 15625Hz TCCR1B |= (1<<CS12); TCCR1B &= ~(1<<CS11); TCCR1B |= (1<<CS10); OCR1A=31250; //0,5Hz == 4 Schläge! // ICR1=31250; //0,5Hz == 4 Schläge! // ICR1=15000; //0,5Hz == 4 Schläge! // TIMSK1 |= (1<<ICIE1); //Mode 12 TIMSK1 |= (1<<OCIE1A); //Mode 4 sei(); //4 LEDs: pinMode(2,OUTPUT); pinMode(4,OUTPUT); pinMode(6,OUTPUT); pinMode(8,OUTPUT); //1 Tonausgang, der nicht auf Timer1 basieren darf! pinMode(13,OUTPUT); //durch Interrupt gesteuert: pinMode(12,OUTPUT); } void loop() { if(TCNT1<500) //4 Schritte: 31250/4 == 7812.5 { digitalWrite(2,1); if(!AN) { tone(13,1720); AN=true; } } else if(TCNT1>7812 && TCNT1<8112) //2000+7812 { digitalWrite(4,1); if(!AN) { tone(13,880); AN=true; } } else if(TCNT1>15625 && TCNT1<15925) //2000+7812 { digitalWrite(6,1); if(!AN) { tone(13,880); AN=true; } } else if(TCNT1>23437 && TCNT1<23737) //2000+7812 { digitalWrite(8,1); if(!AN) { tone(13,880); AN=true; } } else { digitalWrite(2,0); digitalWrite(4,0); digitalWrite(6,0); digitalWrite(8,0); if(AN) { noTone(13); AN=false; } } }
Code 0-5: sched005_interrupt
Aufgabe
Realisieren Sie auf der Grundlage des Schedulerprogramms eine zählende Semaphore.
Diese erhält zu Beginn eine Belegung m, die den verfügbaren Plätzen im Ringpuffer entsprechen.
Sie soll dazu benutzt werden, drei verschiedene Tonhöhen, die über Taster in unregelmäßigen Abständen eingegeben werden in einem Ringpuffer zu speichern (semaphore waiting / Verbrauch von Plätzen / m--).
Solange der Puffer nicht leer ist, sollen die gespeicherten Töne in Zeitintervallen von genau 0,5 Sekunden abgespielt werden (semaphore signaling / Freigabe von Pufferplätzen / m++).