Forum: Mikrocontroller und Digitale Elektronik Servo will nicht richtig, Programm oder Hardwarefehler?


von R. B. (britzi)


Lesenswert?

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
}

von Wolfgang (Gast)


Lesenswert?

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?

von Peter S. (petershaw)


Lesenswert?

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

von R. B. (britzi)


Lesenswert?

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.

von R. B. (britzi)


Lesenswert?

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 :-)

von Spess53 (Gast)


Lesenswert?

Hi

>PORTB|= (1<<PD0) | (1<<PD1) | (1<<PD2);  // PullUp für Taster an PD0,1,2

Soll das so sein?

MfG Spess

von R. B. (britzi)


Lesenswert?

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 :-(

von Georg G. (df2au)


Lesenswert?

Erklär uns doch, warum du PortB mit Bitwerten für PortD initialisierst 
um dann PortD zu nutzen.

von R. B. (britzi)


Lesenswert?

Georg G. schrieb:
> Erklär uns doch, warum du PortB mit Bitwerten für PortD initialisierst
> um dann PortD zu nutzen.

Danke für den Hinweis.
Den Fehler habe ich ständig überlesen! ;-)

Funktionierten tut es nach der Fehlerkorrektur leider noch immer nicht 
:-(

von Spess53 (Gast)


Lesenswert?

Hi

>Funktionierten tut es nach der Fehlerkorrektur leider noch immer nicht

Aber hoffentlich PortB in PortD geändert.

MfG Spess

von R. B. (britzi)


Lesenswert?

Spess53 schrieb:
> Hi
>
>>Funktionierten tut es nach der Fehlerkorrektur leider noch immer nicht
>
> Aber hoffentlich PortB in PortD geändert.
>
> MfG Spess


Jepp und ich habe nun auch den Fehler gefunden.
Aber den verrate ich lieber nicht ^^
Es lag am Compiler ;)

Danke :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.