Servotest Attiny

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


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


Zurück zum Servotest