2 Servos und 2 verschiedenen Impulslängen mit Timer0?

OP (Firma: allround) #1195897
Lesenswert?

Hallo,

im Arm meines Roboters sind 2 Servos. Servo 1 ist im Schultergelenk und 
Servo 2 im Ellbogengelenk.

Folgende Armbewegung will ich realisieren:

Oberarm und Unterarm hängen gestreckt am Körper runter. Beide Servos 
werden mit 1,5 ms angesteuert (Mittelstellung). Danach wird der 
komplette Arm (Oberarm und Unterarm) nach vorne gestreckt. Das heisst, 
Servo 1 wird mit jetzt mit 0,5 ms angesteuert und der Unterarm müsste 
aber seine 1,5 ms weiter bekommen. Der Unterarm hat ja noch seine 
gestreckte Position. Geht aber nicht, weil Timer0 ja alle 20ms nur eine 
einzige Impulslänge generieren kann, also entweder 0,5ms oder 1,5ms

Meine Frage:

Kann ich an einem Gelenkstück (Hand, Ellenbogen, Schultergelenk) mehrere 
Servos mit unterschiedlichen Impulslängen von 0,5 ms bis 2ms unabhängig 
versorgen? Die Impulse werden in der ISR von TIMER0 generiert.

Ich habe für mich die Frage insofern selbst beantwortet, dass ich sage: 
DAS KANN NICHT FUNZEN! Wie denn auch. Es sei denn, jemand von euch hätte 
eine Anregung, wie man sowas trotzdem realisieren kann. Vielleicht 
mehrere TIMER?

Alle Servos am Roboter arbeiten einwandfrei, wenn sie ihren "privaten" 
Impuls bekommen. Aber zeitgleich 2 unterschiedliche Impulse an den 
Servos am Arm???!!

Ausschnitt aus dem sehr umfangreichen Programm:

In der ISR wird "pos" per switch abgefragt und dementsprechend die PORTS 
gesetzt.
1
void arm_STEMMEN()  // stemmen
2

3
{
4
  switch(count)
5
  {
6
  case  140:   pos=0x0003;  break;  //  Ellenbogen 0,5ms
7
  case  200:   pos=0x0073;  break;  //  Ellenbogen 1,5ms
8
  case  280:   pos=0x0003;  break;   // Ellenbogen 0,5ms
9
  case  400:   count =120;  k++;   break;    
10
  } // Ende switch
11
          
12
    switch(k)
13
    {
14
     case 2:  k=0;  count=401;break;  
15
    } // Ende switch
16

17
} // End
18

19

20
########################## check von "pos" in der ISR #####################
21

22

