Hallo, ich benutze in meiner Schaltung zwei Nema17 Schrittmotoren, einen Arduino Nano und einen HC_SR04 Ultraschallsensor. Das Prinzip meiner Schaltung ist etwas gleichmäßig aufwickeln zu können. Das funktioniert auch sehr gut, bis auf ein kleines Problem. In meinem Programmcode im loop messe ich alle 5 Sekunden den Abstand zu meinem Objekt, um den Füllstand zu überprüfen. Diesen gemessenen Abstand rechne ich danach noch um und dann wird das Menü auf meinem LCD aktualisiert. Das Problem ist alle 5 Sekunden stoppen meine Schrittmotoren ganz kurz und laufen danach wieder normal weiter. Ich würde mich freuen wenn mir jemand helfen kann. Wenn ihr noch zusätzliche Informationen benötigt fragt gerne nach. Grüße.
Kenobi Wan O. schrieb: > Das Problem > ist alle 5 Sekunden stoppen meine Schrittmotoren ganz kurz und laufen > danach wieder normal weiter. Mach mal ein Foto von den Motoren. Die sind sicherlich schon etwas älter und müssen alle 5 s Luft holen.
Und zwar in der Ultraschall Messung, die blockiert für einige zig Millisekunden. Messung und SM Ansteuerung müssen parallel laufen.
J. S. schrieb: > Und zwar in der Ultraschall Messung Das ist landläufig die Zeile 42 im Programm ....
Kenobi Wan O. schrieb: > Wenn ihr noch zusätzliche Informationen benötigt fragt > gerne nach. Folgende Frage: ist der Programmcode geheim?
Wenn sich der nano gerade mit etwas anderem beschäftigen muss, hat er für die Motoren kurzfristig keine Zeit..
Beitrag #7773123 wurde vom Autor gelöscht.
Ralf X. schrieb: > Wenn sich der nano gerade mit etwas anderem beschäftigen muss, hat er > für die Motoren kurzfristig keine Zeit. ist ja nicht falsch, aber oft kann man es so programmieren das BEIDES klappt. z.B. entprelle ich alle 10ms Tasten, dort setze ich sofort ein Flag: "bin_im_timer_IRQ", der gesamte Code dauert so um 4-10µs, d.h. ich bin danach wieder raus aus der Entprellung icncl. Flag wieder löschen, dann habe ich noch einen Interrupt für IRMP alle 64µs, bin ich im 10ms TIMER_IRQ gebe ich den IRMP_Infrarot_IRQ frei und der wird im 10ms TIMER_IRQ mit bearbeitet. Man braucht es nur geschickt schachteln und darauf achten das sie sich nicht gegenseitig blockieren. Ich wüsste jetzt nicht warum das hier nicht auch klappen sollte, so eine PWM muß ja nicht mit MHz laufen und bei 5s sollte der Ultraschallsensor auch schnell abgearbeit sein, muß ja nicht blockierend sein.
Kenobi Wan O. schrieb: > Das Problem ist alle 5 Sekunden stoppen meine Schrittmotoren ganz kurz > und laufen danach wieder normal weiter. Das ist doch ein perfekter Ansatzpunkt. Überlege dir, welche Routine alle 5s die Aktualisierung der Schrittmotoren blockiert. Du möchtest mehrere Dinge quasi gleichzeitig tun, also musst du verhindern, dass sie sich zu lange gegenseitig blockieren.
Joachim B. schrieb: > Ich wüsste jetzt nicht warum das hier nicht auch klappen sollte, Weil bei Arduino-Code meistens nichts parallel ablaufen kann. Alles schön sequentiell ohne Interrupts und meist auch nur zusammengeklickt.
Joachim B. schrieb: > Ralf X. schrieb: >> Wenn sich der nano gerade mit etwas anderem beschäftigen muss, hat er >> für die Motoren kurzfristig keine Zeit. > > ist ja nicht falsch, aber oft kann man es so programmieren das BEIDES > klappt. Ich sehe mich in dem Bereich noch als "Anfänger", aber weiss auch, dass unausgereifter Code eben ungewollte Auswirkungen haben kann. Hätte ich so einen Effekt wie Kenobi und sehe den Fehler im Code nicht, würde ich als ersten mal schauen, was der serielle Monitor da (mit timestemp) anzeigt.
Nema17 ist übrigens keine Bezeichnung für einen konkreten Motor, sondern für dessen Befestigung. So wie die E27 Glühbirne.
// Messung durchführen (nicht blockierend) unsigned int distanceInCm = sonar.ping_cm(); // Messung in cm Sicher nicht blockierend? Sonst im Code alle Delays entfernen und mit state machines ersetzen. Bzw durch interrupts.
Manchmal bringt schon ein Aufruf von yield() die Dinge voran. Wenn alle kooperieren, klappt es auch mit den parallelen Abläufen.
Andras H. schrieb: > // Messung durchführen (nicht blockierend) > unsigned int distanceInCm = sonar.ping_cm(); // Messung in cm > > Sicher nicht blockierend? Sicher blockierend ... Andras H. schrieb: > Sonst im Code alle Delays entfernen und mit state machines ersetzen. Bzw > durch interrupts. Ja. Und den Schrittmotor per Hardware-PWM takten. Wäre ein Wunder wenn der Code nicht stottert.
Kenobi Wan O. schrieb: > Das ist er. Naja. Der Ansatz für Multitasking ist ja schon da, zumindest in der loop(). Aber da geht es schon los! m_previousMillis wird in measuring() geschrieben, das ist Unfug. Das gehört in loop(). Vor allem, weil measuring noch mehrfach woanders aufgerufen wird! Die Funktionen measuring(), calculations() und drawMenu() sind OK, die laufen durch ohne zu warten. windingcontrol() auch. Dort ist auch die Handhabung previousSec1 = currentSec1 korrekt. Du hast mehrfach delay(1) im Programm, das ist eher unkritisch, denn das ist nur 1ms. Allerdings sind deine Funktionen readRotaryEncoder() und encoderChanged() vollkommen überladen und machen nicht das, was der Name sagt! Schlechter Stil! Strukturierte Programmierung auf Mikrocontrollern Auf die Schnelle sehe ich keinen gravierenden Fehler und die Ursache der Aussetzer. 8-0
Kenobi Wan O. schrieb: > In meinem Programmcode > messe ich alle 5 Sekunden den Abstand zu meinem Objekt.. > alle 5 Sekunden stoppen meine Schrittmotoren ganz kurz... Sieht jemand irgendeinen Zusammenhang..?
Stephan schrieb: > Andras H. schrieb: >> // Messung durchführen (nicht blockierend) >> unsigned int distanceInCm = sonar.ping_cm(); // Messung in cm >> >> Sicher nicht blockierend? > > Sicher blockierend ... Aber wie lange? Das ist ein Ultraschallsensor
1 | // ---------------------------------------------------------------------------
|
2 | // Standard ping methods
|
3 | // ---------------------------------------------------------------------------
|
4 | |
5 | unsigned int NewPing::ping(unsigned int max_cm_distance) { |
6 | if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance. |
7 | |
8 | if (!ping_trigger()) return NO_ECHO; // Trigger a ping, if it returns false, return NO_ECHO to the calling function. |
9 | |
10 | #if URM37_ENABLED == true
|
11 | #if DO_BITWISE == true
|
12 | while (!(*_echoInput & _echoBit)) // Wait for the ping echo. |
13 | #else
|
14 | while (!digitalRead(_echoPin)) // Wait for the ping echo. |
15 | #endif
|
16 | if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. |
17 | #else
|
18 | #if DO_BITWISE == true
|
19 | while (*_echoInput & _echoBit) // Wait for the ping echo. |
20 | #else
|
21 | while (digitalRead(_echoPin)) // Wait for the ping echo. |
22 | #endif
|
23 | if (micros() > _max_time) return NO_ECHO; // Stop the loop and return NO_ECHO (false) if we're beyond the set maximum distance. |
24 | #endif
|
25 | |
26 | return (micros() - (_max_time - _maxEchoTime) - PING_OVERHEAD); // Calculate ping time, include overhead. |
27 | }
|
> > Andras H. schrieb: >> Sonst im Code alle Delays entfernen und mit state machines ersetzen. Bzw >> durch interrupts. > > Ja. > Und den Schrittmotor per Hardware-PWM takten. Ist nebensächlich. Die Delays sind sehr kurz, 1ms und nicht für die PWM sondern die Schrittsteuerung! > Wäre ein Wunder wenn der Code nicht stottert.
Falk B. schrieb: > Ist nebensächlich. Die Delays sind sehr kurz, 1ms und nicht für die PWM > sondern die Schrittsteuerung! Ist denn für jede Messung ein Treffer garantiert? Innerhalb von so ca. (Schätzung aus dem Arm geschüttelt) 2ms pro 30cm? Oder gibt's bei Fehlmessungen auch mal ein Timeout?
Kenobi Wan O. schrieb: > Ich würde mich freuen wenn mir jemand helfen kann. Bist du stolzer Besitzer eines Logikanalysators (< 10€ reicht) oder eines Oszilloskops?
:
Bearbeitet durch User
unsigned int distanceInCm = sonar.ping_cm(); // Messung in cm Das funktioniert so? Da fehlt der Parameter für die max. Distanz in cm.
Norbert schrieb: > Ist denn für jede Messung ein Treffer garantiert? > Innerhalb von so ca. (Schätzung aus dem Arm geschüttelt) 2ms pro 30cm? Schallgeschwindigkeit ist 330m/s = 330mm/ms. Für Hin und zurück stimmt es. > Oder gibt's bei Fehlmessungen auch mal ein Timeout? Die werden über eine maximale Distanz abgefangen.
Das Auswerten des Drehgebers ist auch Unfug. https://docs.wokwi.com/parts/wokwi-ky-040/ Nein, so nicht. Siehe Drehgeber. Das geht auch mit Arduino, wenn man es oft genug aufruft bzw. gleich einen Interrupt nutzt. Beitrag "Drehgeber und Tastenentprellung für Arduino"
Zum eigentlichen Problem. Wenn all 5s was gemessen wird und alle 5s der Motoren kurz stoppen, wird es wohl damit zusammen hängen. Mein heißester Kandidat ist die sonar-Messung, bei welcher der Parameter der Maximaldistanz fehlt. Es kann aber auch die unsinnige Zuweisung von m_previousMillis = m_currentMillis; in measuring() sein. Das alles kann man einfach testen. 1. measuring() einfach mal in loop() auskommentieren. 2. Die Zuweisung von m_previousMillis in loop machen.
1 | if (m_currentMillis - m_previousMillis >= 10000) { |
2 | m_previousMillis = m_currentMillis; |
3 | measuring(); //Methode für das Ausmessen der Entfernung zur Spule |
4 | calculations(); //Methode zum Umrechnen der Entfernung zum Durchmesser |
5 | drawMenu(); //Methode zum Aufrufen des Menüinhalts |
6 | }
|
Falk B. schrieb: > Die werden über eine maximale Distanz abgefangen. Bei 4 Metern (war der Wert den ich so auf die Schnelle gefunden habe) kämen da aber ordentlich Millisekunden zusammen. Und wenn's dann noch kalt und trocken ist… ;-)
man könnte die Zeit die in sonar verbracht wird auch einfach messen anstatt zu vermuten...
J. S. schrieb: > man könnte die Zeit die in sonar verbracht wird auch einfach > messen > anstatt zu vermuten... Wenn man das könnte, hätte die Eingangsfrage nicht gestellt werden müssen!
Falk B. schrieb: > Zum eigentlichen Problem. Wenn all 5s was gemessen wird und alle > 5s der > Motoren kurz stoppen, wird es wohl damit zusammen hängen. Mein heißester > Kandidat ist die sonar-Messung, Ich habe im Internet gesehen, dass ich mit der NewPing Libary da was machen kann, jedoch ist mir diese noch etwas fremd weshalb das ein Fehler sein kann. Sobald ich es ausprobieren kann schaue ich mal. bei welcher der Parameter der > Maximaldistanz fehlt. Es kann aber auch die unsinnige Zuweisung von > > m_previousMillis = m_currentMillis; > > in measuring() sein. Ich habe schon viel ausprobiert und du hast völlig recht, dass gehört da nicht hin. Löst das Problem aber auch nicht leider. > Das alles kann man einfach testen. > > 1. measuring() einfach mal in loop() auskommentieren. > 2. Die Zuweisung von m_previousMillis in loop machen. > if (m_currentMillis - m_previousMillis >= 10000) { > m_previousMillis = m_currentMillis; > measuring(); //Methode für das Ausmessen der Entfernung zur Spule > calculations(); //Methode zum Umrechnen der Entfernung zum > Durchmesser > drawMenu(); //Methode zum Aufrufen des Menüinhalts > } Danke für deine Ideen.
Rainer W. schrieb: > Kenobi Wan O. schrieb: >> Ich würde mich freuen wenn mir jemand helfen kann. > > Bist du stolzer Besitzer eines Logikanalysators (< 10€ reicht) oder > eines Oszilloskops? Ja aber nicht zuhause. Ich könnte erst im laufe der nächsten Woche dasd Oszilloskop anschließen :(
Kenobi Wan O. schrieb: >> Bist du stolzer Besitzer eines Logikanalysators (< 10€ reicht) oder >> eines Oszilloskops? > Ja aber nicht zuhause. Bis du da wieder ran kommst, könntest du in eigenes Werkzeug investieren, z.B. https://www.ebay.de/itm/126321121803
Ich glaube das Problem liegt in windingcontrol(). Dort wird ja, recht Arduino und Multitasking gerecht, im festen Zeitraster der Schrittmotor mit Pulsen versorgt.
1 | //Festlegung der Taktzeit für den Schrittmotor der Spule
|
2 | if (currentSec2 - previousSec2 >= pulsetime_reel) { |
3 | previousSec2 = currentSec2; |
4 | stepper2state = HIGH; |
5 | //Serial.print("pulsetime_reel: ");
|
6 | //Serial.println(pulsetime_reel);
|
7 | }
|
Wenn dann alle 5s die Ultraschallmessung mit relativ hohem Zeitbedarf da reinhaut, stottert der Motor natürlich kurz. Dagegen gibt es mehrere Maßnahmen. a) Schrittmotorpulse in einem Interrupt erzeugen, der kann die Ultraschallmessung unterbrechen, was aber zu Meßfehlern führt. b) Die Ultraschallmessung mit der Schritterzeugung synchronisieren. Sprich, mittels Signal (Variable) markieren, wann gerade ein Schritt erzeugt wurde. Wenn denn die Ultraschallmessung erfolgen soll, nur dann messen, wenn kurz vorher der Schritt gemcht wurde. Dann dann hat man für die Messung ein Zeitfenster bis zum nächsten Schritt. Das setzt aber voraus, daß die Messung immer kurz genug ist, um in das Fenster zu passen. c) Die Pulse für den Schrittmotor werden per PWM in Hardware erzeugt. Das läuft parallel zum Programmablauf und wird durch die Ultraschallmessung nicht gestört. Das meinte oben schon mal Stefan ich hab es wohl falsch verstanden. Er hatte wohl Recht. Beitrag "Re: Schrittmotoren stoppen kurz Arduino Nano"
:
Bearbeitet durch User
Wastl schrieb: > Folgende Frage: ist der Programmcode geheim? Kenobi Wan O. schrieb: > Das ist er. SCNR
Kenobi Wan O. schrieb: > HC_SR04 Ultraschallsensor Ich nutze den JSN-SR04T Ultraschallsensor (wasserdicht für 2,50€), der ist zwar die ersten etwa 20cm blind, aber wenn man R19 mit 47kOhm bestückt, dann sendet er die Entfernungsdaten über UART in Millimeter und das kann man per Interrupt erledigen. So braucht man nicht aktiv zu warten. JSN-SR04T Modul Modus bei Widerstandswert R19: - offen = Impuls / Echo (wie bei HC-SR04) - geschlossen => Text mit z.B. "Gap=1638mm" wird kontinuierlich gesendet // UART 9600 Baud 8 Datenbits, 1 Stoppbit , keine Parität ------ - einzelner Messwert: 27kOhm bis 85kOhm (47kOhm) Um die Messung auszulösen muss man zum Modul einfach irgend ein Zeichen senden. Resultat: FF 04 D4 D7 0xFF = Startzeichen 0x04D4 = 1236mm D7 = Summe - Kontinuierliche Messwerte: 85kOhm bis 172kOhm (120kOhm)
Falk B. schrieb: > Dagegen gibt es mehrere Maßnahmen. Und natürlich gibt es noch mehr: Die Pulsdauer von der US-Entfernungsmessung kann per Capture-Funktion vom Timer erfasst werden, ganz unabhängig von der Software und ohne irgendwen zu stören.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.