Servus und schönen Sonntag,
ich bin neu hier und neu im Umgang mit dem Arudino und seiner
Programmierung. Und leider habe ich ein Problem, das ich zwar umzingeln,
aber nicht lösen kann. Ich hoffe, dass ihr mir weiterhelfen könnt. Aber
der Reihe nach, schließlich habe ich hier und in anderen Foren gelesen,
dass viele Infos viel helfen:
Was ich verwende:
- Aduino Nano (V3; ATMEGA328-Chip)
- H-Brücke L298N (MotoDriver2)
- diverse Jumpercable
- Breadboard (SYB-46)
- RC-Empfänger Spektrum AR410 (4 Kanäle)
- Fernsteuerung Spektrum Blade MLP4DSM
- Akku Soaring 2200 30C mit 11,1V & 24,42Wh
- Motoren mit unbekannten Spezifika. Der Originalakku hatte folgende
Werte: 7,2V & 1.250mAh, sie funktionieren aber auch super mit dem neuen
Akku. Die Motoren sind auch unten im Bild zu sehen.
- Anfängerkenntnisse eines Fachfremden aus den vielen
(Youtube-)Tutorials, der Lust an so einem Projekt hat ;-)
Das Projekt:
Ich habe mir einen Terrain Twister - quasi ein ferngesteuertes Auto mit
zwei achimedischen Schrauben rechts und links zur Fortbewegung -
gebraucht gekauft. Ein Bild des Fahrzeugs (Fahrzeug_TT.jpg) habe ich
beigefügt.
Das Fahrzeug als solches funktioniert sehr gut, hat aber so eine billige
Kinderfernsteuerung, die mit einem Kreuzknüppel die beiden Schrauben nur
ein- oder ausschalten kann. Weil das kein schönes Fahrgefühl ist, habe
ich mir gedacht, ob man das nicht besser machen könnte.
--> Kann man. Nach einiger Internetrecherche sieht mein Plan nun so aus:
Ich habe eine RC-Fernsteuerung mit der ich wie bei einer Panzersteuerung
die beiden Schrauben steuern kann, sprich rechts > links = Linkskurve;
links > rechts = Rechtskurve etc. Dabei sollen die Motoren auch etwas
zwischen aus und volle pulle können. Funktionieren soll das über einen
RC-Empfänger, der die Steuerinfos an den Arduino weitergibt. Der
wiederrum steuert die beiden Motoren, die die Schrauben antreiben.
Letztlich genau so, wie in diesem Video von Sparkfun auf Youtube
beschrieben: https://www.youtube.com/watch?v=u0Ft8SB3pkw (min 15:13).
Was bisher geschah:
Wer viel zu diesem Thema im Internet sucht, findet auch viel. Darunter
auch verwendbaren Code.
Hier:
https://sturm.selfhost.eu/wordpress/rc-fernsteuerung-mit-arduino-benutzen-1-teil-viele-grundlagen-und-das-auslesen/
habe ich zB. einen guten Code gefunden, der die Kommunikation
RC-Empfänger - Arduino abdeckt. Ich brauche nur zwei Kanäle (Joystick
links für Schraube links & Joystick rechts für Schraube rechts).
Außerdem habe ich mir einen Code (ab-)geschrieben, mit dem ich die
Motoren zeitgesteuert gleichzeitig und einzeln sowie in beide Richtungen
laufen lassen kann. Beide Codes funktionieren einzeln einwandfrei und
zusammengesetzt schauen sie so aus:
1
//Variablen
2
3
//RC-bezogen
4
//Channel 1: linker Joystick vertikal
5
intcnt_CH_1=0;//Zähler Channel 1 für Interruptroutine
6
intfrqraw_CH_1=0;//Übergabewert Channel 1 aus Interruptroutine
7
8
//Channel 3: rechter Joystick vertikal
9
intcnt_CH_3=0;//Zähler Channel 3 für Interruptroutine
10
intfrqraw_CH_3=0;//Übergabewert Channel 3 aus Interruptroutine
Serial.begin(9600);//serielle Verbindung etablieren damit wir was am Seriellen Monitor sehen können [Originaleinstellung: 9600; 112500 funktioniert nicht!]
62
}
63
64
65
ISR(TIMER1_COMPA_vect){//die Interruptroutine gibt ein Zehntel der Impulsbreite in µs zurück
66
67
if(PIND&(1<<PD2)){//Channel 1 rechts vertikal, das ist PIN D2
68
cnt_CH_1++;//wenn Eingang High dann Zähler inkrementieren
69
}
70
elseif(cnt_CH_1){//wenn Eingang Low dann prüfen ob Zähler gestartet
71
frqraw_CH_1=cnt_CH_1;//wenn Zähler gestartet, stoppen und Wert übergeben
72
cnt_CH_1=0;//Zähler zurücksetzen
73
}
74
75
if(PIND&(1<<PD4)){//Channel 3 links vertikal, das ist PIN D4
76
cnt_CH_3++;//wenn Eingang High dann Zähler inkrementieren
77
}
78
elseif(cnt_CH_3){//wenn Eingang Low dann prüfen ob Zähler gestartet
79
frqraw_CH_3=cnt_CH_3;//wenn Zähler gestartet, stoppen und Wert übergeben
// analogWrite(ENB, abs(sigB_CH_3)); // Genau diese Zeile macht das Problem: Mit dieser entstehen komische Werte und der Motor lässt sich nicht steuern. Auf der anderen
126
// Seite ist das kein Problem. Was passiert bei analogWrite, dass des des System so durcheinander bringt?
127
128
if(sigB_CH_3>deadzone)
129
{
130
digitalWrite(IN3,HIGH);
131
digitalWrite(IN4,LOW);
132
}
133
elseif(sigB_CH_3<-deadzone)
134
{
135
digitalWrite(IN3,LOW);
136
digitalWrite(IN4,HIGH);
137
}
138
else
139
{
140
digitalWrite(IN3,LOW);
141
digitalWrite(IN4,LOW);
142
}
143
144
145
}
146
147
//Loop-Ende!
Das Problem:
Der Code funktioniert, aber nicht ganz. Durch viel herumprobieren und
stellenweises auskommentieren habe ich herausgefunden, dass es an der
Zeile "analogWrite(ENB, abs(sigB_CH_3));" liegen muss (ist im Code
entsprechend kommentiert).
Ist diese auskommentiert, dann funktioniert der Code bis auf diese
Funktion einwandfrei, Motor A kann ich, wie ich mir das vorgestellt
habe, proportional über die Fernsteuerung in beide Richtungen steuern.
Auch IN3 & IN4 werden korrekt ausgegeben. Die Werte, die ich über die
serielle Schnittstelle ausgegeben bekomme, sind sinnvoll und entsprechen
dem, was ich erwarten würde.
Ist die besagte Codezeile nicht auskommentiert, dann kann ich keine der
beiden Motoren steuern. Die Werte, die ich über die serielle
Schnittstelle ausgegeben bekomme, sind viel zu hoch, kaum sinnvoll und
führen nur dazu, dass beide Motoren in maximaler Geschwindigkeit in eine
Richtung laufen.
Bisher habe ich folgendes ausprobiert / herausgefunden:
- Die Reihenfolge der "Codeelemente" macht keinen Unterschied, es ist
egal, ob ich zuerst Motor A oder Motor B behandel; es ist egal, ob ich
zuerst CH1 oder CH3 prozessieren lasse und auch die An-/Abwesenheit der
seriellen Schnittstelle und entsprechenden Serial.println(... ist
wurscht.
- Zur Sicherheit habe ich auch die beiden Motoren gegeneinander
ausgetauscht, das macht keinen Unterschied. Auch habe ich die beiden
Motoren stumpf nach dem System
analogWrite(ENA, 100);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(2000);
jeweils in beide Richtungen laufen lassen, dh, ein Hardwareproblem ist
auszuschließen.
- Der Code wird anstandslos kompiliert.
- Und jetzt die interessanteste Erkenntnis: Die Codezeile erzeugt nur
dann Fehler, wenn ein Wert ungleich Null eingetragen wird, sprich die
Zeile "analogWrite(ENB, abs(0));" erzeugt keinen Fehler!
...und an dieser Stelle verstehe ich es nicht mehr: Warum und woran kann
es scheitern, dass des nachweislich sinnvolle und vorhandene Signal
nicht in eine nachweislich sinnvolle und funktionierende Funktion
eingesetzt werden kann? Und warum zerstört es dann auch gleich das ganze
Signalgefüge?
Wenn es nicht an der Hardware liegt, nicht am Code liegt, dann kann es
doch nur noch irgendwo in den Eingeweiden des Arduino liegen? Verwende
ich irgendwelche Speicher, Register oder sowas doppelt oder so? Könnt
ihr mir da weiterhelfen?
Ich habe noch einen (handschriftlichen - ich habe mich bemüht!)
Aufbauplan (Schaltplan_TT.pdf) und Bilder des Aufbaus (Übersicht_TT.jpg;
Detail_Arduino.jpg; Detail_HBrücke.jpg) beigefügt.
Das war jetzt viel zu lesen, ich weiß, aber ich wollte euch keine Infos
vorenthalten, die vielleicht zur Lösung führen könnten. Gleichzeitig ist
das aber auch alles was ich weiß. Vor allem weiß ich auch nicht, wie ich
das Problem weiter eingrenzen soll - oder plump, wonach ich googln
könnte.
Darum meine Frage an euch: Könnt ihr da bitte mal drüberschauen? Was
fällt euch auf, findet ihr Fehler oder woran könnte es liegen?
Schon mal vielen Dank für eure Hilfe! Wenn ihr Rückfragen habt oder
mehr/andere Details braucht, dann meldet euch gerne!
In diesem Sinne noch einen schönen Abend noch!
Flo
Flo B. schrieb:> findet ihr Fehler oder woran könnte es liegen?
Ich glaube, du brauchst jetzt ein Messgerät in Form eines Oszilloskops.
Dann kannst du einfach mal alles abklemmen und an all den Pins messen,
ob das herauskommt, was du erwartest und ob es dem entspricht, was der
angeschlossene Treiber braucht. Nur so wirst du weiterkommen.
kann auch nicht. 115200baud ist der Standard, nicht der Zahlendreher.
Den Rest habe ich nochz nicht weiter angesehen.
Cyblord -. schrieb:> Programmieren ganz ohne Skill und per Trial&Error funktioniert halt nur> im Film. Und wenns nur der Arduino-Werbefilm im Kopf mancher Gestalten> ist.
Ah, ein vom Himmel gefallener Meister...
STK500-Besitzer schrieb:> 112500 funktioniert nicht!]> kann auch nicht. 115200baud ist der Standard, nicht der Zahlendreher.
Die Abweichung zwischen den beiden Zahlen ist gerade mal 2,4%. Das
könnte schon noch gehen.
Aber auch das könnte man ganz einfach nachmessen. Hatte ich es schon
erwähnt: so ein Oszilloskop ist ein echt scharfes Ding für solche
Probleme. Und man kann noch viel mehr damit machen: kontrollieren, ob
die SPI- oder I²C-Schnitte richtig rennt, analoge Spannungsverläufe und
Rampen anzeigen und wasweißichnochalles.
Da der ATmega328 nach meinem Wissen keinen DAC an Bord hat, wird das
analoge Ausgangssignal wohl über PWM erzeugt.
Und da sagt einem doch die Logik, daß dazu ein Timer gebraucht wird.
Und bei Ausgabe 0 wird kein Timer angeworfen, sondern der Pin nur
einmal auf GND geschaltet. Passt insofern alles wunderbar, in erster
Näherung wird von der Arduino-IDE genau der auch von Dir genutzte
Timer eingesetzt.
Sobald Du den Analogausgang setzt, wird alles von Dir Programmierte
über den Haufen geworfen.
Ist einfach nur Spekulation, aber leidlich durch den Effekt begründete.
Weitere Möglichkeiten?
Mit freundlichen Grüßen
Klaus
Mir ist nicht klar, was der Arduino überhaupt machen soll. Der
Fernsteuerempfänger hat schon Servoausgänge, die zwei Fahrtenregler
direkt ansteuern können.
Im schlimmsten Fall brauchst du also 2 Servoelektroniken, aus denen du
Fahrtenregler machst oder du kaufst sowas direkt fertig.
Jedes analoge Servo kann man zum Fahrtenregler machen, wenn man das
Feedback Poti von der Motorachse trennt und zum Einstellen des
Nullpunktes verwendet.
Falls du die Servoelektronik selber bauen willst, habe ich hier zwei
Bauvorschläge veröffentlicht:
Beitrag "RC-Servoelektronik für DC-Motor"
Angesteuert mit Signal vom RC-Empfänger
Flo B. schrieb:> Motoren mit unbekannten SpezifikaFlo B. schrieb:> H-Brücke L298N (MotoDriver2)
Schlecht.
Du weisst überhaupt nicht, ob die Treiber ausreichend sind.
Flo B. schrieb:> Beide Codes funktionieren einzeln einwandfrei und zusammengesetzt> schauen sie so aus:
Na ja, du hast viele Serial.print drin, die verzögern den Programmablauf
erheblich
Erst abhängig von sigB_CH_1, dann abhängig von sigB_CH_3 die Ausgänge
IN1 ind IN2 setzen zu lassen ist jedenfalls suboptimal.
Hi,
ENB - D9 - PB1 - nutzt Timer1a
den benutzt du schon für das Abfragen des Empfängers.
Entweder legst du ENB auf einen anderen PWM Pin, z.B. D10 nutzt Timer2,
oder du nutzt Timer2 für die Empfängerabfrage wobei der halt nur 8Bit
hat.
Grüße
Was passiert, wenn du anstatt
analogWrite(ENB, abs(sigB_CH_3)); (Zeile 125)
die Zeile
analogWrite(ENA, abs(sigB_CH_1)); (Zeile 97)
auskommentierst?
In wechen Bereichen bewegen sich die Werte von sigB_CH_3 und sigB_CH_1?
Weil grad Sonntag ist, habe ich aus Jux und Dollerei mal in die
Arduino Referenz geschaut. Und da ist angegeben, daß für den
Mega328 auf Pin 9 der Timer 1 für PWM zuständig ist.
Würde ich ganz grob über den Daumen mal als Volltreffer
charakterisieren.
MfG
Klaus
>Lothar M. schrieb:>STK500-Besitzer schrieb:>> 112500 funktioniert nicht!]>> kann auch nicht. 115200baud ist der Standard, nicht der Zahlendreher.>Die Abweichung zwischen den beiden Zahlen ist gerade mal 2,4%. Das>könnte schon noch gehen.
Vielleicht hab ich einfach nur meinen Klugscheißer-Tag:
Bei 16MHz steht im BaudrateRegister je nach Mode entweder 8 oder 16.
Der Atmega kann daraus als kleinste Änderung nur 9 oder 17 im BRR
speichern.
Das ergibt eine Abweichung von 1/8 oder 1/16, also 12,5% oder 6,75%.
Kleinere Abweichungen kann er nicht, da kann die C-Software ruhig
mit 128bit Genauigkeit rechnen, das BaudrateRegister kennt kein
FloatingPoint.
Mit freundlichen Grüßen
Klaus
kseege schrieb:> Vielleicht hab ich einfach nur meinen Klugscheißer-Tag:
Stimmt zwar alles, bedeutet aber letztlich nur, dass dieser Tippfehler
mit den 112500 noch weniger Probleme macht, als die Hardware sowieso
schon mit der "richigen" Baudrate 115200 hat. Der kleine Zahlendreher
mit seinen 2,4% Abweichung geht von vorne weg in der groben Auflösung
des Vorteilers unter.
Oder andersrum: mit guter Wahrscheinlichkeit kommt je nach Rechenweg für
beide Fälle der selbe Vorteiler heraus und damit die selbe Abweichung
zustande. Und mit dem bereits erwähnten Oszilloskop könnte ich das recht
gut ausmessen... ;-)
Hi
>Das ergibt eine Abweichung von 1/8 oder 1/16, also 12,5% oder 6,75%.>Kleinere Abweichungen kann er nicht, da kann die C-Software ruhig>mit 128bit Genauigkeit rechnen, das BaudrateRegister kennt kein>FloatingPoint.
Mit Async, Double Speed Kommst du bei 16MHz auf einen Fehler von 2,1%.
MfG Spess
Spess53 schrieb:> Mit Async, Double Speed Kommst du bei 16MHz auf einen Fehler von 2,1%.
Und dann wäre die 112500 sogar noch genauer zu treffen (nur 0,3%
Abweichung, Bingo!) als die richtigen 115200. Und trotzdem genauso
falsch. Schade aber auch... ;-)
Hallo,
TIMSK1 solltest du mit = und nicht |= zuweisen. Oder vorher auf 0
setzen.
Und wenn du den Timer 1 selbst konfigurierst, dann verstellst du
übrigens das PWM Verhalten der Pin D9 und D10. Wahrscheinlich ist das
schon die Fehlerursache. Das ist sogar ziemlich sicher die Ursache, weil
du den ursprünglichen PWM Mode mit dem CTC Mode überschreibst. Weil der
andere Ausgang D6 liegt auf einem Ausgang von Timer 0 den du nicht
verändert hast. Darum funktioniert der. Timer 0 sollte man ohne guten
Grund auch nicht verändern, weil der für millis() und delay() benötigt
wird.
Desweiteren solltest du mit deinen Minuszeichen aufräumen. analogWrite()
kann eh nur zwischen 0 und 255 verarbeiten. Also map() anpassen. Damit
brauchste auch keinen Absolutwert mehr bilden und eine Fehlerquelle ist
weg.
Das hier
DDRD = 0b11000011;
ist auch Unsinn. Damit schießt du eigentlich deine Serial ab. Dich
rettet im Moment nur der Umstand das du Serial.begin() am Schluss von
setup aufrufst, die das korrigiert. Pin 0 und 1 (PD0 und PD1) greifst
und schließt du nicht an! Die gehören der Serial.
Dein Code hat auch mit deinen Links wenig zu tun. Merke. Kleinste
Änderungen können große Wirkung haben.
Desweiteren ist eine H-Brücke mit L298N wirklich, dass muss man so
deutlich sagen, eh totale Scheiße. Wann sterben die jemals aus? Viel zu
hohe Verluste und benötigen glaube ich mindestens 7V. Also falls dein
Akku schlapp macht geht da sowieso nichts mehr.
Suche auf ebay o.a. nach einem Modul mit BTS7960 oder BTN7960. Die
sollte man erstmal nicht kaputt bekommen. Die Kühlkörper könnte man noch
planer montieren, aber auf jeden besser wie die L298N Dinger. Ganz
ehrlich.
@ Lothar M. (lkmiller):
Da habe ich Deine ursprüngliche Bemerkung völlig anders interpretiert,
als Du sie wohl gemeint hast, wie Dein drauffolgendes Posting zeigt.
Daran sieht man mal wieder, wie leicht man mit knappen Beschreibungen
eine völlig unnötige Diskussion entfachen kann, weil unser tolles Gehirn
das Fehlende (aber leider falsch) dazuinterpretiert :-)))
MfG
Klaus
Flo B. schrieb:> - H-Brücke L298N (MotoDriver2)
- bis zu 82mA Eigenverbrauch
- bis zu 5V Abfall im Leistungsteil
- keinerlei Überlastschutz
Ich hab die vor über 20 Jahren auch reihenweise wechseln müssen, wenn
der magische Rauch entwichen ist.
Es gibt moderne MOSFET-Brücken mit geringen Verlusten und internem
Schutz.
Z.B. TB6612FNG bis 1A:
https://hackaday.com/2019/12/29/fet-based-motor-driver-is-better-than-l298n/
Matthias S. schrieb:> Mir ist nicht klar, was der Arduino überhaupt machen soll. Der> Fernsteuerempfänger hat schon Servoausgänge, die zwei Fahrtenregler> direkt ansteuern können.
Das war auch mein Gedanke dazu. Zwei ESC an den Empfänger und fertig ist
die Kiste.
Flo B. schrieb:> Ich habe mir einen Terrain Twister - quasi ein ferngesteuertes Auto mit> zwei achimedischen Schrauben rechts und links zur Fortbewegung -> gebraucht gekauft.
OT:
die beiden archimedischen Schrauben sind dann auch gleichzeitig die
Schwimmkörper? Ich meine: Im Wassen schwimmt das Teil dann auch auf den
Schrauben?
Also dann genauso, wie der sowjetische ЗИЛ ( SIL )- 2906 - genannt auch:
Schneckochod?
Klaus W. schrieb:> Gab auf YT mal einen Film von einem, der sich sowas als Einmann-Gefährt> selber gebaut hatte.
colin furze hat das sicher gemacht, obs noch mehr gibt weiß ich nicht
So ein Teil wäre fürs Brennholz machen - ganz praktisch … n paar mal
kreuz und quer über die Krone des ( bereits ) gefällten Baumes fahren -
dann nur noch aufsammeln und ab nach Hause ;-)
Guten Abend zusammen!
Und zu allererst: Vielen herzlichen Dank für die vielen konstuktiven
Kommentare!
Das ist jetzt mengenmäßig und inhaltlich so viel, dass ich mich da
zunächst Stück für Stück durcharbeiten muss.
So viel schon mal:
Zu dem Oszillioskop werde ich mich mal umhören, ob jemand im Freundes- /
Bekanntenkreis sowas hat und mir das leihen kann. Bislang habe ich
zwischen den Arduino und die H-Brücke LEDs gehängt, wenn sie leuchtet,
dann ist da Strom, ergo sollte zum Schluss der Motor laufen. Bitte
steinigt mich nicht, das ist ganz bestimmt nicht professionell, aber das
war das, was ich gut improvisieren konnte und mir auch einige Fehler
aufgezeigt hat.
Wenn ich einen Speicher doppelt verwende, dass dann komische Werte - die
dann das ganze System betreffen - herauskommen, macht absolut Sinn. Und
es klingt absolut plausibel, dass das auch bei mir zutreffen könnte. Ich
klemme mich dahinter!
Beim Thema Fehlerberechnung werde ich mir noch einen Taschenrechner
holen und vom Schlauch runtergehen, dann verstehe ich das bestimmt auch.
Wobei ich sagen muss, dass ich diese Zahl vielleicht in einer Anleitung
aufgeschnappt habe, im Zuge der Fehlersuche bzw. -eingrenzung
ausprobiert habe und nachdem es nicht funktioniert hat, auch wieder
verworfen habe.
Ich habs dazu geschrieben, weil nach drei Wochen weiß ich nicht mehr,
was ich schon alles ausprobiert habe. Und somit ist es im Code bzw. in
der Kommentierung stehen geblieben.
Die H-Brücke: Joa, des ist halt das Ding, was in den meisten Anleitungen
und Tutorials, die ähnliche Projekte beschrieben haben, auch meistens
verwendet wurde. Wie verlustig oder haltbar das Bauteil ist, habe ich
nicht explizit recherchiert. Aber vielen Dank für den Hinweis, da werde
ich mich mal nach den vorgeschlagenen schauen.
Walter K. schrieb:> Flo B. schrieb:>> Ich habe mir einen Terrain Twister - quasi ein ferngesteuertes Auto mit>> zwei achimedischen Schrauben rechts und links zur Fortbewegung ->> gebraucht gekauft.>> OT:>> die beiden archimedischen Schrauben sind dann auch gleichzeitig die> Schwimmkörper? Ich meine: Im Wassen schwimmt das Teil dann auch auf den> Schrauben?>> Also dann genauso, wie der sowjetische ЗИЛ ( SIL )- 2906 - genannt auch:> Schneckochod?
Walter: Ja, exakt, das Ding schwimmt auch! Ist unter anderem ein Grund,
warum ich es so cool finde. Und ja, das "Modell" ist an das genannte
russische Gefährt angelehnt. Mit dem Original hat man damals die
Astronauten, die mit den Kapseln aus dem Weltall irgendwo in Sibirien
gelandet sind, aus dem Gemüse geholt.
Also nochmals vielen Dank für Eure Hilfe, ich werde mich spätestens am
Wochenende hinsetzen und eure Kommentare sowie meinen Code nebeneinander
legen und nachvollziehen, was ihr genau gemeint habt. Dann werden
wahrscheinlich nochmal Fragen auftauchen, die ich euch sicherlich wissen
lassen werde. ;-)
Schönen Abend noch!
Flo
Flo B. schrieb:> Zu dem Oszillioskop werde ich mich mal umhören, ob jemand im Freundes- /> Bekanntenkreis sowas hat und mir das leihen kann.
Für diesen Zweck eignen sich die DSO150, sie kosten nur 30€. Oder ein
"8ch logic analyzer" für ca. 10€.