Hallo zusammen.
Für ein kleines Projekt (Spinnenbein) sollen 3 Servos angesteuert
werden. Da ich mich erst seit kurzem mit uControllern auseinander setzte
habe ich mich an einigen Tutorials aus diesem Forum bedient.
Bei den Servos tritt nun ein "zittern" auf, welches ich bereits auf eine
zu kurze Pausenzeit zwischen den Pulsen zurückführen konnte. Ich habe
nun versucht eine Pause-Phase nach der Ansteuerung der Servos
hinzuzufügen. Beim Betrachten der Signale am Oszilloskop habe ich
festgestellt,dass Kanal B0 nach erfolgreicher ansteuerung aller Känäle
für ca 21ms "high" und anschliessend der Pausentakt viel länger als
vorgesehen ist. Leider sehe ich aber den Grund dazu nicht..
Gesamter Code
1 | // +------------------------------------------------------------
|
2 | // ¦ Project: Leg
|
3 | // +------------------------------------------------------------
|
4 | // ¦ Author: User
|
5 | // ¦ Date: 1/21/2018 4:23:14 PM
|
6 | // ¦
|
7 | // ¦ Processor: ATmega8
|
8 | // +------------------------------------------------------------
|
9 |
|
10 | #define F_CPU 8000000UL
|
11 | #include <avr/io.h>
|
12 | #include <avr/interrupt.h>
|
13 | #include <util/delay.h>
|
14 |
|
15 | #define Servos 3
|
16 | #define ServoCycle 20000
|
17 |
|
18 | int Servo[Servos] = {1<<PB0, 1<<PB1, 1<<PB2};
|
19 | volatile int ServoValue[Servos];
|
20 |
|
21 | // ¦ Interrupt - SERVO-PWM
|
22 | // +------------------------------------------------------------
|
23 | ISR(TIMER1_COMPA_vect)
|
24 | {
|
25 | static int ServoID = 0;
|
26 | static int ServoCycleIdle = ServoCycle;
|
27 |
|
28 | if (ServoID < Servos)
|
29 | {
|
30 | // aktuellen Servo absteuern
|
31 | PORTB &= ~Servo[ServoID];
|
32 |
|
33 | // ServoID erhöhen
|
34 | ServoID ++;
|
35 |
|
36 | // aktuellen Servor ansteuern
|
37 | PORTB |= Servo[ServoID];
|
38 |
|
39 | // Pulsdauer übergeben
|
40 | OCR1A = ServoValue[ServoID];
|
41 |
|
42 | // Pausendauer berechnen
|
43 | ServoCycleIdle -= ServoValue[ServoID];
|
44 | }
|
45 | else // Pause ausführen / Servo 0 ansteuern
|
46 | {
|
47 | if (ServoID == Servos) // Pause ausführen
|
48 | {
|
49 | // aktuellen Servo absteuern
|
50 | PORTB &= ~Servo[ServoID];
|
51 |
|
52 | // ServoID erhöhen
|
53 | ServoID ++;
|
54 |
|
55 | // Pausendauer übergeben & rücksetzen
|
56 | OCR1A = ServoCycleIdle;
|
57 | ServoCycleIdle = ServoCycle;
|
58 | }
|
59 | else // Servo 0 ansteuern
|
60 | {
|
61 | // ServoID rücksetzen
|
62 | ServoID = 0;
|
63 |
|
64 | // aktuellen Servor ansteuern
|
65 | PORTB |= Servo[ServoID];
|
66 |
|
67 | // Pulsdauer übergeben
|
68 | OCR1A = ServoValue[ServoID];
|
69 |
|
70 | // Pausendauer berechnen
|
71 | ServoCycleIdle -= ServoValue[ServoID];
|
72 | }
|
73 | }
|
74 | }
|
75 |
|
76 |
|
77 |
|
78 | int main(void)
|
79 | {
|
80 | // ¦ Konfiguration SERVO
|
81 | // +------------------------------------------------------------
|
82 | // Pins setzen
|
83 | DDRB = (1<<PB0) | (1<<PB1) | (1<<PB2); // Ausgänge setzen
|
84 | //Zähler konfigurieren
|
85 | TCCR1B = (1<<WGM12) | (1<<CS11); // CTC-Mode & Prescacler=8 (F_CPU / 8 = 100000Hz --> 1us)
|
86 | TIMSK = (1<<OCIE1A); // Timer-Interrupts für Vergleichswerte
|
87 |
|
88 | // ¦ Interrupt einschalten
|
89 | // +------------------------------------------------------------
|
90 | sei();
|
91 |
|
92 | while (1)
|
93 | {
|
94 | ServoValue[0] = 1500;
|
95 | ServoValue[1] = 1500;
|
96 | ServoValue[2] = 1500;
|
97 | }
|
98 | }
|
Hat von Euch jemand eine Idee?
Grüsse Sam