Forum: Mikrocontroller und Digitale Elektronik Problem mit der Servoansteuerung


von Toni (Gast)


Lesenswert?

Hallo,

ich habe bereits gestern etwas gepostet, aber dieses Problem konnte ich 
beheben. Ich programmiere, bzw. ich bastel mir gerade ein Programm für 
einen Schülerwettbewerb zusammen.
Meine Gruppe und ich haben uns vorgenommen eine Abblendmaschine zu 
programmieren. Leider happert es bei unseren Kenntnissen.
Der Schülerwettbewerb wird von einer Firma gesponsort, den Namen werde 
ich hier nicht erwähnen.
Diese Firma hat uns bereits einige Befehle im vorraus mitgegeben, damit 
uns das Programmieren nicht so schwer fällt. Die Vertreter meinten, dass 
sie nicht voraussetzen können, dass wir die Hochsprache C können.
Uns wurde gesagt, wir müssen nicht wissen, wie man diese Befehle 
programmiert, aber wir sollten bei der Präsentation erklären können, 
welche Funktion der Befehl hat und schildern können, wie der Befehl 
funktioniert. (Z.B. Waitus -> Zähler, der im 1MHz Takt von 1 bis 1000 
zählt)

Zum Ablauf unseres Programmes: Wir verwenden zwei Lichtsensoren und 
vergleichen diese per Analogwert. Ist z.B. Analogwert 1 größer als 
Analogwert 2, dann sollen die Super-Hellen-LEDs abgeschalten und die 
normale LEDs angeschalten werden. Wir haben uns noch überlegt, diese 
LEDs abzurichten, d.h. wir haben zusaätzlich 2 Servomotoren verwendet. 
Ein Servomotor lenkt die LEDs Richtung Boden ab, der andere zur Seite.

Unser Problem ist, dass wir die Servomotoren nicht ansteuern können. Wir 
haben bisher im Datenblatt kein Pin gefunden, der PWM-Signale ausgeben 
kann. Wir haben schließlich jemanden gefragt, ob man das auch anders 
regeln könnte.
Dieser meinte, sofern wir ihn nicht falsch verstanden haben, wenn man 
ein Port als Ausgang definiert und ihm "1" und "0" Impulse sendet, 
könnte der Servomotor selbst das Tastverhältnis berechnen und die 
Frequenz selbstbestimmen.

Ich habe unser Programm mitgeschickt, damit vielleicht jemand kurz 
drüber schaut und uns ein Tipp gibt, wie man es umschreiben könne, damit 
die Servos doch noch funktionieren.
Ich erwarte, dass niemand uns die Lösung "in den Arsch schiebt", sondern 
einfach nur, dass man ein paar Tipps bekommt wie es funktionieren 
könnte.

Unser Microcontroller hat negative Ein- und Ausgänge.

#include "sfr_r813.h"

void waitus(unsigned int us)

  {
  unsigned int i;
  //us/=2;
  for (i=us;i>0;i--) {
      asm("nop");
    }

  }

void waitms(unsigned int ms)

  {
  unsigned int i;
  //ms *= 10;
  for (i=ms;i>0;i--) {
      waitus(996);    /*996 statt 1000ms um Fehler auszugleichen*/
    }

  }
void init(void)
  {
  prc0 = 1;             /* Protect off */
  cm13 = 1;             /* Xin Xout */
  cm15 = 1;             /* XCIN-XCOUT drive capacity select bit : HIGH 
*/
  cm05 = 0;             /* Xin on */
  cm16 = 0;             /* Main clock = No division mode */
  cm17 = 0;
  cm06 = 0;             /* CM16 and CM17 enable */
  asm("nop");           /* Waiting for stable of oscillation */
  asm("nop");
  asm("nop");
  asm("nop");
  ocd2 = 0;             /* Main clock change */
  prc0 = 0;             /* Protect on */
  }

int analogwert(int chn)
  {
  int adcresult;
  if (chn>=8||chn<0) return 0;
  chn = 7-chn;
  adcon0 = chn;       //channel
  adcon1 = ((1<<3)|(1<<5));  //10-bit Mode
  adst = 1;      //ADC conversion start
  while (adst==1);    //Ende der conversion abwarten
  //adcresult = (ad);

  return ad;
  }

void main(void)
{
init ();

    pd1 = 0x0F;
  pd0 = 0x00 ;



    while (1)
    {
    if ( analogwert(6) >= analogwert(7) )

// Lichtsensoren vergleich (Aussführung,wenn Umgebungssensor größer 
// ist als  Gegenlichtsensor. Es können Werte von 0 - 1023 ausgeben 
werden.)
//analogwert (6) ist der Gegenlichtsensor und analogwert (7) ist der 
Umgebungssensor.
{

    // Abblendlicht
    p1_0 = 0;
    p1_1 = 0;
    // Aufblendlicht
    p1_2 = 1;
    p1_3 = 1;

      // Servo 1 (auf den Boden abrichten)

      /*while (  analogwert(6) <= analogwert(7)  )
      {
      p0_1 = 0;
      waitus(1500);
      p0_1 = 1;
      waitus(18500);
      }
      //Servo 2 (zur Seite abrichten)
      /*  p0_2 = 0;
        waitms(18);
        p0_2 = 1;
        waitms(2);   */
    }
    else
    {

    // Abblendlicht
    p1_0 = 1;
    p1_1 = 1;
    // Aufblendlicht
    p1_2 = 0;
    p1_3 = 0;


      /*while(  analogwert(6) <= analogwert(7)  )
                       // Servo 1 (auf die Straße aufrichten)
      {
      p0_1 = 0;
      waitus(18500);
      p0_1 = 1;
      waitus(1500);
      }
      // Servo 2 (auf die Seite richten)
      /*  p0_2 = 0;
        waitus(18500);
        p0_2 = 1;
        waitus(1500);  */
    }
}
}


Die While-Schleifen habe ich in /*...*/ gesetzt, damit ersichtlich ist, 
wo die Fehler vermutlich liegen könnten.

Wenn uns jemand weiterhelfen könnte, wäre wir sehr erfreut.

MfG Toni

von Martin (Gast)


Lesenswert?

Guckt euch mal im Servo Tutorial das Servo Impulsdiagramm an
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Servo

Dann baut euch ein kurzes Programm, was in einer Schleife dauernd solche 
Impulse mit einer festen Länge auf einem Pin ausgibt. Am besten läßt 
sich das mit einem Oszilloskop kontrollieren. Wenn das funktioniert, 
könnt ihr das für euer beiden Servos in das Gesamtprogramm einbauen.

Um das zu Prinzip zu verstehen, ist euer Weg mit den wait-Befehlen ok. 
Später, wenn der Mikrocontroller auch noch andere Sachen machen soll, 
passiert die Servosteuerung über Timer und Interrupt.

von Floh (Gast)


Lesenswert?

Toni schrieb:
> //Servo 2 (zur Seite abrichten)
>       /*  p0_2 = 0;
>         waitms(18);
>         p0_2 = 1;
>         waitms(2);   */

Damit kriegt ihr ein Timingproblem, sobald im Programm mehr als nur die 
Ansteuerung des Servos steht, da dann das Timing durch andere Aktionen 
gestört wird.
Also braucht ihr eine verlässliche Zeitbasis, einen Timer.

Noch lesenswert dafür, ist aber leider für AVR und nicht 8051 (?).
http://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung
:-)

von Toni (Gast)


Lesenswert?

Okay. Vielen Dank erstmal. :)
Ich werde mir das alles anschauen und versuchen einen Lösungsweg 
zufinden. Das Timingproblem ist uns schon aufgefallen, da es zu falschen 
Ausgangssignalen kommt, sobald erneut die If-Bedingung erfüllt wird.
Aber trotzdem Danke für die schnelle Resonanz. ;)

MfG Domi

von Martin (Gast)


Lesenswert?

Zwei Servos lassen sich mit wait-Befehlen, auch wenn es nicht schön ist, 
noch halbwegs in den Griff kriegen, indem man die im Zeitmultiplex 
steuert, also

While (1) //Schleife
- Pin für Servo1 einschalten
- Warten für Pulsdauer von Servo1
- Pin für Servo1 ausschalten

- Pin für Servo2 einschalten
- Warten für Pulsdauer von Servo2
- Pin für Servo2 ausschalten

- Warten für Mindestpausendauer (ausprobieren, Tip > 4 ms)

- andere Dinge machen
// Ende Schleife

Die Servos interessiert nur die Impulsdauer, die Pausendauer ist denen 
in weiten Grenzen egal (100 ms ist z.B. gar kein Problem).

von Toni (Gast)


Lesenswert?

Wir haben bereits alles ausprobiert, um nur einen Servo zum Laufen zu 
bringen. Aber der Servo ruckelt die ganze Zeit nur rum, schlägt aus und 
fährt zur Ausgangsposition zurück, ohne die gewünschte Position zu 
halten.

Liegt es eventuell am Servo oder an unserer Unwissenheit?

[[http://www.conrad.de/ce/de/product/233751/TOP-LINE-STANDARD-SERVO-RS-2-JR]]

von Martin (Gast)


Lesenswert?

Der Servo läuft mit den 1..2 ms Pulsen.
Habt ihr die Impulse auf einem Oszi angesehen?

Die Zeitschleife in der funktion waitus() liefert nur für eine bestimmte 
Prozessortaktfrequenz die richtigen Zeiten.
Zur groben Überprüfung kann man z.B. eine LED mit 1000 ms Wartezeiten 
blinken lassen und per Uhr die Periodendauer messen.

von Toni (Gast)


Lesenswert?

Vielen Dank für die vielen Ratschläge.

Wir haben leider kein Oszilloskop griffbereit und können die Impulse 
nicht überprüfen. :-(

Aber wir versuchen die Periodendauer per Uhr und LED zu überprüfen.
Danke für die Hinweise.

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.