Motoransteuerung - Steh grad etwas auf dem Schlauch... (Problem gelöst)

Hallo miteinander,

ich habe eben einen Versuchsaufbau stehen, der einem alten RC-Car einen Arduino als "Gehirn" verpassen soll. Installiert ist eine H-Brücke L293 E mit einem Schottky Array (L6210) - momentan der L293 mit nur 2kanälen(ein Motor). Der ist entsprechend Anordnung mittels Poti in der Sollgeschwindigkeit regelbar.

Ab //Ausgabe PWM beginnt der Motor in die eine Richtung zu drehen (vorher wird die Sollgeschwindigkeit gesetzt). Soweit so klar.

Wobei ich jetzt total hänge ist die Frage wie definiere ich die Sollgeschwindigkeit "global" aber variabel und lasse es trotz dem zu, dass die beiden Drehrichtungen funktionieren. Denn das Delay (100) bezieht sich ja auf die Abfrage der möglichen PWM-"Pegel) und hat in der Regel mit der Einschaltzeit der Motoren bzw Drehrichtungen nichts zu tun.
Wäre das was für switch case für eine Verzweigung in die Drehrichtung bei gleichbleibender Geschwindigkeit - oder rufe ich vor jeder neuen Drehrichtung einfach die Sollgeschwindigkeit aufs Neue ab - da funktioniert das aber mit dem Delay für die PWM nicht mehr (oder liege ich da falsch??).

int PWMPin = 9;  //PWM-Signal Motor
int MotorPin1 = 6;  //Vor/Rück Motor
int MotorPin2 = 7;  //Vor/Rück Motor

int SollSpeedPin = 0;   //Sollwert für Geschwindigkeit
int SollSpeed = 0;      // Eingelesene Sollgeschwindigkeit


void setup()
{
  pinMode(MotorPin1,OUTPUT);
  pinMode(MotorPin2,OUTPUT);
}


void loop()
{
  //Sollwert einlesen
  SollSpeed = analogRead(SollSpeedPin) / 4;
  
 // Ausgabe PWM
 analogWrite(PWMPin,SollSpeed);
 //Motor vorwärts
 digitalWrite(MotorPin1,HIGH);
 digitalWrite(MotorPin2,LOW);
 delay(100);
 

}

Ich steh total auf dem Schlauch - es würde mich sehr freuen, könnte mir jemand den Knoten lösen... :wink:

Thomas

digitalWrite(MotorPin1,HIGH);
digitalWrite(MotorPin2,LOW);
vorwärtz

digitalWrite(MotorPin1,LOW);
digitalWrite(MotorPin2,HIGH);
rückwärts

Grüße Uwe

uwefed:
digitalWrite(MotorPin1,HIGH);
digitalWrite(MotorPin2,LOW);
vorwärtz

digitalWrite(MotorPin1,LOW);
digitalWrite(MotorPin2,HIGH);
rückwärts

Grüße Uwe

Das war mir soweit klar und hat auch funktioniert, aber die Geschwindigkeit der jeweiligen Richtung zuzuordnen, dort hat es gehapert.

Diese zwar variabel aber dennoch "global" festzulegen, unabhängig in welche Richtung der motor dreht....

Dann habe ich Dich falsch verstanden und verstehe Dich immer noch nicht.
Kannst Du ein Beispiel machen?
Grüße Uwe

if(SollsSpeed>=512){
analogWrite(MotorPin1,SollSpeed-512);
digitalWrite(MotorPin2,LOW);
}
else {
digitalWrite(MotorPin1,LOW);
digitalWrite(MotorPin2,512-SollSpeed);
}

zumindest wenn ich dich richtig verstanden habe... dann fährt er forwärts sobald der der analogwert größergleich 512 ist und rückwärts wenn er kleiner ist, ist der poti auf mittlerer position steht er

uwefed:
Dann habe ich Dich falsch verstanden und verstehe Dich immer noch nicht.
Kannst Du ein Beispiel machen?
Grüße Uwe

Hab mich sicher auch bissl blöd ausgedrückt...

Hier eine Variante ohne PWM, also mit Maximaldrehzahl:

//Skript mit Maximalgeschwindigkeit(ohne PWM)

int FreigabePin = 9; //Freigabe Motor
int MotorPin1 = 6; //vor/rück Motor
int MotorPin2 = 7; //vor/rück Motor

void setup()
{
pinMode(FreigabePin,OUTPUT);
pinMode(MotorPin1,OUTPUT);
pinMode(MotorPin2,OUTPUT);
}

void loop()
{
//Motor vorwärts für 2 Sek
digitalWrite(FreigabePin,HIGH);
digitalWrite(MotorPin1,HIGH);
digitalWrite(MotorPin2,LOW);
delay(2000);

//Motor rückwärts für 2 Sek
digitalWrite(MotorPin1,LOW);
digitalWrite(MotorPin2,HIGH);
delay(2000);

//Motor stoppen für 1 Sek
digitalWrite(FreigabePin,LOW);
delay(1000);
}

Die delays beschreiben hier die Einschaltzeiten. Demgegenüber ist das Delay (100) des ersten Codes meiner Meinung nach eher so etwas wie eine Abtastrate für die Aktualisierung der Geschwindigkeit (PWM).
Ich habe mich schon umgesehen und festgestellt, das die Beispiele der Motor- Shields für mich so nicht verwendbar scheinen, Adafruit nutzt ein Shiftregister um zusätzliche Werte zu setzen -ich dachte, das geht auch einfacher aber stell mich grad zu blöd an....

Wie kann ich jetzt das PWM-Signal zu den Vorwärts- und Rückwerts-"Blöcken" zuordnen? Füge ich das a la

void loop()
{
  //Sollwert einlesen
  SollSpeed = analogRead(SollSpeedPin) / 4;
  
 // Ausgabe PWM
 analogWrite(PWMPin,SollSpeed);
 //Motor vorwärts
 digitalWrite(MotorPin1,HIGH);
 digitalWrite(MotorPin2,LOW);
 delay(1000);
 
  // Ausgabe PWM
 analogWrite(PWMPin,SollSpeed);
 //Motor rückwärts
 digitalWrite(MotorPin1,LOW);
 digitalWrite(MotorPin2,HIGH);
 delay(1000);

jedes mal vorab an?
Grundsätzlich funktioniert das, jedoch ist mir nun die Regelbarkeit beinahe ganz verloren gegangen. Der untere Potibereich, in dem der Motor nur fiept ist wesentlich größer geworden und darüber ist die Regelbarkeit minimal???

Grüße Thomas

Da hab ich ja was angerichtet.... :wink: lauter kreative Ideen - Danke dafür! Aber so meinte ich das nicht.

Was ich erreichen wollte ist, dass die Solldrehzahl von außen oder von anderer Stelle im Skript definiert sowohl bei Vorwärts- als auch bei rückwärtsfahrt sauber umgesetzt wird.

Beim Probieren hatte ich aber den Eindruck, dass ich einen denkfehler in der art der Definition habe. Siehe meine Antwort an Uwe....

!!! Ich verstehe jetzt die leichte Konfusion, die bezüglich der Potiabfrage entstanden ist.... An dieser stelle stand ein missverständliches Quote, dass hat Euch völlig auf die falsche Fährte gefürt - und ich hab es nicht gemerkt, weil ich meinen Post nicht noch mal korrektur gelesen habe....

Sorry

ich hoffe das ich dein problem verstanden habe :smiley:

SollSpeed = analogRead(SollSpeedPin) / 4;

der poti gibt im prinzip einen wert von 0 bis 255 aus. du willst aber die mittel stellung vom poti als pwm wert 0 haben und nach rechts und links wieder 255 pwm schritte haben.

dann musst du mit der funktion map hantieren. erst die eigentliche stellung vom poti per größer bzw gleich abfrage ermitteln und dann die werte neu mit map festlegen.

ich hoffe das war einigermaßen verständlich

das ist ja quasi das, was ich schonmal geschrieben hatte, ich habs nur manuel und nicht per map gemacht... und vergessen es durch 2 zu teilen in dem fall, scheint ja nicht das gewesen zu sein was er möchte... ich verstehs allerdings nicht so genau ^^ und noch dazu: ein negativer PWM-Wert bringt nichts, da musst du dann auch ne fallunterscheidung machen und beträge nehmen

Ungefähr so:

  JoystickValue = analogRead(Joystick1XPin);
  if ((JoystickValue > 507) and (JoystickValue < 513))
  {
     Hoch1 = 0;
     Runter1 = 0;
  }
    else if (JoystickValue < 508) 
    {
       Runter1 = map(JoystickValue, 507, 0, 150, 1);  
    }
      else
      {
         Hoch1 = map(JoystickValue, 513, 1023, 150, 1);
      }

  JoystickValue = analogRead(Joystick1YPin);
  if ((JoystickValue > 496) and (JoystickValue < 502))
  {
     Links1 = 0;
     Rechts1 = 0;
  }
    else if (JoystickValue < 497) 
    {
       Links1 = map(JoystickValue, 496, 0, 150, 1);  
    }
      else
      {
         Rechts1 = map(JoystickValue, 502, 1023, 150, 1);
      }

  JoystickValue = analogRead(Joystick2XPin);
  if ((JoystickValue > 513) and (JoystickValue < 519))
  {
     Hoch2 = 0;
     Runter2 = 0;
  }
    else if (JoystickValue < 514) 
    {
       Hoch2 = map(JoystickValue, 513, 0, 150, 1);  
    }
      else
      {
         Runter2 = map(JoystickValue, 519, 1023, 150, 1);
      }

  JoystickValue = analogRead(Joystick2YPin);
  if ((JoystickValue > 518) and (JoystickValue < 524))
  {
     Links2 = 0;
     Rechts2 = 0;
  }
    else if (JoystickValue < 519) 
    {
       Rechts2 = map(JoystickValue, 518, 0, 150, 1);  
    }
      else
      {
         Links2 = map(JoystickValue, 524, 1023, 150, 1);
      }

Ich habe Joystick ein auf 5V, Joystick Out auf GND und der Schleifer wird abgefragt.
Der Ergebniswert 0 - 1023 wird dann wie benötigt umgemappt !

Zm Verständnis:
Du hast 3 Pin:
int FreigabePin = 9; //Freigabe Motor
int MotorPin1 = 6; //vor/rück Motor
int MotorPin2 = 7; //vor/rück Motor

Motor in eine Richtung:
FreigabePin = H
MotorPin1 = H
MotorPin2 = L
Motor in andere Richtung
FreigabePin = H
MotorPin1 = L
MotorPin2 = H
Motor gebremst (kurzgeschlossen):
FreigabePin = H
MotorPin1 = L
MotorPin2 = L
oder
FreigabePin = H
MotorPin1 = H
MotorPin2 = H

Motor nicht Spannungsversorgt und im Freilauf:
FreigabePin = L
MotorPin1 = x
MotorPin2 = x

wobei x H oder L sein kann.

Grüß Uwe

@all erst ein mal danke für die Mühe

@derder...Genau Du hast es auf den Punkt gebracht :wink:

@Uwe, danke für die akribische Auflistung. Bis auf die beiden Zustände Schnellstopp und "Freilauf" war mir das völlig klar. Letztere beiden hab ich mir nicht so richtig getraut (hatte das was von Kurzschluss im Hinterkopf aus Transistor-H-Brücken-Zeiten...) aber das war alles nicht mein Kern-Problem.

Ich versuch es noch mal:

Wenn ich im Progammablauf die beiden Motoren ansteuere (vor, zurück, gegensinnig(also lenkend)) und die Laufzeiten mittels Delay bestimme bekomme ich doch irgendwann ein Problem, wenn ich unabhängig vom zeitichen Ablauf des "Fahrprogrammes" die Abfrage der Sollgeschwindigkeit (hier mein Poti) abwickeln möchte. Das ist doch dann in jedem Falle eine Verzweigung oder besser gesagt ein Einschub in die andere Routine. Sonst müsste ich doch mit der Änderung der Geschwindigkeit warten, bis ich meinen Kurs abgefahren habe?

Ich hoffe, das ich mein Anliegen jetzt besser beschrieben habe...

Thomas

Ich glaub langsam hab ichs (hoffentlich). Dein Problem ist, das du z.B. während eines delays, und somit während z.B. eines Wendemanövers die Geschwindigkeit nicht neu einlesen kannst? Regele den Motor doch einfach nicht über delays sondern schreib den per Analog input übermittelten wert direkt per PWM (analogWrite) auf den richtigen pin (und schalte die richtungs-pins richtig), da brauchst du kein delay, der gesamte loop läuft in wenigen microsekunden durch und danach wird gleich wieder der poti-stand abgefragt

derder:
Ich glaub langsam hab ichs (hoffentlich). Dein Problem ist, das du z.B. während eines delays, und somit während z.B. eines Wendemanövers die Geschwindigkeit nicht neu einlesen kannst? Regele den Motor doch einfach nicht über delays sondern schreib den per Analog input übermittelten wert direkt per PWM (analogWrite) auf den richtigen pin (und schalte die richtungs-pins richtig), da brauchst du kein delay, der gesamte loop läuft in wenigen microsekunden durch und danach wird gleich wieder der poti-stand abgefragt

100 Points für derder ;):wink: - Danke!
Aber jetzt hab ich eine Verständnisfrage: Wenn ich Dich richtig verstehe meinst Du, dass das PWM- Signal auf den vorwärts/rückwärts-Pin des Motors geschrieben wird. Ich habe das auf den Enable-Pin des Controlers geschrieben und das ist offenbar so nicht richtig.

