Pages: [1]   Go Down
Author Topic: Servo Scheibenwischerbetrieb, Zeit aendern  (Read 601 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ich betreiebe einen Servo mit dem Arduino Board. Der Server macht die Wischebewegung, wie Sie im Beispielprogramm vorgegeben ist.
Ueber die Delayzeit aendere ich die "Wischgeschwindigkeit" / Servogeschwindigkeit.
Anbei das Beispielprogramm von Arduino.

Code:
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created
 
int pos = 0;    // variable to store the servo position
 
void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}
 
 
void loop()
{
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees                   Sobald man in dieser For-Schleife sich befindet, wird eine Aenderung der Delayzeit nicht mehr ausgefuehrt.
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

Allerdings dauert es genau 1 Zyklus, bis sich die Aenderung auswirkt. D.h. faehrt der Servo gerade nach unten und ich aendere die Delayzeit, so muss der Servo ganz nach fahren, damit sich die Delayzeit in der For-Schleife aendert. Somit brauche ich 1/2 Wischbewegung bis sich die Geschwindigkeit aendert.
Frage: Kann ich dies so aendern, dass der Servo sofort seine Geschwindigkeit aendert? zBsp ueber einen Interrupt? Was fuer Vorschlaege habt ihr?

MfG

Robert

« Last Edit: January 10, 2012, 05:04:21 pm by Arudnoh » Logged

Weinsberg, Germany
Offline Offline
God Member
*****
Karma: 3
Posts: 773
A Coder's Tale
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Was Du beschreibst und der Code hier passen aber nicht wirklich zusammen, bitte zeig uns mal Deinen aktuellen Code. smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

Code:
#include <Servo.h>
 
Servo myservo;  // create servo object to control a servo
                // a maximum of eight servo objects can be created
 
int pos = 0;    // variable to store the servo position
int m = .... ; //geradesteigung
int b = .... ;  //y-achsenabstand
int transmitterThrottle;

void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  pinMode (9, INPUT);    //Input of Throttle
}

void checkTransmitter() //function for reading a signal of a RC-Receiver
{
transmitterThrottlee = ((pulseIn (9, HIGH, 100000))/10)-transmitterThrottleeLow; //read RC channel, wait max of 0.1 seconds for pulse
}
 
 
void loop()
{
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees                   Sobald man in dieser For-Schleife sich befindet, wird eine Aenderung der Delayzeit nicht mehr ausgefuehrt.
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(transmitterThrottle*m+b);                       // Formel zum ausrechnen der Delayzeit, ändert sich transmitterThrottle während der Schleife, so wird die ganze Schleife mit dem ursprünglichen Wert ausgeführt. Gibt es hier eine Interruptmöglichkeit??
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(transmitterThrottle*m+b);                       // Formel zum ausrechnen der Delayzeit, ändert sich transmitterThrottle während der Schleife, so wird die ganze Schleife mit dem ursprünglichen Wert ausgeführt. Gibt es hier eine Interruptmöglichkeit??
  }
}
« Last Edit: January 10, 2012, 08:10:12 pm by Arudnoh » Logged

Cologne
Offline Offline
God Member
*****
Karma: 11
Posts: 505
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

das Programm erzeugt Fehler beim Compilieren, hätte dir eigentlich schon sagen müssen, wo der Fehler liegt.
1. Die Variable transmitterThrottlee ist nirgendwo definiert worden.
2. Die Variable müsste global definiert werden, damit sie auch im Hauptprogramm gelesen werden kann
3. Du müsstest das Sub void checkTransmitter() aufrufen, damit sich die Variable überhaupt ändert

Besser: definiere die Formel für transmitterThrottlee als Function und übergebe im Aufruf in der Schleife diesen Wert.

Gruß
Reinhard
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

natürlich wird die Variable transmitterThrottle global deklariert. Habe das nur kurz zu Verdeutlichung aufgeschrieben. Ich möchte diesen Programmteil so verwenden, habe das Programm dafür aber noch nicht geschrieben, da ich noch nicht wusste, wie ich mein Problem löse. Habe den Fehler trotzdem oben korrigiert.

Ich verstehe nicht, was mit Sub void checkTransmitter() gemeint ist. Für was steht das Sub? Leider konnte mir Google da auch nicht weiterhelfen.

Wie kann ich wenn sich die Variable transmitterThrottle ändert, die for schleife abbrechen und mit dem neuen wert wieder starten? Ich möchte nicht, dass die For schleife komplett durchlauft und dann die nächste losgeht, sondern die delayzeit soll sich automatisch ändern.
Wie kann man soetwas realisieren?? Ist es möglich, einen Interrupt auszulösen, wenn sich die Variable transmitterThrottle ändert?

