Servotest Attiny
Abbildung 3-1: Testaufbau mit Attiny45 auf Steckplatine
Wie ich mit einem Attiny45 einen Servo ansteuere, zeige ich hier mit Hilfe eines Timerinterruptes.
Testaufbau:
Verwendete Bauteile und Komponenten:
- 1 Attiny45 / 8 MHz
- 1 Poti 10 kOhm
- 1 Resettaster
- 1 LED
- 1 Widerstand 220 Ohm
- 1 Programmierstecker 4-pol.
- 1 Analog-Servo (z.B. Modelcraft RS2 MG/BB)
- 1 Netzteil 5VDC, 1A
Abbildung 3-2: Testaufbau zum Servo-Test mit Attiny45
Testprogramm:
Im Testprogramm wird (wie bein Arduino-Testprogramm Variante 2) Mithilfe des Timer1 alle 20 ms ein zeitgesteuerter Interrupt (Timerinterrupt) erzeugt. Bei Auftreten des Interrupts wird ein Impuls mit einer Länge - in Abhängigkeit der Potentiometerstellung - von 600 bis 2400 us an den Servo ausgegeben. Die Impulslänge wird über die Funktion "delayMicroseconds" eingestellt, wobei bei einer Taktfrequenz des Attiny von 8 Mhz eine Auflösung von 8 us gegeben ist.
Wie ein Timerinterrupt bei einem Arduino programmiert wird, habe ich bereits hier gezeigt: Timer-Interrupt. Beim Attiny, am Beispiel des Timer1, funktioniert das sehr ähnlich:
- Vorteiler (Prescaler) festlegen -> Register TCCR1
- Ermittelter Vergleichswert eintragen -> Register OCR1C
- CTC-Modus aktivieren -> Register TCCR1
Der Vergleichswert kann mit folgender Formel ermittelt werden:
CPUFrequenz = 8.000.000 Hz
Periodendauer = 0,02 s (20 ms) -> Interruptfrequenz = 1 / 0,02 = 50 Hz
Mögliche Vorteiler = 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 und 16348
Mit Vorteiler von 1024 ergibt sich:
Vergleichswert = (8.000.000 / (1024 * 50)) - 1 = 155,25
Wie man einen Attiny mit Hilfe eines Arduino programmiert und den Bootloader für eine Taktfrequenz von 8 MHz installiert, findet ihr hier: Attiny programmieren
//Servo Testprogramm
//Code fuer Attiny45 / 8 MHz
//Author Retian
//Version 1.0
#define servoPin 3 //Servo auf PB3
#define potiPin 2 //Poti auf Pin ADC2
#define ledPin 1 //LED auf PB1
int potiWert;
int pwmTime;
void setup() {
pwmTime = 1500; //Servo1 in Mittenstellung
pinMode(servoPin, OUTPUT);
digitalWrite(servoPin, 0);
pinMode(ledPin, OUTPUT);
//LED leuchtet beim Start fuer 1 Sekunde (Funktionskontrolle)
digitalWrite(ledPin, 1);
delay(1000);
digitalWrite(ledPin, 0);
//Setzen der Register fuer 20 ms Timerinterrupt
cli(); // Loesche globales Interruptflag
TCNT1 = 0; //Loesche Timer Counter 1
TCCR1 = 0; //Loesche Timer Counter Controll Register
OCR1C = 155; //Setze Output Compare Register C
// Setze CS10, CS11 und CS13 - Clock Select Bit 10,11,13 (Prescaler 1024)
TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
//CTC-Mode ein
TCCR1 |= (1 << CTC1); // CTC-Mode (Clear Timer and Compare)
//Timer/Counter Interrupt Mask Register
TIMSK |= (1 << OCIE1A); //Output Compare A Match Interrupt Enable
sei(); //Setze globales Interruptflag}
void loop() {
potiWert = analogRead(potiPin);
pwmTime = map(potiWert, 0, 1023, 600, 2400);
}
ISR(TIMER1_COMPA_vect) //Interrupt-Serviceroutine
{
//Setzen des Servopins durch Registermanipulation (siehe: Ein-Ausgangsports)
PORTB |= (1 << PORTB3);
delayMicroseconds(pwmTime);
PORTB &= ~(1 << PORTB3);
}
Ein Anwendungsbeispiel findet ihr bei meiner Funkfernsteuerung, wo ich mit einem Attiny45 zwei Servos ansteuere: Servoansteuerung Attiny
Und auch hier, wo ich mit einem Attiny eine Modellbahn-Bahnschranke und eine Weiche oder ein Signal steuere: Modellbahnschranke, Weichensteuerung