23
ISR(TIMER0_OVF_vect) 
24
{
25
if (TCCR0 == 5) // wenn ja, dann ist die 20ms Pause zuende, es folgt Port setzen
26
      {
27

28
      switch(pos)
29
      {         
30
      case 0x0000:  TCNT0 = 0xd5; PORTC  &= ~(1<<PC0);   break; // 0 Grad
31
      case 0x0010:  TCNT0 = 0xB0; PORTC  &= ~(1<<PC0);   break; // 12 Grad
32
.............................................................
33

34
...........................................................
35

36
usw.
Persönliche Seite #1196032
Lesenswert?

> Ich habe für mich die Frage insofern selbst beantwortet, dass ich sage:
> DAS KANN NICHT FUNZEN!

So schlimm ist es nicht! Es kann funzen.

Wie wäre es, wenn du den Timer auf die kleinste gemeinsame Zeit 
einstellst (0,5ms) und alle anderen Zeiten als Vielfache dieser Zeit 
betrachtest, d.h. intern Zähler mitlaufen lässt?

Also der Timer als Taktgeber für eine Stoppuhr mit einem 0,5ms Takt. Der 
Zähler Servo1 startet bei 1 (0,5ms) und läuft bis 41 (Start+20ms) 
beginnt von vorne. Der Zähler Servo2 startet bei 3 (1,5ms) und läuft 
bis 43 (Start+20ms).
Persönliche Seite #1196069
Lesenswert?

ich hab mal eine Routine geschrieben die 3 Servos versorgt über EINEN 
Timer

Ablauf:

1. 1. Ausgang high -> Timer laden mit Pulslänge 1
2. Timer schlägt zu -> 1.Ausgang low, 2. Ausgang high -> Timer laden mit 
Pulslänge 2
3. Timer schlägt zu -> 2. Ausgang low, 3. Ausgang high -> Timer laden 
mit Pulslänge 3
4. ...

Du mußt dann natürlich die Pins alleine umschalten, das erledigt nicht 
mehr der Timer alleine...
OP (Firma: allround) #1196101
Lesenswert?

Hallo ihr beiden Hotliner,

gute Ideen, die ihr vorgeschlagen habt. Ich glaube, dass ich meine 10 
Servos im Roboter mit Timer0 versorgen kann. Die anderen Timer im MEGA16 
sind schon mit Encoder und Tastenentprellung beschäftigt. Ich setze mich 
diese Woche hin und berichte dann, inwieweit ich das realisieren konnte. 
Sehr interessante Antworten von euch.DANKE!

Udo
OP (Firma: allround) #1200476
Lesenswert?

Hallo Hotliner,


Danke für eure Anschubhilfe. Habe das Prinzip bei 2 Servos realisiert. 
Beide Servos werden unabhängig mit frei wählbaren Impulsen angesteuert. 
Der Einfachheit halber drehen in diesem Demoprogramm beide Servos von 
0,8ms nach 2,2ms jeweils in entgegengesetzte Richtung.

Es ist sehr wahrscheinlich die x-te Variante, um Servos unabhängig 
anzusteuern. Wer will, kann das Programm als Einstieg verwenden.

Ich programmiere noch nicht solange in C. Deshalb ist der Code 
möglicherweise noch umständlich.Aber er funktioniert tadellos. Trotzdem 
möcht ich mal bei den Experten nachfragen, wie ein optimierter, 
verkürzter Code aussieht. Würde mich über die eine oder andere Anregung 
freuen.

Hier mein Programm. Liebe Experten: Es ist bestimmt verbesserungswürdig. 
Bitte um eure Anregungen!!

Udo
1
// 2 unabhängige Servos drehen gleichzeitig in entgegengesetzte Richtung 
2
// Wechsel nach ca. 2 Sekunden
3

4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
#include <inttypes.h>
7

8
#define  F_CPU  7372800
9

10
// März 2009 o.k.    
11

12
//###################### Globale Variablen ###############################
13

14
volatile int  servolinks=3, scount, LR;
15

16
volatile int16_t warten;
17

18
volatile char s;
19

20
int S01_L_R(int);    //gleichzeitig
21

22
int S01_R_L(int);     //gleichzeitig
23

24

25
//###################### TIMER 0 #######################################
26

27
ISR(TIMER0_OVF_vect)     // Takt/8, alle 277us TOV
28

29
{  
30

31
S01_L_R(LR);
32

33
S01_R_L(LR);
34

35
} // Ende ISR
36

37
// ############### TIMER0 initialisieren ##################################
38

39
void init(void)
40
{  
41
  TIMSK =  (1<<TOIE0) ;   
42

43
  TCCR0 = (1<<CS01);    // Takt/8
44
  
45

46
  DDRC=0xff;
47
  PORTC = 0xff;
48

49
   sei();
50
}
51

52
// ###################### main #################################
53

54
int main(void)
55
{  
56
     init();
57

58
  LR=100;
59

60
      while(1) 
61
    { 
62
    
63
    }  // Ende while
64
    return 0;
65
} // Ende main
66

67

68

69
// ## Funktion Servo 0 und Servo 1  an C0 nach links und C1 nach rechts ##
70

71
int S01_L_R(int LR)      
72

73
{  
74
  if(s==0)
75
  {  
76
    if(scount<servolinks)     // Impuls wieder auf HIGH setzen 3 entspricht 1ms
77
    { 
78
    PORTC &=~((1<<PC1) | (1<<PC0));  // PIN C0 und PC1 LOW, damit Impulse am Servo HIGH
79
    } // Ende if
80

81
      else 
82
      {       
83
        if(scount>=3)
84
        { 
85
          { 
86
          PORTC |=(1<<PC0); // PIN C0 HIGH 0,8 ms erreicht, Impuls Servo LOW
87
          
88
          if(scount>=8)      
89
            { 
90
            PORTC |=(1<<PC1); // PIN C0 LOW 2 ms erreicht, Impuls Servo LOW
91
            }
92
          }
93
        } // Ende if,  jetzt 20ms Pause, damit Impuls LOW
94
        
95
      } // Ende else 
96

97
      scount++;
98
            
99
        if(scount >=72)    // warten bis 20ms vergangen sind
100
        { 
101
        scount=0;
102
        warten++;
103

104
          if(warten==100)
105
            { 
106
            warten=0;
107
            s=1;
108
            }
109
        }
110
  }
111
  return 0;
112
} // Ende funk 
113

114

115

116
// ## Funktion Servo 0 und Servo 1  an C0 nach rechts und C1 nach links ##
117

118
int S01_R_L(int LR)      
119

120
{ 
121
  if(s==1)
122
  { 
123
    if(scount<servolinks)   // Impuls wieder auf HIGH setzen 3 entspricht 1ms  
124
    
125
    { 
126
    PORTC &=~((1<<PC1) | (1<<PC0));  // PIN C0 und PC1 LOW, damit Impulse HIGH
127
    } // Ende if
128

129
      else 
130
      {       
131
        if(scount>=3)
132
        { 
133
          { 
134
          PORTC |=(1<<PC1);   // PIN C0 HIGH 0,8 ms erreicht, Impuls LOW
135
          
136
          if(scount>=8)      
137
            { 
138
            PORTC |=(1<<PC0);   // PIN C0 LOW 2 ms erreicht
139
            }
140
          }
141
        } // Ende if, jetzt 20ms Pause, damit Impuls LOW
142
        
143
      } // Ende else 
144

145
            scount++;
146
            
147
            if(scount >=72)    // warten bis 20ms vergangen sind
148
            { 
149
            scount=0;
150
            warten++;
151

152
              if(warten==100)
153
              { 
154
              warten=0;
155
              s=0;
156
              }
157
            }
158
  } // Ende if
159
  return 0;
160
} // Ende funk

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren