da ich nur hin und wieder den Arduino für meine Bastelprojekte nutze muss ich mal wieder eine triviale frage Stellen.
Für meine kleine China-Drehbank habe ich ein Messsystem auf der Basis des rotary sensors MLX90316BDG von Melexis gebaut, was per Arduino ausgelesen wird. Die Ausgabe erfolgt über ein LCD-Display per I2C. Das Ganze funktioniert auf die hundertstel Stelle genau (so genau schafft nicht mal die China-Drehe…)
Frage:
Da der Sensor sehr schnell misst ist es wichtig möglichst wenig Zeit für die Werteausgabe auf das Display zu verschwenden.
Was ist also schneller, einzelne Werte und Zeichen jeweils direkt per „lcd.print()“ an das Display senden, oder zuvor die Zeichen und Werte in einem string zusammenfassen und diesen dann mit nur einem „lcd.print(myString)“ an das Display su senden?
ja verstehe ich, aber mir geht es nicht um die Schnelligkeit der Anzeige.
In einem Früheren Projekt mit dem MLX habe ich festgestellt, dass der Sensor durch die Serielle Übertragung bei schnellerer Rotation mal ein par Grad verschluckt. Das kann man zwar rausrechnen, doch bei Richtungswechsel führt das zu ungenauigkeiten.
Mir geht es deshalb darum die Serielle Übertragung möglichst kurz zu halten.
Deshalb die Frage, mehrere einzelne "LCD.print()"-Befehle oder einen mit zuvor im einem String zusammengefassten Zeichen und Werten?
Ich kenne nun diesen Sensor nicht, aber wird er nicht per Interrupt ausgelesen?
Du könntest natürlich versuchen, nicht alle Zeichen auf einmal auf das Display auszugeben, sondern alle paar Millisekunden nur eines oder zwei. Das Auge macht dann keinen Unterschied.
Aber der Loop wird eben nicht so lange blockiert, sozusagen.
So mache ich das mit Temperatursensoren, der war auch nur einer alle paar Millisekunden ausgelesen, Bis dann alle fünf durch sind.
Auch solltest du nur die veränderten Zeichen auf das Display schreiben, und nicht jedes Mal die gesamte Zeile
Darüber findet man auch etwas (wenig) hier im Forum.
Das funktioniert sehr gut aber wie gesagt, um so mehr serielle Übertragung, um so mehr kleine Störungen.
Der Hinweis von EIEspanol hat mich dazu inspiriert das Display nur alle 70 loop-Durchläufe zu aktulisieren. Das stabilisiert schon sehr gut. (Die "70" sind hier nur der erste Test, kann sicher noch erhöht weren bis es sich auf die Anzeige auswirkt.)
Auch wenn ich damit das Problem lösen konnte, rein theoretisch interessiert mich immer noch was schneller ist, mehrere kurze "print" -Befehle oder einen mit größerem String?
der Sensor durch die Serielle Übertragung bei schnellerer Rotation mal ein par Grad verschluckt
Dein Link führt auf eine MLX90316 Library, die nur die Methode readAngle() kennt. Die entweder einen Fehler oder einen Zehntelgrad (0 .. 3600) Wert per SPI-ähnlichem Protokoll (nur 1 Datenleitung für beide Richtungen) empfängt und zurückliefert.
Wie können da auf der Arduino-Seite ein paar Grad verschluckt werden ?
Nochmal: write ist etwas schneller als print. Aber da geht es um Mikrosekunden.
Auch wenn mir unklar ist, was das mit deinem Problem zu tun haben könnte, kannst du versuchen, während eines readAngle() - Aufrufs nichts im Hintergrund laufen zu lassen (mal noInterrupts() ausprobieren, ob da z.B. alles incl. millis() ausser Tritt gerät )
Oder je loop-Durchlauf max 1 Zeichen per write an das LCD zu senden und den Puffer selber verwalten.
(Schau dir arduiniana.org/libraries/pstring/ an)
Hallo,
Habe mich wohl etwas unklar ausgedrückt. Der Sensor gerät nicht „außer Tritt“, vielmehr überspringt er einige Gradmessungen, wenn seriell übertragen wird. Das ist eigentlich egal, da der nächste Wert ja ein absoluter Winkel ist und somit den aktuellen Stand wiedergibt.
Problematisch ist es nur wenn der Übersprung von 3600 auf 1 (360 auf 1 Grad bzw. 1 auf 360 Grad) erfolgt oder die Änderung der Drehrichtung. Das wird benötigt um die „Runden“ zu zählen. Das ginge sicher auch per Programm, aber als Gelegenheits-Arduinonutzer sind meine Fähigkeiten begrenzt und ich möcht ich den Aufwand gering halten.
Bei meiner Drehmaschine ist z.B. eine Spindelumdrehung = 1 mm Vorschub.
Dieses hier geschilderte Problem tritt jedoch nur bei zu schneller Spindelumdrehung auf und durch die o.g. Reduzierung der Ausgabe an das Display jetzt gelöst.
Aufgefallen ist mir dieser Effekt übrigens schon in einem älteren Projekt. Dort wird ein Eigenbau - Selonoid- MotorMotor durch einen Arduino mit dem hier genannten Sensor gesteuert. Der Motor läuft wie am Schnürchen, wenn ich jedoch zur Justierung ein Display anschließe (oder per serial.read den Monitor) läuft der Motor merklich langsamer und unrund.
Zusätzlich zur genannten Lösung werde ich jetzt auch noch nointerrupts() ausprobieren.
Danke an alle für die Hilfe!
michael_x:
Wie können da auf der Arduino-Seite ein paar Grad verschluckt werden ?
Ich denke, es geht einfach um die Schnelligkeit der Abfrage. Jede Abfrage von readAngle() gibt die Momentanposition zurück. Wenn man nicht oft genug abfragt, Hat sich die Drehbank evtl. und mehrere Grad weitergedreht, bis der nächste Wert abgefragt wird. Und wenn dazwischen eine Drehumkehr war, kann man den genauen Umkehrpunkt eben nicht bestimmen. Da das ganze nicht interruptgesteuert ist, sondern eigentlich ein einfaches Pollen ist, bleibt also nur, readAngle() oft genug aufzurufen.
Da die wire Lib für die Ansteuerung des LCD blockierend ist, bleibt wohl nur - wie Michael schrieb - die Zeichen ans LCD selbst einzeln auszugeben und dazwischen immer wieder den Angle auszulesen.
Die Methode, das LCD nur alle z.B. 70 Durchläufe zu aktualisieren schützt auch nicht davor, dass man dann genau in dem Moment evtl. was verliert.
Edit: Sehe gerade, dass Klaus es noch genauer beschrieben hat. Scheint aber zu meinem oben geschriebenen zu passen. nointerrupts() wird aber nichts helfen, da hier gar nichts mit Interrupts läuft.
also wie schon festgestellt wurde bringt noIntrrups() nichts und ich habe das wieder rausgenommen. Ist aber trotzdem eine Option, sollte ich über den Arduino auch noch die Drehzahlmessung der Spindel implementieren (mit Hallsensor). Bin mir da nicht sicher, da ich dann ein größeres Display brauchte. Vermutlich werde ich dafür einen eigenen Kontroller mit einzeiligem Display einsetzen – wird auch übersichtlicher beim Ablesen.
Zurück MLX-Sensor.
Das Prinzip der Messung hat Franz-Peter ja nochmal sehr gut zusammengefasst.
Habe noch ein bisschen mit dem Testaufbau rumgespielt und bin soweit zufrieden. Da dieser Aufbau ziemlich klapprig ist, muss ich das jetzt an der Maschine testen, wo der Rundlauf und die Ausrichtung zum Magnet ohne Spiel sehr präzise ist. Dadurch erhoffe ich mir eine weitere Verbesserung.
Im Testaufbau ist jetzt die Fehlerquote bei Überlauf von 1 auf 3600 (und Revers) bei langsamer gleichmäßiger Umdrehung der Achse (ca. eine Umdrehung pro Sekunde) dauerhaft 0 %. Nur bei schnellerem Drehen gibt es ab und an einen Aussetzer beim Überlauf.
Werde hierfür noch etwas am Programm rumschrauben. Ansatz ist das Fenster der Erfassung der Gradzahlen bei einem Überlauf zu erweitern, bisher geschieht das nur auf eine Messwerterfassung bezogen. Wie aber schon gesagt, erhoffe mir besonders durch den mechanisch exakten Einbau weitere Verbesserung - sprich exakte Ergebnisse auch beim schnelleren Kurbeln am Querschlitten.
Egal wie du es machst, es kommt haupsächlich darauf an, wieviele Zeichen in einem Loop Durchlauf geschickt werden.
Es sollte besser sein, alle 7 loops 2 Zeichen zu schicken als alle 70 loops 20
Hallo,
nochmals Danke für die Unterstützung.
Um hier möglicherweise bestehende Missverständnisse auszuräumen nochmal ein kurze Erklärung. Die Trägheit der Anzeige stellt kein Problem dar. Wenn es darum geht den Drehmeißel auf ein Hundertstel genau einzustellen kurbelt man auch nur sehr langsam und schaut genau auf das Dislpay. Also Displayablesen und Auswerten stellen überhaupt kein Problem dar
Hier mal eine Skizze zur Funktion und dem mechanischem Aufbau der Messeinrichtung:
KLAPPT NICHT MIT DEM EINSTELLEN DER SKIZZE - DACHTE MAN KANN HIER BILDER DIREKT HOCHLADEN...
Das Messkabel (geschirmt) hat im Versuchsaufbau ca. 1 m Länge, wird aber im eigentlichen Betrieb ca. 60 bis max. 70 cm lang sein.
Das Programm habe ich nun so umgestellt, dass im normalen Messbetrieb nur max. 6 Zeichen alle 60 loop-Durchläufe an das Display gesendet werden. Damit sind die Problem gelöst und der jetzt folgende feste Anbau an die Drehbank wird durch die dann auch vorhandene Präzision der Sensorpositionierung und einem gleichmäßigem Drehverhalten der Kurbelspindel eine verlässliches Arbeiten damit ermöglichen.
Wenn Interesse besteht kann ich ja über Erfolg oder Misserfolg des Einbaus berichten.
Nächstes Projekt wird dann der Einbau eines gleichartigen Messsystem am Kreuztisch meiner Fräse, da werden jedoch zwei Achsen (x und z) ausgemessen…
Um die Sache mit ein paar Zahlen zu unterlegen:
Deine 6 Zeichen brauchen mit Cursor setzen 8060 uS, davon Cursor setzen ca. 900 uS
Ein Zeichen ohne Cursor setzen auch ca. 900 uS
Wenn du also mit einem endlichen Automaten (mit switch case), der alle x loops ausgeführt wird, folgendes machst:
Cursor positionieren
Eine Stelle aufs LCD
Cursor positionieren
Eine Stelle aufs LCD
Cursor positionieren
Eine Stelle aufs LCD
....
wenn alle 6 geschrieben sind, den Automaten zurücksetzen. U.U. brauchst du ja nicht mal immer den Cursor positionieren.
d.h., dein Sketch wird alle z.B. 10 Loops für nur 900 uS fürs LCD unterbrochen. Das ist auf alle Fälle besser, als alle 70 Loops für 8060 uS zu unterbrechen
habe Deinen Beispielsketch eben laufen lassen (musste nur die Adresse und Zeilenzahl des LCDs anpassen).
Was Du schreibst bestätigt sich natürlich. Bei mir (Nano) wird für ein Zeichen ohne Cursor setzen 1464 uS gemessen.
Habe jetzt erst mal die Anzeige so geändert, dass ich fast ohne cursor-setzen auskomme.
Deinen Vorschlag nur einzelne Zeichen zu schreiben ist sichtlich nochmal schneller als meine derzeitigen max. 6.
Danke für die guten Tipps.
Ich denke ich werde bis zum kommenden Wochenende das Messsystem installiert haben. Bis dahin müssen noch einige zusätzliche Funktionen eingebaut werden (Wert halten, zurücksetzen, Differenzwert und Differenz * 2). Das und die Ausgabe der Werte ist jedoch nicht zeitkritisch, da diese Berechnungen per Taster ausgelöst werden wenn die Kurbelspindel eh still steht.
Wenn das erledigt ist werde ich mich mit der von Dir genannten Variante der einzelnen Zeichenübergabe alle 10 Durchläufe befassen.
mit der Positionsanzeige an meiner Drehmaschine möchte ich mich ev. demnächst auch beschäftigen.
Deine Erfassung der Spindelposition hat, mbMn nach, ein Problem:
Eine Trapezspindel (wie sie an handbedienten Hobbymaschinen üblicherweise verwendet wird) ist nie ganz spielfrei und so wird die Positionserfassung des Schlittens ungenau. Alle, mir bisher bekannten, Verfahren werten die Position des Schlittens direkt aus. (z.B. Messchieber) Damit fällt das Spindelspiel als Fehlerquelle aus.
ja, das Spindelspiel ist bei diesem Messprinzip das Problem.
Da ich je erst frühestens am Wochenende dazu komme das Messsystem an die Drehe anzubauen und im Echtbetrieb zu testen habe ich zwei bisher nur theoretische Ansätze das Problem anzugehen..
Innerhalb des Programmdurchlaufs wird erfasst ob ein Drehrichtungswechsel der Spindel erfolgt. Trifft das zu, dann wird das (zuvor ausgemessene) Spindelspiel rausgerechnet. Im Versuch klappt das erst einmal gut, weiteres muss die Praxis zeigen.
Sollte der erste Ansatz nicht zielführend sein, bleibt noch die manuelle Kontrolle. Ähnlich wie auch beim Ablesen des Skalenrings auf der Spindel könnte man bei Drehrichtungswechsel die Messung per Taster stoppen bis das Spiel überwunden ist und der Schlitten wieder bewegt wird.
Das mit den einzelnen geht noch einfacher mit dem loopzähler
ungetestet, pseudocode:
uint16_t loops, freq=10;
.....
void loop(){
if loops==freq{
lcd.print....
}
if loops==2*freq{
lcd.print....
}
if loops==3*freq{
lcd.print....
}
if loops==4*freq{
lcd.print....
}
if loops==5*freq{
lcd.print....
}
if loops==6*freq{
lcd.print....
loops=0;
}
loops++;
......
}
Mit der freq kannst du dann austesten, alle wieviele Loops du die Ausgaben schreiben musst, damit die Anzeige flüssig genug läuft. Kommt eben auf die Looptime an.
das sieht ja nochmal um Einiges einfacher aus und ist überschaubar im Block für die Zeichenausgabe einzubasteln.
Werde das bestimmt so übernehmen und anpassen.