Zu oben noch mal... Die Delays waren gewissermaßen Waypoints - also fahre bis dort, steuere nach rechts, fahre soundsoweit......

Thomas

nene, enable-pin stimmt schon, nur eben das der wert für geschwindigkeit 0 (also stillstand) eben sowas wie 512 ist und du dann quasi alles ab 511 und drunter auf "rückwärts" mappen musst und alles über 513 auf vorwärts und dementsprechend zum einen die steuerpins setzen musst und zum anderen die PWM-zahl ausrechnen musst, für vorwärts ist es (WERT-512)/2 und rückwärts (512-WERT)/2.

wenn du jetzt während deiner "wegpunkte" die geschwindigkeit ändern willst musst du entweder ohne delays arbeiten (mit if-abfragen und millis() oder so, siehe "Blink without delay" Tutorial) oder während dieser wegpunkte mit while-schleifen und millis() arbeiten und innerhalb der schleife immer wieder die geschwindigkeit abfragen

derder:
wenn du jetzt während deiner "wegpunkte" die geschwindigkeit ändern willst musst du entweder ohne delays arbeiten (mit if-abfragen und millis() oder so, siehe "Blink without delay" Tutorial) oder während dieser wegpunkte mit while-schleifen und millis() arbeiten und innerhalb der schleife immer wieder die geschwindigkeit abfragen

Danke, das werd ich heute mal alles ausprobieren. Das scheint die richtige Fährte zu sein.

Grüße, Thomas

woodmaster:
...
Ich versuch es noch mal:

Wenn ich im Progammablauf die beiden Motoren ansteuere (vor, zurück, gegensinnig(also lenkend)) und die Laufzeiten mittels Delay bestimme bekomme ich doch irgendwann ein Problem, wenn ich unabhängig vom zeitichen Ablauf des "Fahrprogrammes" die Abfrage der Sollgeschwindigkeit (hier mein Poti) abwickeln möchte. Das ist doch dann in jedem Falle eine Verzweigung oder besser gesagt ein Einschub in die andere Routine. Sonst müsste ich doch mit der Änderung der Geschwindigkeit warten, bis ich meinen Kurs abgefahren habe?

Ich hoffe, das ich mein Anliegen jetzt besser beschrieben habe...
Thomas

Das hast Du uns ganz schön schwierig gemacht.
Lösung: eliminiere das delay und ersetze es durch millis() wie im Beispiel:
http://arduino.cc/en/Tutorial/BlinkWithoutDelay
Der Sketch kontrollier ob die Zeit vergangen ist. In der Zwischenzeit kann anderer Kode ausgeführt werden.

Grüße Uwe

uwefed:
Das hast Du uns ganz schön schwierig gemacht.
Lösung: eliminiere das delay und ersetze es durch millis() wie im Beispiel:
http://arduino.cc/en/Tutorial/BlinkWithoutDelay
Der Sketch kontrollier ob die Zeit vergangen ist. In der Zwischenzeit kann anderer Kode ausgeführt werden.

Grüße Uwe

Und deswegen danke ich Euch besonders für Eure Geduld! Manchmal ist man eben irgendwie betriebsblind. Das "blinkwithoutdelay" habe ich am Anfang meiner "Arduinokarriere" mal irgendwann ausprobiert, aber dann völlig ausgeblendet. Ich hatte zwar das Gefühl hier irgendetwas zu übersehen - aber kam einfach nicht drauf was....

Grüße, Thomas