Forum: Mikrocontroller und Digitale Elektronik 4x Servo-PWM mit ATTiny2313


von Alex B. (alde_oma)


Lesenswert?

Hi,

ich versuche mit dem Attiny2313 4 Servos anzusteuern.
habe mit Timern leider nicht besonders viel Erfahrung.
Jetzt hab ich hier im FOrum den Beitrag 
http://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung#Signalerzeugung_f.C3.BCr_1_Servo_mittels_Timer_.28C.29 
gefunden und habe ihn versucht auf die 4 Servos anzupassen. Mit halbem 
Erfolg...
Hier mal mein Code:
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
7
ISR( TIMER0_COMPA_vect )                // Interruptbehandlungsroutine
8
{
9
  OCR0A = 2500-OCR0A;      
10
}
11
12
ISR( TIMER0_COMPB_vect )                // Interruptbehandlungsroutine
13
{
14
  OCR0B = 2500-OCR0B;      
15
}
16
17
ISR( TIMER1_COMPA_vect )                // Interruptbehandlungsroutine
18
{
19
  OCR1A = 2500-OCR1A;      
20
}
21
22
ISR( TIMER1_COMPB_vect )                // Interruptbehandlungsroutine
23
{
24
  OCR1B = 2500-OCR1B;      
25
}
26
27
void init_pwm (void)
28
{
29
  
30
  // Timer 0 PWM Init
31
32
    TCCR0A = (0 << WGM00) | (1 << WGM01) | (1 << COM0A0) | (1 << COM0B0);
33
    TCCR0B = (0 << WGM02) | (1 << CS00) | (1 << CS01) | (0 << CS02);
34
35
36
  // OC0A PWM Port
37
38
  DDRB   |= (1 << PB2);
39
40
  OCR0A = 139;
41
42
43
  // OC0B PWM Port
44
  
45
  DDRD   |= (1 << PD5);
46
47
  OCR0B = 139;
48
  
49
50
  // Timer 1 PWM Init
51
52
  TCCR1A = (1 << COM1A0) |(1 << COM1B0);
53
  TCCR1B = (1 << WGM12) | (1 << CS11);
54
  TIMSK  = (1 << OCIE1A) | (1 << OCIE1B) |(1 << OCIE0A) | (1 << OCIE0B);                 // Timer-Compare Interrupt an
55
56
  // OC1A PWM Port
57
58
  DDRB   |= (1 << PB3);
59
  
60
  OCR1A = 2250;  //2250-2,0 ms
61
          //2312-1,5 ms
62
          //2374-1,0 ms
63
64
  // OC1B PWM Port
65
66
  DDRB   |= (1 << PB4);
67
  
68
  OCR1B = 1125;  //1185-1,0 ms
69
          //1156-1,5 ms
70
          //1125-2,0 ms
71
          
72
}
73
74
int main (void) {
75
  
76
  init_pwm();
77
  sei();
78
  
79
  while(1){
80
    
81
  }
82
  
83
84
}

Timer1A funktioniert wie er soll. Timer1B eigenlich auch. Jedoch die 
Frage, warum der OCR1B auf einen anderen Wert gesetzt werden muss, damit 
ich das gleiche Ergebnis erhalte? Genauso beim Timer0. Den bekomme ich 
nicht auf 20ms.
Ich könnte auch mit _delay_ms arbeiten, da der Tiny sonst nichts anderes 
macht, aber wenn ich jetzt dabei bin, möchte ich natürlich eine richtige 
PWM erzeugen.
Habe auch schon beispiele gesehen, bei denen ICR1 als angabe dient, die 
Periodendauer anzugeben.. Bin im Moment etwas verwirrt.

von Simon R. (simon_r44)


Lesenswert?

Also die RS-2 Servos sind komisch, deshalb haben die mit 
Rechenbeispielen auch nie in die Stellung gekommen die man wollte also 
sind die Werte für OCR1A experimentell ermittelt worden...

von Alex B. (alde_oma)


Lesenswert?

Hi,

ich habe die Servos im Moment noch nicht angeschlossen. Beobachte die 
Signale mit einem Oszi.

von Simon R. (simon_r44)


Lesenswert?

Alex B. schrieb:
> Hi,
>
> ich habe die Servos im Moment noch nicht angeschlossen. Beobachte die
> Signale mit einem Oszi.

Was willst du mit den 4 Servos genau anstellen? Hab da auch mal ne Weile 
an so einem Programm rumgebastelt (auch für den 2313) das aber nie 
sonderlich gut lief...

von Alex B. (alde_oma)


Lesenswert?

Hi,
ich will Brushlessmotoren betrieben. Und der Brushless-Controller 
benötigt das PWM-Signal eines Servos.

von Jasson (Gast)


Lesenswert?

Du könntest auch einen anderen Ansatz wählen und die PWM von nur einem 
OCR Output erzeugen lassen und multiplexen. Löte 4 Widerstände (z.B. 
4k7) an den Pin. Die vom Controller abgewandten Seite verbindest du 
jeweils mit einem Prozessor Pin, den du aber nur zwischen LOW und 
Floating schaltest. Bis auf einen MultiplexPin sind alle LOW und du 
lädst das OCR Register mit dem zugehörigen Wert. Sind alles Kanäle 
abgearbeitet, wartest du noch die Totzeit ab. Dann beginnt das Spiel von 
vorne.

von Alex B. (alde_oma)


Lesenswert?

Wäre auch noch eine Idee. Ich möchte aber wie beschrieben die PWM 
"richtig" erzeugen, damit ichs jetzt kapiere und für spätere Projekte 
nutzen kann.
Mein Hauptproblem ist im Moment kurzgefasst: Wie stelle ich die 
Periodendauer und die Pulsdauer der einzelnen Timer ein?

von Karl H. (kbuchegg)


Lesenswert?

generelle Timerberechnung
FAQ: Timer

Im übrigen gebe ich Jasson recht. Es ist nicht wirklich klug, seine 
kostbaren Timer für das Erzeugen von 4 PWM Signalen zu verschwenden, 
wenn das 1 Timer alleine genausogut kann, und man damit dann noch nicht 
mal auf die Pins festgenagelt ist. Am 'Timer lernen' und wie man damit 
Zeiten berechnet ändert das ja nichts.

: Bearbeitet durch User
von Alex B. (alde_oma)


Angehängte Dateien:

Lesenswert?

Hi,

die Timerberechnung habe ich mittlerweile hinbekommen. Was mich aber 
immernoch verwirrt, ist die Sache, dass bei mir Timer1A und 1B andere 
Werte haben, damit ich 20ms zusammenbekomme.

Beschaltung siehe Anhang...
Kannst du das mit dem Schalten nochmal etwas genauer erklären? Komm da 
grad nicht mit.

von Stefan us (Gast)


Lesenswert?

Schau von meinem Programm ab: 
http://stefanfrings.de/servocontroller/ServoController.zip

Ich nutze einen Timer und ein Compare-Register, um 5 PWM Signale zu 
erzeugen. Das Multiplexing erledigt die Interrupt-Routine.

Das zweite Compare Register nutze ich, um weitere 5 Kanäle zu 
implementieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.