MfG
« Last Edit: January 10, 2012, 08:12:06 pm by Arudnoh » Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Würde es nicht reichen, in jedem Schleifendurchlauf checkTransmitter() aufzurufen? Das war auch das was Reinhard wohl meinte mit
Quote
Du müsstest das Sub void checkTransmitter() aufrufen

Wobei Sub hier für Unterprogramm / Funktion / Subroutine steht.
Du brauchst auf jeden Fall zusätzlichen Code in der Schleife, der auf die "externe" Änderung reagiert.
Mario.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So, das Problem hab ich ein bisschen ruhen lassen, weil es nicht so wichtig war, aber nun wollt ich mich darum kuemmern.
Das Programm besteht aus 3 Teilen.
1. Die "Main" funktion mit der Deklaration der Variablen, Hauptschleife usw.
2. Dem Tab/ Der Funktion Checktransmitter, die den Wert vom RC Empfaenger einliest
3. Der Funktion Sweep

Hier ist der Original Code, der funktioniert. Aendere ich allerdings waehrend des Wischzyklus den Wert vom RC Empfaenger, so dauert es einen Wischzyklus bis der neue Wert umgesetzt wird.

Main Programm
Code:
//Imports servo library
#include <Servo.h>
//Initializes servos
Servo servo;
unsigned long transmitterThrottlee=0;     //these store the current transmitter positions/values
unsigned long transmitterThrottleeLow=0;  //these store the current transmitter positions/values

//Constants for actual frequency, minimum target angle, and maximum target angle
const int minAngle=45;
const int maxAngle=135;

void setup()
{
  servo.attach(11);
  pinMode (9, INPUT);    //Input of Throttle
  transmitterThrottleeLow = ((pulseIn (9, HIGH, 100000))/10);
}

