www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega88 Timer problem


Autor: Aloha (Gast)
Datum:
Angehängte Dateien:

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

Autor: Stefan Weßels (swessels)
Datum:

Bewertung
0 lesenswert
nicht 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:
void T1_init(void) {
    DDRB |= 1<<PB1 | 1<<PB2;    //OC-Pins auf Ausgang
    ICR1 = 46080;   //Rahmenzeit 20ms
    //OutputCompare auf Portpins, Timer Mode 14, Prescaler 8
    TCCR1A |= 1<<COM1A1 | 1<<COM1B1 | 1<<WGM11;
    TCCR1B |= 1<<WGM13 | 1<<WGM12 | 1<<CS11;
}

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

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, also war mein Problem das der Servoimpulse nicht genau alle 20ms 
kam? Werde heute noch deinen Timer ausprobieren und berichten.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Stefan Weßels (swessels)
Datum:

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

Autor: Aloha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So habe den Quellcode an deinen Timer ,Stefan, angepasst. Hoffe ich habe 
alles richtig verstanden. Die Batterien sind zum laden gelegt. Dann 
werde ich es mal an den Servos probieren.

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Servos bewegen sich super! Jedoch beide bis an den 180° Anschlag 
sehr komisch. Komme irgendwie nicht auf den Fehler. Danke für den Timer 
nochmal =)

Autor: Aloha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ein weiteres Problem habe ich wenn ich den Servo nach fahren zu 
Position1 auf eine´andere Position fahren will. Er stoppt einfach bei 
Position 1 und macht dannach nichts mehr ( Hält aber seine Position ). 
Vllt kann mir jemand erklären warum das so ist.

Autor: Stefan Weßels (swessels)
Datum:

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

Autor: Stefan Weßels (swessels)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hab mal schnell was getippt....

So sollte das funktionieren:
#ifndef F_CPU
    #define F_CPU 18432000UL
#endif

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

#include <avr/io.h>
#include <util/delay.h>

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

int main(void) {
    init();
    _delay_ms(1000);
    while(1) {
        //Servos auf MIN
        OCR1A = SERVOMIN;
        OCR1B = SERVOMIN;
        
        _delay_ms(1000);
        
        //Servos auf CENTER
        OCR1A = SERVOCENTER;
        OCR1B = SERVOCENTER;
        
        _delay_ms(1000);
        
        //Servos auf MAX
        OCR1A = SERVOMAX;
        OCR1B = SERVOMAX;
        
        _delay_ms(1000);
        
        //Servos auf CENTER
        OCR1A = SERVOCENTER;
        OCR1B = SERVOCENTER;
        
        _delay_ms(1000);
    }
    return(1);
}
Dein LCD und das verändern der Werte musst Du selber reinfummeln....

Gruß,
Stefan

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow so früh morgens hilfst du mir schon :). DANKE!
Leider fahren die Servos immer noch beide auf MAX und bleiben da :(. Ich 
probiere weiter herum und melde mich wenn ich etwas merkwürdiges 
entdecke

Autor: Stefan Weßels (swessels)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal,

bist Du sicher, dass Du auf den Externen Quarz umgeschaltet hast? Wenn 
nicht würde das einiges erklären...

Das Timing sollte stimmen, den obigen Code habe ich, allerdings mit 
16MHz Takt, in einem aktuellen Projekt am laufen.

Gruß,
Stefan

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
muss leider sagen ja. Der Mc funktioniert zu 100% :(. Könnte vllt was 
mit den Servos nicht stimmen ?

Autor: Stefan Ernst (sternst)
Datum:

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

PS: Und dein eigener Code hat das selbe Problem.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beitrag "Re: Problem mit PWM und Servo"

Stunden lang gesucht...

Autor: Aloha (Gast)
Datum:

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

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich danke dir auch, vllt kannst du mir auch helfen das Problem zu lösen? 
Oder ist deine Antwort ein Hinweis darauf das ich eine anderen Timer 
Mode nehmen muss/soll.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aloha schrieb:
> Ich danke dir auch, vllt kannst du mir auch helfen das Problem zu lösen?

Was an dem zitierten Text verstehst du denn nicht?
Da steht doch unmissverständlich drin, wann ICR1 zu beschreiben ist.

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR1B |= (1<<WGM13)

WGM13 ist doch beiden Codes gesetzt

Autor: Aloha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Juhu!!! Hab den Fehler gefunden ... natürlich ein Hardware Problem, das 
Kabel das die beiden GNDs miteinander verbindet hatte einen Wackler. 
Danke an alle für die Hilfe

Autor: Stefan Weßels (swessels)
Datum:

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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Weßels schrieb:

> Ist Dir da mal was aufgefallen?

Nein, aber es steht halt im Datenblatt eindeutig drin, dass ICR1 erst 
beschrieben werden kann, nachdem man einen Timermode eingestellt hat, 
bei dem ICR1 TOP ist.
Wenn es andersherum trotzdem funktioniert, hast du Glück. Darauf 
verlassen würde ich mich nicht.

Autor: Stefan Weßels (swessels)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stefan,

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

    ICR1=SERVOFRAME;                //Impulswiederholzeit 20ms
    OCR1A=SERVOCENTER;                //Servo 1 Mittelstellung
    OCR1B=SERVOCENTER;                //Servo 2 Mittelstellung

    TCCR1B |= (1<CS11);

}

Danke für den Hinweis und frohe Feiertage!

Gruß,
Stefan

Autor: Aloha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Habs bei mir auch geändert und dazu noch ein paar Taster, um an die 
Grenzen des Servos zu fahren und die passenden Werten auf dem Display zu 
haben, eingebaut. Frohe Feiertage euch.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.