Werbung
Wenn ich heute abend zuhause bin fange ich mal einen etwas anderen Sketch an, der hat dann nur eine Funktion mit 4 Parametern.
Da kannst Du dann alleine durch die Parameter alles gestalten.
Also Stop, Vorwärts, Rückwärts, auf der Stelle Links und Rechts drehen, aber auch Kurvenfahrt oder drehen über ein stehendes Rad.
Das wäre dann die flexibelste Variante.
Dadurch das es einzelne Parameter sind, kann man dann auch später problemlos eine Geschwindigkeits oder Positionsregelung integrieren (Odometrie).
In der momentanen Variante mit dem einem Parameter ist das unschön, da müsste man die Regelung in jede einzelne Fahrfunktionen reinlegen.
Das würde später mal ein riesen Code Wust ergeben.
Geändert von i_make_it (21.02.2018 um 11:40 Uhr)
So, hier die Fassung mit den vier Parametern.
Code:/* PWM Pins Nano: 3; 5; 6; 9; 10; 11 Uno: 3; 5; 6; 9; 10; 11 Due: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 Mega 2560: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 */ int IN1 = 9; int IN2 = 8; int IN3 = 7; int IN4 = 6; int speedl1; int speedl2; int speedr1; int speedr2; int loopcount; void setup() { pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); } void loop() { // Vorwärts for (int loopcount=0; loopcount <=255; loopcount++){ speedl1 = loopcount; speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=255; loopcount >=0; loopcount--){ speedl1 = loopcount; speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Rückwärts for (int loopcount=0; loopcount <=255; loopcount++){ speedl1 = 0; speedl2 = loopcount; speedr1 = 0; speedr2 = loopcount; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=255; loopcount >=0; loopcount--){ speedl1 = 0; speedl2 = loopcount; speedr1 = 0; speedr2 = loopcount; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Links Drehen über Mittelpunkt for (int loopcount=0; loopcount <=255; loopcount++){ speedl1 = loopcount; speedl2 = 0; speedr1 = (255 - loopcount); speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=255; loopcount >=0; loopcount--){ speedl1 = loopcount; speedl2 = 0; speedr1 = (255 - loopcount); speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Rechts Drehen über Mittelpunkt for (int loopcount=0; loopcount <=255; loopcount++){ speedl1 = (255 - loopcount); speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=255; loopcount >=0; loopcount--){ speedl1 = (255 - loopcount); speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Links Drehen über linkes Rad for (int loopcount=0; loopcount <=255; loopcount++){ speedl1 = loopcount; speedl2 = 0; speedr1 = 0; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=255; loopcount >=0; loopcount--){ speedl1 = loopcount; speedl2 = 0; speedr1 = 0; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Rechts Drehen über rechtes Rad for (int loopcount=0; loopcount <=255; loopcount++){ speedl1 = 0; speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=255; loopcount >=0; loopcount--){ speedl1 = 0; speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Vorwärts Kurve Links Radius = Roboterbreite for (int loopcount=0; loopcount <=127; loopcount++){ speedl1 = (loopcount * 2); speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=127; loopcount >=0; loopcount--){ speedl1 = (loopcount * 2); speedl2 = 0; speedr1 = loopcount; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } // Rückwärts Kurve Rechts Radius = Roboterbreite for (int loopcount=0; loopcount <=127; loopcount++){ speedl1 = 0; speedl2 = loopcount; speedr1 = 0; speedr2 = (loopcount * 2); PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } for (int loopcount=127; loopcount >=0; loopcount--){ speedl1 = 0; speedl2 = loopcount; speedr1 = 0; speedr2 = (loopcount * 2); PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(10); } } void PWMDrive(int speedl1,int speedl2,int speedr1,int speedr2){ analogWrite(IN1, speedl1); analogWrite(IN2, speedl2); analogWrite(IN3, speedr1); analogWrite(IN4, speedr2); }
@i_make_it:
alle beispiele in Deiner demo sind als for-schleife ausgelegt. Warum laufen die motoren hier z.b. in der loop aufgerufen, ohne for schleife nicht?
zuerst dachte ich es liegt an zu kleinem delay, das ist es aber nichtCode:void vorwaerts() { speedl1 = 255; speedl2 = 0; speedr1 = 255; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(500); Serial.println("vorwärts"); } void rueckwaerts() { speedl1 = 0; speedl2 = 255; speedr1 = 0; speedr2 = 255; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(500); Serial.println("rückwärts"); }![]()
das ist der aufruf in der loop:
jetzt wirds aber noch geheimnisvoller: solange das USB kabel zum pc angeschlossen ist läufts, ziehe ich es ab nicht mehr. Die akkuspannung (6xAA) liegt bei 7,3VCode:void loop() { vorwaerts(); //delay(500); //delay(500); rueckwaerts(); //delay(500); }
Geändert von inka (01.03.2018 um 17:24 Uhr)
gruß inka
Die For Schleifen habe ich nur zum Rampen von 0 auf 255 und zurück genutzt.
Man kann natürlich auch vor dem Aufruf feste Werte eingeben.
Wenn man keinen Entscheidungsbaum hat kann man ein festes Fahrprogramm mit delay() schreiben (wodurch man aber nichts anderes merh machen kann).
Üblicherweise würde man (nicht bei Deinem Balancer) Bumper auswerten für STOP und dann auswerten welcher Bumper ausgelöst wurde und entsprechend eine gewisse Strecke oder Zeit nach hinten fahren und dann auf der Stelle drehen um die Ausrichtung weg vom Hinderniss zu verändern.
Bei den Fernsensoren würde man z.B.:
bei einem Hinderniss vorne Rechts mit Abstand < 10cm den Linken Motor auf 50 drosseln und den rechts auf 230 lassen. (231 bis 255 sind Regelreserve).
Bei einem Hinderniss vorne Rechts mit Abstand < 20cm den Linken Motor auf 90 drosseln und den rechts auf 230 lassen.
Bei einem Hinderniss vorne Rechts mit Abstand < 30cm den Linken Motor auf 130 drosseln und den rechts auf 230 lassen.
Bei einem Hinderniss vorne Rechts mit Abstand < 40cm den Linken Motor auf 170 drosseln und den rechts auf 230 lassen.
Bei einem Hinderniss vorne Rechts mit Abstand < 50cm den Linken Motor auf 200 drosseln und den rechts auf 230 lassen.
Bei einem Hinderniss vorne Rechts mit Abstand >= 50cm den Linken Motor auf 230 lassen und den rechts auf 230 lassen.
Das selbe noch für links und man hat ein relativ flüssiges Fahren, bei dem der Roboter Annäherungen unter 50cm an erkannte Hindernisse versucht zu vermeiden und bei Unterschreitung immer stärker gegenlenkt ohne zu langsam zu werden.
Delay() sollte man im fertigen Program vermeiden.
An dem Rechner hier habe ich keine Arduino IDE, der Code ist rein im Notepad geschrieben, ich kann also nicht sicher sagen ob er fehlerfrei ist.
Er sollte die Buildin LED blinken lassen und 1 Sekunde vorwärts fahen mit blinkender LED.
Dann 1 Sekunde rückwärts fahren mit delay(), wodurch die LED nicht blinken kann.
Dann 1 Sekunde auf der Stelle rechts drehen mit blinkender LED und 1 Sekunde ein enge Kurve nach links fahren mit delay(), wodurch die LED wieder nicht blinken kann.
Update: Fehler im Code beseitigt.Code:/* PWM Pins Nano: 3; 5; 6; 9; 10; 11 Uno: 3; 5; 6; 9; 10; 11 Due: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 Mega 2560: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 */ int IN1 = 9; int IN2 = 8; int IN3 = 7; int IN4 = 6; int speedl1; int speedl2; int speedr1; int speedr2; unsigned long prev1micros = 0; const long waittime1 = 1000; int togglestate1 = LOW; unsigned long prev2micros = 0; const long waittime2 = 100; int togglestate2 = LOW; void setup() { pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); } void loop() { //Blinken der Build in LED unsigned long cur2micros = millis(); if (cur2micros - prev2micros >= waittime2) { prev2micros = cur2micros; if (togglestate2 == LOW){ togglestate2 = HIGH; digitalWrite(LED_BUILTIN, HIGH); }else{ togglestate2 = LOW; digitalWrite(LED_BUILTIN, LOW); } } // Warten ohne delay unsigned long cur1micros = millis(); if (togglestate1 == LOW){ if (cur1micros - prev1micros >= waittime1) { prev1micros = cur1micros; // rückwärts mit delay speedl1 = 0; speedl2 = 200; speedr1 = 0; speedr2 = 200; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(1000); togglestate1 = HIGH; }else{ // vorwärts ohne Delay (LED Blinkt) speedl1 = 200; speedl2 = 0; speedr1 = 200; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); } } if (togglestate1 == LOW){ if (cur1micros - prev1micros >= waittime1) { prev1micros = cur1micros; // linksrum mit delay speedl1 = 50; speedl2 = 0; speedr1 = 200; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(1000); togglestate1 = LOW; }else{ // Rechts drehen ohne Delay (LED blinkt) speedl1 = 200; speedl2 = 0; speedr1 = 0; speedr2 = 200; PWMDrive(speedl1, speedl2, speedr1, speedr2); } } } void PWMDrive(int speedl1,int speedl2,int speedr1,int speedr2){ analogWrite(IN1, speedl1); analogWrite(IN2, speedl2); analogWrite(IN3, speedr1); analogWrite(IN4, speedr2); }
Geändert von i_make_it (01.03.2018 um 21:04 Uhr)
Du hast den Akku über den VIN Pin oder den Klinkenstecker angeschlossen?
Der Code den Du in Deinem letzten Post hast, Da ist keine Funktion PWMDrive zu sehen. Hast Du Die nur nicht dargestellt, oder ist die auch nicht im Sketch?
Denn diese Funktion wird ja in den Funktionen vorwaerts und rueckwaerts aufgerufen.
ja, über Vin
ich habe jetzt hier noch einmal die geänderte "demo" version.
in den funktionen vorwaerts() und rueckwaerts() habe ich nur die schleife rausgenommen und die werte direkt eingesetzt. Noch einmal ausprobiert bei gleicher hardware: Deine demoversion geht, die von mir korrigierte (ohne FOR schleife) nur bei eingestecktem USB kabel. Man spürt nur am auf dem motor aufgelegtem finger, dass der motor alle halbe sekunde kurz tickt...Code:/* PWM Pins Nano: 3; 5; 6; 9; 10; 11 Uno: 3; 5; 6; 9; 10; 11 Due: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 Mega 2560: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 */ int IN1 = 8;//9 int IN2 = 9;//8 int IN3 = 10;//7 int IN4 = 11;//6 int speedl1; int speedl2; int speedr1; int speedr2; int loopcount; void setup() { pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); Serial.begin(115200); Serial1.begin(115200); } void loop() { /* vorwaerts_rampe_hoch(); delay(500); vorwaerts_rampe_runter(); delay(500); rueckwaerts_rampe_hoch(); delay(500); rueckwaerts_rampe_runter(); delay(500); */ vorwaerts(); //delay(500); //delay(500); rueckwaerts(); //delay(500); } void vorwaerts()//geht nicht { speedl1 = 255; speedl2 = 0; speedr1 = 255; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(500); Serial.println("vorwärts"); Serial1.println("vorwärts"); } void rueckwaerts()//geht nicht { speedl1 = 0; speedl2 = 255; speedr1 = 0; speedr2 = 255; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(500); Serial.println("rückwärts"); Serial1.println("rückwärts"); } void PWMDrive(int speedl1, int speedl2, int speedr1, int speedr2) { analogWrite(IN1, speedl1); analogWrite(IN2, speedl2); analogWrite(IN3, speedr1); analogWrite(IN4, speedr2); }
gruß inka
Ich vermute mal, das der Anlaufstrom der Motoren die Spannung einbrechen lässt.
Mit USB hast Du ein halbes Ampere mehr.
Beim Rampe mit den For Schleifen, wird die Drehzahl ja in diskreten Schritten erhöht, was den Motorstrom zeitlich entzerrt.
Bei einem direkten Sprung von 0 auf 255 ziehen die Motoren halt Maximalstrom.
Da kann man mal Stützkondensatoren in der Stromversorgung des Motorreglers versuchen oder halt mehrere Fahrstufen.
Das deutet allerdings eher auf den Effekt durch EIN (1) delay(500) hin.
Zum Testen, kannst Du mal diesen Code in void setup() einfügen
Das sollte ein Count Down Blinken der Build in LED verursachen, einmalig wenn der µC startet.Code:pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); delay(800); digitalWrite(LED_BUILTIN, LOW); delay(200); digitalWrite(LED_BUILTIN, HIGH); delay(500); digitalWrite(LED_BUILTIN, LOW); delay(200); digitalWrite(LED_BUILTIN, HIGH); delay(300); digitalWrite(LED_BUILTIN, LOW);
Sollte die LED nach dem Rucken der Motoren wieder den Count Down blinken, dann bricht die Spanung ein und der µC geht durch den "brown out" in Reset.
Zweite Maßnahme ist den Motoren statt 255 erst mal 10 als wert fürs PWM zu geben.
Der folgene Code führt den Count Down Blink durch, rampt dann Vorwärts bis 250 hoch, stoppt und geht dann von 0 auf 255 in Rückwärts.
Das sollte ggf. schon zeigen an welcher Stelle es hängt.
Code:// PWM Pins Due: 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13 int IN1 = 8;//9 int IN2 = 9;//8 int IN3 = 10;//7 int IN4 = 11;//6 int speedl1; int speedl2; int speedr1; int speedr2; void setup() { pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); delay(800); digitalWrite(LED_BUILTIN, LOW); delay(200); digitalWrite(LED_BUILTIN, HIGH); delay(500); digitalWrite(LED_BUILTIN, LOW); delay(200); digitalWrite(LED_BUILTIN, HIGH); delay(300); digitalWrite(LED_BUILTIN, LOW); } void loop() { speedl1 = 20; speedl2 = 0; speedr1 = 20; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 40; speedl2 = 0; speedr1 = 40; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 80; speedl2 = 0; speedr1 = 80; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 120; speedl2 = 0; speedr1 = 120; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 160; speedl2 = 0; speedr1 = 160; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 200; speedl2 = 0; speedr1 = 200; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 250; speedl2 = 0; speedr1 = 250; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 0; speedl2 = 0; speedr1 = 0; speedr2 = 0; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(50); speedl1 = 0; speedl2 = 255; speedr1 = 0; speedr2 = 255; PWMDrive(speedl1, speedl2, speedr1, speedr2); delay(350); } void PWMDrive(int speedl1, int speedl2, int speedr1, int speedr2) { analogWrite(IN1, speedl1); analogWrite(IN2, speedl2); analogWrite(IN3, speedr1); analogWrite(IN4, speedr2); }
Geändert von i_make_it (04.03.2018 um 07:05 Uhr)
das blinken der eingebauten LED zeigt eindeutig, dass die motoren, bzw. der strom den sie ziehen den arduino zum reset zwingen...
danke erstmal, ich habe jetzt genügend "stoff" zum üben und testen...
gruß inka
Eventuell mal zwichen Akku und VIN eine kleine Schaltung einfügen. Direkt nach der Aufteilung (Steuerungsversorgung/Motorenversorgung) eine Diode (Germanium wegen dem kleineren Spannungasabfall) in die Steuerungsversorgung und danach einen Stützkondensator. Bei der Motorversorgung auch einen Stützkondensator rein.
Beide Kondensatoren werden durch den Akku geladen. Ziehen die Mororen zu viel Strom, kann der Stützkondensator im Motorzweig kurzfristig den Akku unterstützen.
Reicht das nicht, verhindert die Diode einen Stromfluß von der Steuerungsseite zur Motorseite und der Stützkondensator dort kann kurzfristig den Arduino versorgen.
Das ist aber nur für wirklich kurze Stromspitzen gut.
Ein Step Up/Down Regler, der bei schwankender Eingangsspannung direkt 5V für den Arduino liefert Zusammen mit einem Stützkondensator ist insgesammt vermutlich besser.
Wenn ich mich richtig erinnere ist hinter VIN ein Längsregler, der benötigt typisch mindestens 1,5V mehr Eingangsspannung als er liefern kann.
Da VIN mit 7-12V angegeben ist, hat dein Akku nur 0,3 V (oder maximal 0,8V) die er einbrechen kann bevor der Arduino den Saft abgedreht bekommt.
Bei einem Regler der auch mit deutlich weniger Eingangsspannung auskommt, wird auch die Einsatzzeit zwichen zwei Ladervorgängen erhöht, da der Akku tiefer entladen werden kann bevor die Spannung nicht mehr reicht.
Geändert von i_make_it (04.03.2018 um 10:40 Uhr)
Lesezeichen