void loop()
{
  checkTransmitter();              //check the data being received by the transmitter.
  sweepfunction();
}
CheckTransmitterFunction
Code:
void checkTransmitter()
{
  transmitterThrottlee = ((pulseIn (9, HIGH, 100000))/10)-transmitterThrottleeLow; //read RC channel, wait max of 0.1 seconds for pulse

  if (transmitterThrottlee > 42000)
    transmitterThrottlee =0;
}
Sweepfunction
Code:
void sweepfunction()
{
  if(transmitterThrottlee>=5&&transmitterThrottlee<95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {
      servo.write(pos);
      delay((transmitterThrottlee*-.1143)+13.4286);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {                                
      servo.write(pos);
      delay((transmitterThrottlee*-.1143)+13.4286);
    }
  }
  else if(transmitterThrottlee>=95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {
      servo.write(pos);
      delay(2);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {                                
      servo.write(pos);
      delay(2);
    }
  }
  else
  {
    servo.write(90);
  }
}

So nun habe ich dies Modifiziert in der Hoffnung, dass die Aenderung des RC Signales sofort in eine Geschwindigkeitsaenderung des Wischens umgesetzt wird.
Leider funktioniert anscheinend der Funktionsaufruf nicht.
Erneut MainFunction (alles identisch mit oben, bis auf dass die Function checkTransmitter nicht mehr aufgerufen wird. Dies passiert in der Funktion sweepfunction.Daher nur die main loop, den Rest spare ich ma aus.)
Code:
void loop()
{
  sweepfunction();
}
Checktransmitterfunction
Code:
identisch, siehe oben
Sweepfunction
Code:
void sweepfunction()
{
  int i=0;
  checkTransmitter();
  if(transmitterThrottlee>=5&&transmitterThrottlee<95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {
      if (i=5)                          // habe dies aus dem folgenden Grund gemacht, dass alle 5 Grad Wischaenderung eine "Ueberpruefung"
      {                                  //erfolgt, ob das RC Signal noch das Selbe ist, und Falls nicht sollte mit dem neuen weitergearbeitet
        checkTransmitter();     //werden. Aber wo ist der Fehler? Wieso wird der neue Wert nicht in die Haupt For Schleife uebernommen
        i=0;
      }
      i++;
      servo.write(pos);
      delay((transmitterThrottlee*-.1143)+13.4286);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {    
      if (i=5)
      {
        checkTransmitter();
        i=0;
      }  
      i++;    
      servo.write(pos);
      delay((transmitterThrottlee*-.1143)+13.4286);
    }
  }

  else if(transmitterThrottlee>=95)
  {
    for(int pos = minAngle; pos < maxAngle; pos+=1)  // goes from 0 degrees to 180 degrees
    {        
      if (i=5)
      {
        checkTransmitter();  
        i=0;
      }  
      i++;
      servo.write(pos);        
      delay(2);
    }
    for(int pos = maxAngle; pos > minAngle; pos-=1)     // goes from 180 degrees to 0 degrees
    {          
      if (i=5)
      {
        checkTransmitter();  
        i=0;
      }    
      i++;                      
      servo.write(pos);
      delay(2);
    }
  }
  else
  {
    servo.write(90);
  }
}
Hoffe, mein anliegen wird nun klarer und verstaendlicher.

MfG
« Last Edit: February 14, 2012, 11:32:02 am by Arudnoh » Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Du ahst nur das CheckTransmitter in die sweep-Funktion befördert. Allerdings ohne einen wirklichen Effekt, denn ob Du nun bei jedem Aufruf von loop() einmal checktransmitter aufrufs oder jedesmal innerhalb von sweepfunction(), aber immer noch nur einmal während des Durchlaufs von loop() macht keinen Unterschied.
Du musst wenn schon innerhalb der for-Schleife im sweepfunction() die CheckTransmitter() aufrufen.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
ja ich habe die CheckTransmitter in die Sweep Funktion befoerdet, damit beim allerersten Aufruft der SweepFunktion die Checktransmitter Funktion aufgerufen wird und ein definierter Wert eingelesen wird.
Allerdings wird in der for schleife die Checktransmitter function ebenfalls aufgerufen. Alle 5 Grad sollte der Wert ueberprueft werden. Leider kann ich die Stelle nicht farblich im Code markieren, dann wuerde man die stelle leichter sehen.

MfG
« Last Edit: February 14, 2012, 11:33:08 am by Arudnoh » Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, sorry. Das hatte ich tatsächlich übersehen. Versuch mal in der CheckTransmitter (oder dem Aufruf im if-Block in sweepfunction()) per Seria.-println() diverse Werte zu debuggen auszugeben. Damit siehst Du zum einen ob die Funktion an der richtigen Stelle aufgerufen wird und welche Werte danach gesetzt sind.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mh, das hat nicht wirklich was gebracht. Die Funktion wird zwar aufgerufen, aber der neue Wert wird nicht in die alte bereits laufende For Schleife übergeben.
Jemand Ideen?

Robert
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Jetzt sehe ich den Fehler ....
Code:
      if (i=5)                          // habe dies aus dem folgenden Grund gemacht, dass alle 5 Grad Wischaenderung eine "Ueberpruefung"
      {                                  //erfolgt, ob das RC Signal noch das Selbe ist, und Falls nicht sollte mit dem neuen weitergearbeitet
        checkTransmitter();     //werden. Aber wo ist der Fehler? Wieso wird der neue Wert nicht in die Haupt For Schleife uebernommen
        i=0;
      }
      i++;

Mit i=5 setzt Du den Wert für "i" auf 5 aber vergleichst ihn nicht. Es muss "if (i == 5)" heissen.
Außerdem würde ich das erste checkTransmitter() in sweepfunction() mal auskommentieren, um zu sehen das die Funktionen innerhalb der Schleifen aufgerufen werden.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

thx, jetzt funktioniert es. Ich mache oft so kleine dumme Fehler die ich dann nie finde und dann funktioniert es nicht. Ich hasse soetwas, danke dass du dir die Muehe gemacht hast meinen code genau anzuschauen. smiley
Den ersten Checktransmitterfunctionaufruf kann ich nicht weglassen, da dieser eine Bedingung zurueckgibt, die zum Aufrufen der For-Schleife benoetigt wird. Aber in der For Schleife wird die Funktion nun aufgerufen und die Geschwindigkeit des Servos aendert sich sofort. Was mir allerdings aufgefallen ist, dass man die Zeit, die die Funktion Checktransmitter benoetigt (20ms) merkt. Nimmt man als Grenze den Wert 2 oder 3, so merkt man, dass man die maximalgeschwindigkeit des Servos niedriger ist, als bei dem Wert 10. Grund, die Funktion checktransmitter benoetigt 20ms und wenn man diese zu oft aufruft kann man den Servo nicht oft genug ansteuern und die Geschwindigkeit verringert sich.
Habe den gleichen Post nochmals im Englischsprachigen Forum stehen, wo mir ein anderer Ansatz geraten wurde, den ich nun auch verfolge. Ma schauen was da dabei rauskommt.

Gruesse
Robert
Logged

Pages: [1]   Go Up
Jump to: