Servo will nicht richtig, Programm oder Hardwarefehler?

OP #3275945
Hallo zusammen,

ich wollte nun mal testen, ob ich es schaffe mit einem AVR einen Servo 
zu steuern.

Der Servo besitzt eine eigene Spannungsversorgung und ist mit der 
Steuersignalleitung und GND mit einem ATmega8 verbunden.

Der ATmega8 arbeitet mit 12MHz.
Wenn ich den Servo mit Spannung versorge bewegt er sich ein Stück vor.

Durch das jetzige Programm passiert nichts, wenn ich eine Taste drucke, 
um die Servoposition zu ändern. Ich weiß, dass die Tasten nicht 
entprellt sind, aber das ist ja so nur zum testen ;-)

Ich hatte mit einem etwas anderen Programm den Servo so, dass ich ihn 
einmal per Taste bewegen konnte und dann stürzte der AVR ab, weil ich 
keinen Prescaler genutzt habe und der Timerwert größer als 16 bit wurde. 
Das ist zumindest meine Vermutung ;-)


Hat jemand eine Idee, was falsch ist?
Ein Oszi habe ich leider nicht zur Verfügung, sonst hätte ich mal 
geschaut, wie mein Signal aussieht.

Danke :-)
1
#include <avr/io.h>
2

3

4
int main(){
5
  int ServoPos;
6
  DDRB |= (1<<DDB1); // PB1 (=OC1A) als Ausgang
7
  PORTB|= (1<<PD0) | (1<<PD1) | (1<<PD2);  // PullUp für Taster an PD0,1,2
8
  TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<<WGM10); // Ausgang OC1A bei 0 setzen und bei OCR1A loeschen
9
  TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11); // Waveform Generation Mode: Fast PWM it OCR1A als Top, Timer mit CPU-CLK // Prescaler auf 8
10
  OCR1A = 29999; // alle 20 ms 
11
  
12
  while (1){ // Endlosschleife
13
  OCR1B = ServoPos;  
14
  if (!(PIND & (1<<PIND0))) {ServoPos=1500}; //entspricht 1 ms
15
  if (!(PIND & (1<<PIND1))) {ServoPos=2250}; //entspricht 1,5 ms
16
  if (!(PIND & (1<<PIND2))) {ServoPos=3000};}//entspricht 2 ms
17
}
Hallo,
ich habe mich gestern auch damit beschäftigt. Ich glaube dein fPWM 
benutzt das falsche Register.
Anstatt OCR1A = 29999; versuch mal
1
ICR1=29999;

zu verwenden.
Weil OCR1 das ist ja der compare Wert bei dem die Flanke auf 0 gehen 
soll, ICR ist TOP, also da wo der Zähler wieder auf 0 geht.

Hm, bissel schlecht erklärt, aber ich denke somit sollte es gehen, die 
Hintergründe und richtige Bezeichnungen kann ja eventuell noch mal ein 
Profi hier erklären.

Lieben Gruß,
ps
OP
Wolfgang schrieb:
> R. B. schrieb:
>> Ein Oszi habe ich leider nicht zur Verfügung, sonst hätte ich mal
>> geschaut, wie mein Signal aussieht.
>
> Aber einen Simulator hast du doch - oder welche Entwicklungsumgebung
> benutzt du?

Ich habe keinen Simulator, da ich Visual Studio mit AVR GCC nutze.
Zugegeben, ein Simulator wäre nicht verkehrt ;)


Peter Shaw schrieb:
> Anstatt OCR1A = 29999; versuch mal
> ICR1=29999;
>
> zu verwenden.
> Weil OCR1 das ist ja der compare Wert bei dem die Flanke auf 0 gehen
> soll, ICR ist TOP, also da wo der Zähler wieder auf 0 geht.

Ich habe gerade mal einen Blick ins Datenblatt geworfen und ich denke du 
hast recht, dass ich ICR1 nehmen muss. (Ist mein Erstkontakt mit PWM und 
alles noch nicht so 100 % verstanden ;) )

Leider ändert sich nichts.
Der Servo mag noch immer nicht.
OP
Ok, ich habe jetzt nochmal alles mit dem Datenblatt vom Meg8 verglichen 
und festgestellt, dass WGM10, wenn ich ICR1 als Top nehmen möchte 0 sein 
muss.

Den Servo habe ich mal testweise an den Pin vom genutzten Quarz gehalten 
und da bewegt er sich munter in alle Richtungen wild hin und her. Am 
Servo scheint es also nicht zu liegen.

Mein Programm sieht jetzt so aus:
1
#include <avr/io.h>
2

3

4
int main(){
5
  int ServoPos;
6
  DDRB |= (1<<DDB1); // PB1 (=OC1A) als Ausgang
7
  PORTB|= (1<<PD0) | (1<<PD1) | (1<<PD2);  // PullUp für Taster an PD0,1,2
8
  TCCR1A |= (1<<COM1A1) | (1<<WGM11); // Ausgang OC1A bei 0 setzen und bei ICR1 loeschen
9
  TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11); //Fast PWM it ICR1 als Top // Prescaler auf 8
10
  ICR1 = 29999; // alle 20ms 
11
  
12
  while (1){ // Endlosschleife
13
  OCR1B = ServoPos;  // Impulslaenge 1,5ms bei 12 MHZ und Prescaler 8 = 18000
14
  if (!(PIND & (1<<PIND0))) {ServoPos=1500};
15
  if (!(PIND & (1<<PIND1))) {ServoPos=2250};
16
  if (!(PIND & (1<<PIND2))) {ServoPos=3000};}
17
}

Leider funktioniert nach wie vor nichts und mir fällt leider momentan 
nichts mehr ein.

Hat jemand eine Idee?
Danke :-)
OP
Spess53 schrieb:
> Hi
>
>>PORTB|= (1<<PD0) | (1<<PD1) | (1<<PD2);  // PullUp für Taster an PD0,1,2
>
> Soll das so sein?
>
> MfG Spess

Hi, jepp, weil die Taster als ActiveLow angeschlossen sind.

Ich habe eben mal die Taster durch eine Schleife ersetzt, die die Werte 
für die Servoposition ändert.
Bringt aber leider nichts.

Ich bin mir nun auch unsicher, ob OCR1A oder B der Ausgang sein muss und 
steig langsam nicht mehr durch.
Ich habe aber beides getestet und den Servo umgesteckt sowie OCR1B auch 
als Ausgang definiert. Trotzdem keine Reaktion!

Lediglich bein Reset des AVRs bewegt sich der Servo kurz gegen den 
Uhrzeigersinn :-(

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.