Forum: Mikrocontroller und Digitale Elektronik Ansteuerung von 3 Servos alle 20ms


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Sam G. (asiris)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert

von Sam G. (asiris)


Bewertung
0 lesenswert
nicht lesenswert
Besten Dank für den Link zum Beitrag. Damit hats geklappt.
1
ISR(TIMER1_COMPA_vect)
2
{
3
  static int ServoID = 0;
4
  static int ServoCycleIdle = ServoCycle;
5
  
6
  
7
  switch (ServoID)
8
  {
9
    case 0:                // Servo 0
10
    PORTB |= Servo[0];          // Servopuls 0 setzten
11
    OCR1A = ServoValue[0];        // Pulsdauer 0 an Timer übergeben
12
    ServoCycleIdle -= ServoValue[0];  // Pulsdauer 0 von CycleIdle abziehen
13
    break;
14
    case 1:                // Servo 1
15
    PORTB &= ~Servo[0];          // Servopuls 0 rücksetzten
16
    PORTB |= Servo[1];          // Servopuls 1 setzten
17
    OCR1A = ServoValue[1];        // Pulsdauer 1 an Timer übergeben
18
    ServoCycleIdle -= ServoValue[1];  // Pulsdauer 1 von CycleIdle abziehen
19
    break;
20
    case 2:                // Servo 2
21
    PORTB &= ~Servo[1];          // Servopuls 1 rücksetzten
22
    PORTB |= Servo[2];          // Servopuls 2 setzten
23
    OCR1A = ServoValue[2];        // Pulsdauer 2 an Timer übergeben  
24
    ServoCycleIdle -= ServoValue[2];  // Pulsdauer 2 von CycleIdle abziehen
25
    break;
26
    case 3:                // Pausendauer
27
    PORTB &= ~Servo[2];          // Servopuls 2 rücksetzten
28
    OCR1A = ServoCycleIdle;        // CycleIdle an Timer übergeben
29
    ServoCycleIdle = ServoCycle;    // CycleIdle rückstzen
30
    break;
31
  }
32
  
33
  ServoID++;                // ServoID hochzählen
34
  if (ServoID > Servos) ServoID = 0;    // ServoID rücksetzen
35
}

von Ent Tabber (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Sam G. schrieb:
> Besten Dank für den Link zum Beitrag. Damit hats geklappt.

Ich kann so ein Chaos nicht ansehen.
1
ISR (TIMER1_COMPA_vect)
2
{
3
  static int ServoID = 0;
4
  static int ServoCycleIdle = ServoCycle;
5
6
  switch (ServoID)
7
  {
8
    case 0:                             // Servo 0
9
      PORTB |= Servo[0];                // Servopuls 0 setzten
10
      OCR1A  = ServoValue[0];           // Pulsdauer 0 an Timer übergeben
11
      ServoCycleIdle -= ServoValue[0];  // Pulsdauer 0 von CycleIdle abziehen
12
    break;
13
    case 1:                             // Servo 1
14
      PORTB &= ~Servo[0];               // Servopuls 0 rücksetzten
15
      PORTB |= Servo[1];                // Servopuls 1 setzten
16
      OCR1A  = ServoValue[1];           // Pulsdauer 1 an Timer übergeben
17
      ServoCycleIdle -= ServoValue[1];  // Pulsdauer 1 von CycleIdle abziehen
18
    break;
19
    case 2:                             // Servo 2
20
      PORTB &= ~Servo[1];               // Servopuls 1 rücksetzten
21
      PORTB |= Servo[2];                // Servopuls 2 setzten
22
      OCR1A  = ServoValue[2];           // Pulsdauer 2 an Timer übergeben
23
      ServoCycleIdle -= ServoValue[2];  // Pulsdauer 2 von CycleIdle abziehen
24
    break;
25
    case 3:                             // Pausendauer
26
      PORTB &= ~Servo[2];               // Servopuls 2 rücksetzten
27
      OCR1A  = ServoCycleIdle;          // CycleIdle an Timer übergeben
28
      ServoCycleIdle = ServoCycle;      // CycleIdle rückstzen
29
    break;
30
  }
31
32
  ServoID++;                            // ServoID hochzählen
33
  if (ServoID > Servos) ServoID = 0;    // ServoID rücksetzen
34
}

von hankok (Gast)


Bewertung
-2 lesenswert
nicht lesenswert
Ent Tabber schrieb:
> Sam G. schrieb:
>> Besten Dank für den Link zum Beitrag. Damit hats geklappt.
>
> Ich kann so ein Chaos nicht ansehen.

Ohne einen erläuterten Bezug schau ich deinen Text erst gar nicht an.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.