ICh habe folgendes Problem: Ich habe einen Servo an meinem Arduino Uno
mit Arduino Motorshield. Der Servo alleine Funktioniert prima. Ob mit
5V-Pin oder mit 7V Batterie es geht. Wenn ich jetzt aber ein LCD und
einen Abstandssensor dazunehme, geht er nichtmehr(das heißt, er geht,
macht aber lauter schwindsüchtige zuckungen. Egal, ob ich das mit oder
ohne Batterien versuche. Daraus schließe ich, das das irgendwie mit dem
Steuer-anschluss zu tun hat.
Mein Servo: http://www.segor.de/#Q%3DArduinoMicroServo%26M%3D1
Mein LCD: http://arduino.cc/en/Main/GTFT
Mein Abstandssensor: http://www.segor.de/#Q%3DHC-SR04%26M%3D1
Ich hoffe ihr könnt mir helfen. Wenn euch irgendwelche Dinge fehlen,
dann schreibt mir bitte.
12V
Es wird an deinem Programm scheitern. Das Ansteuern des LCD und Sensor
braucht Zeit und diese Zeit wird dir in deinem Servoprogramm fehlen.
Mit delay usw. geht da nichts mehr.
Aber das erklärt doch nicht diese seltsamen Zuckungen, die können doc
nur durch falsche Ansteuerung/Hardwarefehler entstehen. Letzteres
schließe ich aus, da er ja im alleinbetrieb wunderbar funktioniert.
12V DC schrieb:> Aber das erklärt doch nicht diese seltsamen Zuckungen, die können doc> nur durch falsche Ansteuerung/Hardwarefehler entstehen. Letzteres> schließe ich aus, da er ja im alleinbetrieb wunderbar funktioniert.
Ich schliesse das keineswegs aus.
Wenn ein Servo zuckt, kann das auch daran liegen, dass die
Versorgungsspannung zusammenbricht, wenn der Motor anfährt.
Aber du bist lange genug hier im Forum, um zu wissen, dass unsere
Glaskugeln nicht besonders gut funktionieren und das normalerweise immer
noch einem Schaltplan und dem Programm gefragt wird. Eigentlich solltest
du das schon wissen, wie hier der Hase läuft.
Also hier ist das Programm und mit nem Schaltplan kann man hier nicht so
viel anfangen glaub ich. Das Programm sollte selbsterklärend sein.
Aufbau hab ch oben schon mal beschrieben.
Karl Heinz schrieb:> Wenn ein Servo zuckt,
Er zuckt ja nicht, sondern macht unkonntrollierte Bewegungen, d.h. Er
fährt eine halbe sekunde, stoppt, fährt wieder, diesmal kürzer usw. Es
sind einfach unkontrollierte Bewegungen, allerdings immer in eine
Richtung.
12V DC schrieb:> Karl Heinz schrieb:>> Wenn ein Servo zuckt,>> Er zuckt ja nicht, sondern macht unkonntrollierte Bewegungen, d.h. Er> fährt eine halbe sekunde, stoppt, fährt wieder, diesmal kürzer usw. Es> sind einfach unkontrollierte Bewegungen, allerdings immer in eine> Richtung.
Mein Bauchgefühl, dass das Problem in der Stromversorgung zu suchen ist,
verstärkt sich.
Hier mal das Programm in einer lesbaren Form
Werden eigentlich die Arduino Servo Objekte per Timerinterrupt
betrieben?
Ich hoffe das mal, denn im Programm wimmelt es wieder mal von
Verzögerungssachen.
Magnus M. schrieb:> void setup()>> Beabsichtigst du die Routine auch mal aufzurufen?
Das ist Arduino.
Stell dir ein dazu ein main vor, dass so aussieht
1
intmain()
2
{
3
setup();
4
5
while(1)
6
loop();
7
}
und vordefiniert ist.
Als Modell für den Programmierer reicht das, wenn auch das Arduino
System noch ein paar Sachen zusätzlich macht (wie zb eine Systemuhr,
Timerinterrupts etc.)
Karl Heinz schrieb:>> Beabsichtigst du die Routine auch mal aufzurufen?>> Das ist Ardunio.
Ich glaube ich werde mich zukünftig aus allen Arduino Threads raus
halten. Das ist ja peinlich!
Magnus M. schrieb:> halten. Das ist ja peinlich!
So schlimm ist es nicht.
Das Hauptproblem bei der Arduino Programmierung besteht darin, dass es
da ein mitlerweile recht großes Framework gibt, welches einem viel
Arbeit abnimmt, aber auch das Problem hat, dass man wissen muss, wie
sich die einzelnen vordefinierten Klassen (ja, ist C++), die Resourcen
teilen und wo die Einschränkungen liegen.
Und natürlich, dass die hier aufschlagenden Arduino Programmierer
meistens die Doku nicht lesen. Den Teil finde ich persönlich viel
peinlicher: wenn ich als nicht-Arduino Programmierer in Google Stichwort
eingebe, in 5 Sekunden auf der Arduio Hompage die Doku zu einer
Funktion/Klasse finde und dort dann ganz genau steht, wies geht.
Aber im konkreten Fall hab ich immer noch die Stromversorgung im Auge.
Servos können nun mal schlimme Finger auf der Stromversorgung sein.
Karl Heinz schrieb:> Mein Bauchgefühl, dass das Problem in der Stromversorgung zu suchen ist,> verstärkt sich.
Das war auch mein erster Gedanke, weil ich das schon mal hatte, aber
nachdem das über Batterien mal geht mal nicht(wenn mehr am Arduino
hängt), dachte ich, das es etwas mit dem Signal zu tun hat. Evtl. kommt
es zu schwach an und wird falsch interpretiert
Magnus M. schrieb:> Warum nicht?>> Sind wir hier im Strickforum?
Nein sind wir nicht ;) Aber wenn der Schaltplan nur aus Verbindungen
besteht, die man aus dem Programm entnehmen kann, halte ich dies für
unnötig. Wenn du dazu Fragen hast dann frag. Aber extra nen Schaltplan
dafür zu basteln ist doch iwie unnötig, oder?
Magnus M. schrieb:> void setup()>> Beabsichtigst du die Routine auch mal aufzurufen?
Das braucht er bei Arduino-Programmen nicht. Für Arduino wird keine
"main" Funktion geschrieben, sondern eine "setup" (wird einmal
ausgeführt) und eine "loop" (wird immer wieder ausgeführt). Darum, dass
setup (einmalig) und loop (immer wieder) gestartet werden, braucht man
sich bei Arduino nicht zu kümmern. Solche Programme heißen daher bei
Arduino auch nicht "Programm" sondern "Sketch". Wahrscheinlich, weil es
für C-Programmierer so komisch aussieht.
@"12V DC": Wenn Du gut funktionierende Arduino-Software mit komplexen
Funktionabläufen schreiben möchtest, solltest Du Dich dringend darum
kümmern, die "Komfort-Funktionen" und die "Library-Funktionen" zu
verstehen, die Du verwendest!
Und dann alles an "Komfortfunktionen" weglassen, das kontraproduktiv für
Dein Vorhaben ist.
Schau Dir das an:
dis = pulseIn(echo, HIGH);
Die Arduino-Funktion "pulseIn" sperrt die Interrupts und blockiert den
Programmablauf, bis entweder der gesuchte HIGH-Impuls aufgetreten ist
oder das Standard-Timeout von einer Sekunde abgelaufen ist.
Ein Programm mit abgeschalteten Interrupts in der Ausführung total zu
blockieren ist natürlich völlig kontraproduktiv, wenn mehrere Dinge
gleichzeitig ablaufen sollen.
Deine "Servo-Library" möchte gerne per Timer-Interrupts alle 20
Millisekunden den Impuls zum Servo-Refresh senden, und Deine
pulseIn-Funktion blockiert den Programmablauf für bis zu 1000
Millisekunden komplett.
Das Programmkonzept mit der "pulseIn" Funktion ist völlig daneben.
Die Komfortfunktion "pulseIn" kannst Du NUR in solchen Sketchen sinnvoll
verwenden, die nichts anderes machen solllen als diese eine Pulslänge
messen. Für Sketche, die mehr oder weniger gleichzeitig oder im
Hintergrund Dinge erledigen sollen, ist "pulseIn" eine Funktion, die Du
überhaupt nicht verwenden darfst.
Ja, hab ich übersehn. Das ist ja leifer Gottes der Nachteil von Arduino,
das man iwelche Dinge einbindet, weil man gesgt bekommt, das das so geht
ohne sich darum zu scheren, was wirklich drin steht. Jürgens Text im
Klartext heißt also "Schreib dein Programm komplett um". Dieses PulseIn
-wenn ich da als dritten Parameter angeben soll, das maximal 10µS bis
zum beginn des Pulses gewartet werden sollen, dan wäre doch schonmal
ziemlich viel Zeit gespart, oder?
Aber ich versteh trotzdem nicht, wieso das PulseIn im alten PRogramm
gefunzt hat…
Kann es sein, das ich eine andere Funktion verwwendet habe, denn -wie
gesagt- habe ich den Quellcode geändert und versehentlich die Zeile
mitrausgeschmissen, in der die Zuweisung der Distanz festgelegt war.
12V DC schrieb:> Aber ich versteh trotzdem nicht, wieso das PulseIn im alten PRogramm> gefunzt hat…
Dein Programm ist ja bereits ziemlich komplex. Kann auch sein, dass Dir
was anderes als pulseIn in die Suppe spuckt. Ich habe mal gerade
versucht den Quelltext von pulseIn einzusehen und konnte dabei entgegen
meiner Annahme nicht feststellen, dass die Interrupts tatsächlich
gesperrt werden, während die Funktion läuft. Also es könnte auch sein,
dass dann die Servo-Library weiterläuft (da timer-interruptgesteuert),
aber das Problem mit so einem "blockierenden Funktionsaufruf" ist
trotzdem: Wenn vom Abstandsservo kein Echo kommt, wartet die Funktion
auf einen Timeout von einer Sekunde und so lange wird das Programm
ausgebremst (auch wenn der Servo dabei nicht durchdrehen sollte).
Deine loop-Funktion sieht jedenfalls so aus, als wenn der Servo alle 75
ms eine neue Servoposition anfahren soll, aber wie soll das mit einer
Funktion funktionieren, wenn die Funktion das Programm zwischendurch für
bis zu 1000ms bei jedem Schritt der for-Schleife blockiert?
Anyway.
Was mir noch auffällt, ist, dass Du ein Pixel-Display ansteuern möchtest
und nur einen UNO hast. Bist Du sicher, dass der genug RAM-Speicher zur
Ansteuerung des Displays und Deinen sonstigen Code hat?
Hast Du mal geprüft, wie viel RAM-Speicher Dein Programm überhaupt noch
frei hat, wenn die loop-Funktion startet?
Wenn die delayMicroSeconds halbwegs genau arbeiten soll, dann kommt sie
nicht drumherum, Interrupts zu sperren. Das wiederum dürfte die Signale
der Servo Klasse erheblich beeinflussen.
Kleiner Tip: Lagere die Servo-Steuerung in einen zweiten Mikrocontroller
aus. Im Netzt kursieren einige fix und fertige Schaltungsbeispiele z.B.
auf Basis eines AtTiny2313.
Mit Google habe ich das gefunden: "Wie damals bei der Arduino IDE 0018,
schaltet die Funktion delayMicroseconds() nicht mehr die Interrupts ab."
Welche Version verwendest du?
Stefan us schrieb:> Welche Version verwendest du?
Arduino 1.5.4
Stefan us schrieb:> Lagere die Servo-Steuerung in einen zweiten Mikrocontroller
Hatte ich auch schon dran gedacht. Nur bin ich mit meinem STM32f4 noch
nicht so bewndert. Atiny is ne Option, nur komme ich selten zum
Elektrohändler. Und ich würde das Problem gerne möglichst schnell lösen.
Jürgen S. schrieb:> Was mir noch auffällt, ist, dass Du ein Pixel-Display ansteuern möchtest> und nur einen UNO hast.
Das Hat eigentlich immer Prima gefunzt. auch mit diesem Programm.
Jürgen S. schrieb:> Hast Du mal geprüft, wie viel RAM-Speicher Dein Programm überhaupt noch> frei hat, wenn die loop-Funktion startet?
Wie kann ich das? Der Compiler gibt immer den verbrauchten Speicher an,
aber den Ram?
Mal ne andere Frage, wie viele Timer hat der Atmega? Er hat doch
bestimmt mehr als einen?
Laut Datenblatt hat der 2 8-bit Timer und einen 16bit Timer, aber kann
ich die über die Skeches einzeln ansteuern, um z.B. den Servo auf einen
zu legen und den Abstandssensor für den anderen zu benutzen? Muss ich
das dann in C schreiben?
12V DC schrieb:> Wie kann ich das? Der Compiler gibt immer den verbrauchten Speicher an,> aber den Ram?
Du kannst diese Funktion in Deinen Sketch einbauen:
Und dann mal den Rückgabewert am Ende des setups oder am Anfang der loop
auf Deiner Anzeige ausgeben lassen. Faustformel: Wenn im laufenden
Sketch noch mindestens 200 Bytes RAM frei sind und Du keine exzessiv
tiefen Funktionsaufrufe geschachtelt hast oder übermäßig viele Parameter
übergibst, sollte das ausreichen.
> Mal ne andere Frage, wie viele Timer hat der Atmega? Er hat doch> bestimmt mehr als einen?
Der UNO (Atmega328) hat drei Timer (Timer0, Timer1, Timer2), wovon
Timer0 bereits von der Arduino-Software verwendet wird, z.B. für die
Zeitmessung per millis() Funktion. Und Timer1 wird glaube ich
standardmäßig von der Servo-Library verwendet.
Sketch uses 11.298 bytes (35%) of program storage space. Maximum is
32.256 bytes. Das wäre die Ausgabe des Compilers zum RAM. Deine Funktion
funzt iwie nicht.
12V DC schrieb:> Ach ne sorry, hatte die Schriftfarbe falsch ;)> also: am anfang "1801/1795"> am ende "1781"
Also noch massenhaft RAM-Speicher frei, wenn die Funktion anzeigt, dass
Du von den 2048 Bytes RAM eines Atmega328 noch mindestens 1781 Bytes
frei hast.
Das reicht dicke, der Fehler muß also irgendeine andere Ursache haben.
Oben sehe ich auch das von Dir:
> Arduino 1.5.4
Was passiert denn, wenn Du Dir mal für Dein Board die richtige Version
der Arduino-Software installierst, statt die Betaversion für den
32-bittigen Arduino Due?
Die richtige und derzeitig aktuelle Softwareversion hat die Nummer
1.0.5!
Erst mit der Version 2.0 sollen irgendwann man die 8-bittigen
Entwicklungszweige 1.0.x und die 32-bittigen Entwicklungszweige 1.5.x zu
einer gemeinsamen Softwareversion zusammengelegt werden. Bis dahin ist
die Betaversion 1.5.x NUR für die 32-Bit DUE Boards vorgesehen. Und
diese DUE-Version ist für die 8-bittigen Atmegas noch relativ buggy.
Also diese lieber nicht für die 8-bittigen Controller verwenden, sondern
für diese immer nur die 1.0.5 oder Nachfolger (1.0.x)!
Sag mir das doch mal einer! Ich sehe auf der Arduino Homepage die IDE
1.5.4 und sehe im Menü, das man das Uno als Board auswählen kann und bin
zufrieden. es geht doch, oder ist das das Problem in der IDE zu suchen?
Aber anscheind geht das mit der Speicherverwaltung?
Wie hätte ich das erkennen können??
12V DC schrieb:> Sag mir das doch mal einer! Ich sehe auf der Arduino Homepage die IDE> 1.5.4 und sehe im Menü, das man das Uno als Board auswählen kann und bin> zufrieden.
Nur weil du es auswählen kannst, heisst das nicht, dass es auch
unterstützt ist. Auf der Seite steht klar dass es Beta ist:
http://arduino.cc/en/Main/Software
Bevor du weiterprobierst würde ich schon mal auf die aktuelle
unterstütze Version 1.0.5 zurückgreifen.
Auch mit 1.0.5 Zuckungen, allerdings kleine in beide richtungen.
Programm dasselbe. Den Ram zu prüfen halte ich für unnötig, da sich ja
nicht so viel verändert hat(oder irre ich mich?).
12V DC
Hast du denn schon mal versuchsweise das "unsägliche"
1
dis=pulseIn(echo,HIGH);
auskommentiert, oder wenigsten das Timeout auf ein paar wenige ms
gesetzt? Was passiert dann?
Die Funktion abstand() brauchst ja nur nur für die Anzeige. Die könnte
also auch einfach z.B. nur jede Sekunde im Loop aktualisiert werden,
oder?
12V DC schrieb:> Auch mit 1.0.5 Zuckungen, allerdings kleine in beide richtungen.
Also es hat sich etwas verändert durch den Wechsel der Softwareversion?
Und der Servo fährt seine vorgesehene Position an, und hat dann nur noch
kleine Zuckungen in beide Richtungen? Mehr so ein "Tickern" oder
"Zittern" auf der Stelle?
Das passiert mit der standardmäßigen Servo-Library, wenn im Sketch
Interrupts für längere Zeit gesperrt sind. Die üblichen Verdächtigen
sind dabei Display-Ausgaben.
Kannst Du mal versuchen, Displayausgaben zu deaktivieren, ob der Servo
dann immer noch zuckt?
Jürgen S. schrieb:> Kannst Du mal versuchen, Displayausgaben zu deaktivieren, ob der Servo> dann immer noch zuckt?
Soll ich auskommentieren oder abstecken?
Markus schrieb:> Hast du denn schon mal versuchsweise das "unsägliche"dis = pulseIn(echo,> HIGH); auskommentiert, oder wenigsten das Timeout auf ein paar wenige ms> gesetzt? Was passiert dann?
probier ich mal. Welches Timeout meinst du?
12V DC schrieb:> Jürgen S. schrieb:>> Kannst Du mal versuchen, Displayausgaben zu deaktivieren, ob der Servo>> dann immer noch zuckt?>> Soll ich auskommentieren oder abstecken?
Textausgaben auskommentieren.
Denn es ist ja wenn nur immer das Programm und nicht die Hardware, das
die Interrupts sperrt wenn es Zeit für exakte Timings bei Textausgaben
benötigt. Und das Sperren der Interrupts wiederum kann das exakte Timing
der Refresh-Impulse durch die Servo-Library negativ beeinflussen.
Jo, Problem liegt 1.)beim Display, es verursacht die Zuckungen
2.)b3eim PulseIn, es macht allse sehr langsam.
Ich habe zuerst die lcdtext() funktion auskommnetiert, und da hat sich
der servo sehr langsam, aber richtig bewegt und als ich dann noch
pulseIn weggenommen hab hats ordnungsgemäß funktioniert.
Im Gegensatz zu den Servo-Signalen ist die Displayausgabe ja überhaupt
nicht Zeitkritisch. ALso würde ich die Display-Ausgabe neu
programmieren, und zwar so, dass sie keine Interrupts sperrt.
Man könnte z.B. den auszugebenden Text in ein Array ablegen. Und dann in
einem Timer-Interrupt alle 20 Millisekunden einen Buchstaben davon an
das Display übertragen. Dadurch entfalen die sonst nötigen Wartezeiten
zwischen den Buchstaben, wenn man ganze Zeichenketten am Stück ans
Display sendet.
Für die Servo-Ansteuerung hast Du sowieso schon einen 20ms Timer. Man
könnte also beide Fliegen mit einer Klappe schlagen - wenn man auf die
Arduino Libraries verzichtet.
12V DC schrieb:> Hast du denn schon mal versuchsweise das "unsägliche"dis = pulseIn(echo,>> HIGH); auskommentiert, oder wenigsten das Timeout auf ein paar wenige ms>> gesetzt? Was passiert dann?>> probier ich mal. Welches Timeout meinst du?
Das Timeout des
1
pulseIn(pin,value,timeout);
Gib doch da mal ein tiefer Wert. z.B. 100 us an.
Und eben das Display weniger häufig. z.B. nur noch alle Sekunde,
aktualisieren, das reicht doch.
Ein bisschen Zeit könnte ich mir auch sparen, wenn ich SPI benutzen
würde, das kann ich aber nicht, weil das Motorshield die MOSI und SCLK
pIndś benutzt. Da geht halt auch so ca. eine haalbe skeunde jedesmal
verloren.
Wobei ja das Display die Zuckungen verursacht. Und die können doch nicht
durch Interrrupts entstehen, oder? Die PulseIn Funktion ist langsam, wie
oben beschrieben. Da merkt man das richtig. Keine Zuckungen, nur alles
sehr langsam.
Aber mein Hauptproblem sind die Zuckungen. Das es langsam ist stört
nicht so. Wenn man die Ursache dafür feststellen könnte(genau, nicht
"das lcd ist schuld"). Hat jemand das schon mal gehabt und kann mir
sagen, wie er es gelöst hat?
Ich habs damals(ich hatte das Problem schon mal ohne LCD) mit mehr
Batterien(Vin) gelöst, das hilft hier aber anscheined nicht.
12V DC schrieb:> Aber mein Hauptproblem sind die Zuckungen. Das es langsam ist stört> nicht so. Wenn man die Ursache dafür feststellen könnte(genau, nicht> "das lcd ist schuld"). Hat jemand das schon mal gehabt und kann mir> sagen, wie er es gelöst hat?
Wie viele Servos sind denn anzusteuern?
Wenn es nur ein oder zwei Servos sind, dann machst Du Dir am besten eine
eigene ServoRefresh-Funktion, die dann im Programm laufend aufgerufen
wird, und zwar aus der loop heraus (und nicht in timergesteuerten
Interrupts wie bei der Servo-Library).
Ich hab einen Servo ;)
Jürgen S. schrieb:> Wenn es nur ein oder zwei Servos sind, dann machst Du Dir am besten eine> eigene ServoRefresh-Funktion, die dann im Programm laufend aufgerufen> wird, und zwar aus der loop heraus (und nicht in timergesteuerten> Interrupts wie bei der Servo-Library).
versteh ich nicht.
Also ich habe vor einger Zeit eine Ansteuerung für zwei Servos und einen
Laser zum X-Y-gesteuerten Zeigen auf ein Lager-Regal gebaut, die wurde
per USB-UART angesteuert - da hatte ich niemals Probleme mit zuckenden
Servos. Während der Entwicklung hatte ich auch zeitweise noch ein
serielles LCD an einer Soft-UART dran ...
Ich habe die Servo-Routinen als Funktionen selber geschrieben, ohne
Interrupts einfach mit delay-microseconds (oder wie das hieß).
Allerdings habe ich digitale Servos verwendet - denen ist nach meinen
Erfahrungen ziemlich "wurscht" in welchem Abstand die Inpulse kommen,
lediglich deren korrekte Länge wird ausgewertet (und bis zu einer
Änderung auch gehalten).
Da hat nie irgendwas gezuckt oder gerüttelt, wollte ich nochmal
wiederholen, trotz der Tatasache, dass ich beide (Micro-) Servos aus der
gemeinsamen USB-Versorgung des Arduino mitversorgt habe.
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang