Atmega88 Timer problem

Gast #1526157
Lesenswert?

Hallo,

ich habe versucht 2 Servos mit dem Atmega88 zu steuern. Dabei arbeite 
ich zum ersten mal mit einem Timer (wie man bestimmt auch im Quellcode 
sieht :D).Beim Ausführen bewegen sich die Servos aber nur für ca 1/2 sec 
nachdem ich den mega88 resete(1mal reset = 1/2 bewegung der Servos). 
Ansosnten hört man ein brummen in den Servos.

-Habe den Timer nicht ganz genau bekommen. Problem?

Vllt ist es so wie ich es programmiert habe gar nicht möglich einen 
Servo zu betreiben.Hoffe ihr könnt mir vllt sagen was ich Falsch gemacht 
habe. Danke
Angehängte Dateien:
#1527108
Lesenswert?

Hallo,

>-Habe den Timer nicht ganz genau bekommen. Problem?

nein, kein Problem. Du solltest nur deine Impulse etwa alle 20ms 
widerholen.

Aber:

Du solltest anstatt des CTC - Modes lieber einen der PWM Modi benutzen. 
Im CTC wird jede Änderung der OCR1x Register sofort geschrieben. 
Dadürch könntest Du extrem kurze oder auch lange Servoimpulse erzeugen.

Ich würde Dir den Mode 14 (Fast-PWM) und einen prescaler von 8 
empfehlen. Dann hast Du 2304 Ticks/ms. Damit bekommst Du sowohl den 
Servoimpuls (1,1 - 1,9ms) als auch die Rahmenzeit von ca. 20ms locker in 
die Auflösung des Timers.

Beispiel:
1
void T1_init(void) {
2
    DDRB |= 1<<PB1 | 1<<PB2;    //OC-Pins auf Ausgang
3
    ICR1 = 46080;   //Rahmenzeit 20ms
4
    //OutputCompare auf Portpins, Timer Mode 14, Prescaler 8
5
    TCCR1A |= 1<<COM1A1 | 1<<COM1B1 | 1<<WGM11;
6
    TCCR1B |= 1<<WGM13 | 1<<WGM12 | 1<<CS11;
7
}

Jetzt musst Du nur noch OCR1A und OCR1B mit sinnvollen Werten füttern.
Buffern und so Weiter übernimmt der Mega88 für Dich.

Ich hoffe es hilft...

gruß,
 Stefan
#1527192
Lesenswert?

Aloha schrieb:
> Danke, also war mein Problem das der Servoimpulse nicht genau alle 20ms
> kam? Werde heute noch deinen Timer ausprobieren und berichten.

Probiers aus.
Aber normalerweise sind die 20ms noch das Variabelste in einer 
Servoansteuerung. Servos stören sich nicht daran, ob der Stell-Puls alle 
20ms oder alle 16 oder 18 oder 22 oder 12ms kommt.

Die 20ms resultieren aus der Übertragungstechnik auf der Funkstrecke und 
haben sich daraus ergeben. Für das Servo selbst haben sie kaum bis keine 
Bedeutung.

Servos knurren auch schon mal, wenn das Rückmeldepoti 'blöd steht'. 
Kennt jeder mit einer Fernsteuerung: Schieb den Gas-Knüppel am Sender um 
eine Rastung weiter (egal in welche Richtung) und sofort hört das 
Knurren auf.
#1527242
Lesenswert?

Hallo,

>Servoansteuerung. Servos stören sich nicht daran, ob der Stell-Puls alle
>20ms oder alle 16 oder 18 oder 22 oder 12ms kommt.

Da gebe ich Dir Recht. Aber ich denke dass nicht jedes Servo mit kurzen 
Impulswiederholungen klar kommt. Die 20ms sind halt Quasi-Standard.

@Aloha:
Die 20ms kommen zustande, weil im ursprünglichen PPM - 
Übertragungsverfahren 8 Kanäle sequenziell übertragen wurden. 8x2,1ms + 
8xPause + Synchronuisation entsprechen etwa 20ms.

Gruß,
Stefan
#1527998
Lesenswert?

Moin,

>void Servo1(unsigned char);

Gibt es da keine Compilerwarnung?

>for(i=0;i<2000;i++){_delay_ms(1);} // 2sec warten.

Das kannst Du auch so schreiben:
1
_delay_ms(2000);
 Die Variable i brauchst Du dann nicht mehr. Es gab wohl früher die 
Einschränkung, dass nur 255 ms Verzögerung möglich waren, heute geht 
mehr.

Warum die Servos nicht fahren muss ich mir mal genauer anschauen. Auf 
den Ersten Blick sehe ich nichts.

Die Ansteuerung der Servos mit Graden ist etwas schwierig. Die meisten 
Servos bewegen sich zwischen 1,1ms und 1,9ms Impulslänge um 90°, also 
ausgehend von der Mittelstellung bei 1,5ms um +/- 45°. Es gibt auch 
welche mit +/- 90°. ABer verlassen würde ich mich darauf nicht.

Ich würde nicht mit Grad sondern mit Prozenten arbeiten, so in Richtung 
+-100% Weg.

Ich suche mal ein Beispiel, melde mich dann wieder.

Gruß,
Stefan
#1528022
Lesenswert?

So, hab mal schnell was getippt....

So sollte das funktionieren:
1
#ifndef F_CPU
2
    #define F_CPU 18432000UL
3
#endif
4

5
//servo values
6
#define SERVOMAX 4377                //1,9ms => +100% => (F_CPU / 8 / 1000 * 1,9) -1
7
#define SERVOMIN 2533                //1,1ms => -100% => (F_CPU / 8 / 1000 * 1,1) -1
8
#define SERVOCENTER 3455            //1,5ms => 0% => (F_CPU / 8 / 1000 * 1,5) -1
9
#define SERVOFRAME 46079            //20ms => (F_CPU / 8 / 1000 * 20) -1
10

11
#include <avr/io.h>
12
#include <util/delay.h>
13

14
void init(void) {
15
    DDRB |= (1<<PB1) | (1<<PB2);    //OCR1x Ports auf Ausgang
16
    
17
    //Timer0, Mode 14 Fast-PWM, prescaler 8
18
    ICR1=SERVOFRAME;                //Impulswiederholzeit 20ms
19
    OCR1A=SERVOCENTER;                //Servo 1 Mittelstellung
20
    OCR1B=SERVOCENTER;                //Servo 2 Mittelstellung
21
    
22
    TCCR1A |= (1<<COM1A1) | (1<<COM1B1) |(1<<WGM11);
23
    TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11);
24
}
25

26
int main(void) {
27
    init();
28
    _delay_ms(1000);
29
    while(1) {
30
        //Servos auf MIN
31
        OCR1A = SERVOMIN;
32
        OCR1B = SERVOMIN;
33
        
34
        _delay_ms(1000);
35
        
36
        //Servos auf CENTER
37
        OCR1A = SERVOCENTER;
38
        OCR1B = SERVOCENTER;
39
        
40
        _delay_ms(1000);
41
        
42
        //Servos auf MAX
43
        OCR1A = SERVOMAX;
44
        OCR1B = SERVOMAX;
45
        
46
        _delay_ms(1000);
47
        
48
        //Servos auf CENTER
49
        OCR1A = SERVOCENTER;
50
        OCR1B = SERVOCENTER;
51
        
52
        _delay_ms(1000);
53
    }
54
    return(1);
55
}
Dein LCD und das verändern der Werte musst Du selber reinfummeln....

Gruß,
Stefan
#1529081
Lesenswert?

Der Code meines Namensvetters kann nicht funktionieren, weil ...
Zitat Datenblatt:
1
The ICR1 Register can only be written when using a Waveform Generation
2
mode that utilizes the ICR1 Register for defining the counter’s TOP value.
3
In these cases the Waveform Generation mode (WGM13:0) bits must be set
4
before the TOP value can be written to the ICR1 Register.

PS: Und dein eigener Code hat das selbe Problem.
Gast #1529304
Lesenswert?

@Stefan Ernst

Weiter unten im Handbuch bei Fast PWM steht aber dann ->
Using the ICR1 Register for defining TOP works well...

@STK500-Besitzer

Danke, habe mir alles durchgelesen, habe jedoch noch Probleme deinen 
Code an meinen MC anzupassen um ihn zu testen, werde schreiben ob er 
Funktioniert hat sobald ich es geschafft habe ihn zu ändern
#1529309
Lesenswert?

Aloha schrieb:
> @Stefan Ernst
>
> Weiter unten im Handbuch bei Fast PWM steht aber dann ->
> Using the ICR1 Register for defining TOP works well...

Ja und? Ich habe ja nicht gesagt, dass es grundsätzlich nicht 
funktioniert. Es funktioniert nur nicht so, wie es jetzt im Code steht, 
weil ICR1 zum richtigen Zeitpunkt beschrieben werden muss. Oder meinst 
du der von mir zitierte Text steht nur aus Spaß im Datenblatt?
#1529351
Lesenswert?

Hallo Stefan,

>Es funktioniert nur nicht so, wie es jetzt im Code steht,
>weil ICR1 zum richtigen Zeitpunkt beschrieben werden muss.

ich gebe zu dass ich das Datenbaltt nicht allzu genau gelesen habe. Aber 
der Code funktioniert trotzdem. Bei mir zwar auf nem Mega168, aber beim 
Timer1 unterscheidet der sich nicht vom Mega88.

Ich setze ICRx / OCRx bei allen PWM Modi so wie oben und hatte noch nie 
Probleme. Ich habe bisher Tiny13, Tiny25, Mega8 , Mega168 und Mega16 
verwendet.

Ist Dir da mal was aufgefallen?

Gruß,
Stefan
#1529461
Lesenswert?

Hallo Stefan,

dann werde ich es in Zukunft so machen ( Habe den Passus im Datenblatt 
gefunden):
1
void init(void) {
2
    DDRB |= (1<<PB1) | (1<<PB2);    //OCR1x Ports auf Ausgang
3
    
4
    //Timer0, Mode 14 Fast-PWM, prescaler 8
5
    
6
    TCCR1A |= (1<<COM1A1) | (1<<COM1B1) |(1<<WGM11);
7
    TCCR1B |= (1<<WGM13) | (1<<WGM12);
8

9
    ICR1=SERVOFRAME;                //Impulswiederholzeit 20ms
10
    OCR1A=SERVOCENTER;                //Servo 1 Mittelstellung
11
    OCR1B=SERVOCENTER;                //Servo 2 Mittelstellung
12

13
    TCCR1B |= (1<CS11);
14

15
}

Danke für den Hinweis und frohe Feiertage!

Gruß,
Stefan

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