Go Down

Topic: Gerade Fehleranzahl erzeugt richtiges Ergebnis? (Read 133 times) previous topic - next topic

themanfrommoon

Quote
Wäre auch schön, wenn sowas zu Anfang kommt.
Denn wenn nichts angegeben ist, vermute ich und auch sicherlich die anderen, einen Standard Arduino.
Wie den UNO.
Das vergesse ich bisher leider meistens, da ich zu 99,9% immer einen ESP8266 einsetze.
Ich ahne auch immer nicht, das sowas überhaupt relevant sein könnte.
Das muss ich mir einfach noch mehr angewöhnen.


Okay, dann versuche ich noch einmal komplett zu erklären was ich vorhabe und was mein Programm bis hier her können soll. Bisher kann das Programm nur einen Teil von einem Gesamtprojekt.
Das Gesamtprojekt ist eine Bügelperlensortiermaschine die ich Just for fun für mich baue, um dabei etwas zu lernen und Spaß zu haben.
Dabei gibt es im groben ungefähr 3 unterschiedliche Einheiten, die verschiedene Aufgaben haben.
Angefangen hab ich mit der mittleren Einheit, der Farberkennung.
Zunächst beschäftige ich mich mit jedem Teil einzeln und wenn ich alle unter Kontrolle gebracht habe möchte ich alles zu dem einen Projekt zusammenführen.

In dieser Farberkennungseinheit geht es darum die Farbe einer Bügelperle zu bestimmen.
Die Hardware ist fertig und besteht aus einem mehrteiligen 3D gedruckten Gehäuse und Sensorrad mit 4 Mulden, einem Schrittmotor zum Antrieb und einem Magnetencoder zur Bestimmung der absoluten Position (innerhalb von 360°).

Der Schrittmotor treibt das Sensorrad mit den 4 Mulden an.
Diese Mulden nehmen jeweils genau eine Bügelperle auf, fördern sie um 90° weiter, hier findet die Farberkennung statt, und wenn das Rad weiterdreht kann die Bügelperle wieder rausfallen.

Der Encoder dient vor allem dazu eine Blockade festzustellen und dann könnte der Schrittmotor nochmal versuchen die Blockade durch rütteln zu lösen.
Gelingt das nicht wird ein Fehler ausgegeben.


Der Schrittmotor soll dabei immer weiter in eine Richtung drehen, damit nicht unnötig viel Zeit verschwendet wird. Mein Ziel ist möglichst eine Zykluszeit von 1 Sekunde oder wenn möglich weniger, denn es werden später Größenordnung 14.000 Bügelperlen sortiert.

So, wie mache ich das jetzt? (das aufzuschreiben ist ja auch gute Rubberduckdebugging, also mache ich mir noch einmal komplett die ganze Mühe)

Der Encoder hat 4096 Positionen.
Der Stepper hat mit den momentanen Einstellungen 1/4 Mikroschritte (Microstepping = 4) und 200 Schritte pro Umdrehung (StepperStepsPerRevolution = 200).
Das Sketch berechnet daraus die Anzahl der nötigen Schritte für eine Umdrehung StepsPerRevolution = (StepperStepsPerRevolution * Microstepping) = 800.
Warum mache ich das so? Weil ich später den Treiber und oder die Mikroschritte noch ändern werde um hier die optimalen Einstellungen zu finden oder auch einfach nur um leicht verschiedene Einstellungen testen zu können.

Mit dem Encoder brauche ich keine Referenzfahrt und keinen Referenzschalter für den Schrittmotor, sondern weiss immer sofort und absolut wo das Sensorrad steht.
Da ich mit Hilfe des Encoders einen SOLL-IST Positionsabgleich fahren kann, kann ich so eine mögliche Blockade des Sensorrads erkennen und versuchen diese zu lösen oder einen Alarm ausgeben.
Ebenfalls kann ich durch den Encoder in der Software programmieren wo genau die Mulde im Sensorrad ist.
Diese Muldenpositionen werden später, wenn ich mit dem Farbsensor anfange, noch durch Versuche ermittelt. Mein Ziel sind hier die Muldenpositionen bei denen ich die besten Farbmesswerte erhalte. Möglicherweise werden später auch in einem gewissen Winkelbereich des Sensorrads mehrere Farbmessungen durchgeführt und der Wert gemittelt um die Farbe zu bestimmen. Das steht momentan noch nicht genau fest.

Die 4 Muldenpositionen werden in Pos[4] = {115, 1129, 2153, 3177}; festgelegt und beziehen sich auf das 4096er System des Encoders. Der Encoder ist fest mit den Mulden verbunden, daher erscheint mir diese Festlegung so besser als sie mit den Mikroschritten auf die Stepperpositionen umzurechnen und hier möglicherweise Fehler reinzukriegen.

Nun soll es also losgehen mit der Bewegung.
Leider steht der Stepper ja nach dem Einschalten und auch nachdem es eine Blockade gab 'irgendwo'.
Da dieser Teil von verschiedenen Teilen aus aufgerufen werden kann habe ich diesen in eine eigene Prozedur gesteckt, die ich StepperFindOrigin() nenne.

Nun habe ich festgestellt, das ich mit den absoluten Positionen nicht so viel anfangen kann, weil Accelstepper ja immer relative Positionen hochzählen möchte.
Also rechne ich die absoluten Positionen in relative Positionen um.
RelativeStep[0] ist also die Anzahl der Schritte zwischen Mulde 1 und 2.
RelativeStep[1] ist also die Anzahl der Schritte zwischen Mulde 2 und 3.
RelativeStep[2] ist also die Anzahl der Schritte zwischen Mulde 3 und 4.
RelativeStep[3] ist also die Anzahl der Schritte zwischen Mulde 4 und 1.
Als Prüfung (manuell geprüft, nicht im Programm) muss die Summe der 4 relativen Schritte wieder 800 Schritte für eine Umdrehung ergeben.
Das passte bisher auch immer. Bis hierher gibt es also keinen Fehler.

Nun muss das Sensorrad auf die nächste Muldenposition weitergedreht werden (nicht zurück!).
Die Startposition des Encoders wird ausgelesen.
Falls die Startposition des Encoders mit einer Muldenposition übereinstimmen sollte, dreht sich gar nichts. Das ist zwar relativ umwahrscheinlich, aber kommt dennoch öfters vor als ich gedacht hätte.
Dann wird geprüft ob die Muldenposition 0 - die Startposition vom Encoder größer Null ist. Wenn ja, wird genau um diese Differenz weitergedreht mit der folge, dass dann genau die 1. Mulde dort steht wo sie sein soll.
Falls nein, wird die nächste geprüft, usw.

Nun steht also eine Mulde genau dort von wo ich starten möchte.
Es gibt es einen Offset zwischen dem 4096er Encodersystem und dem 800ter Steppersystem.

Es wird also die Encoder Position ausgelesen, die Stepper Position wird ausgelesen und daraus der StepperOffset berechnet:
EncoderPos = encoder.getPosition();
StepperPos = stepper.currentPosition();
StepperOffset = EncoderPos - map(StepperPos, 1, StepsPerRevolution, 0, 4095);

(...jetzt beim Schreiben merke ich, dass ich anstatt des StepperOffsets auch einfach nur mit stepper.setCurrentPosition(0) die aktuelle Stepperposition nullen könnte. Das würde es wohl etwas vereinfachen. Merke ich mir mal.....)

Im Setup wird die Prozedur StepperFindOrigin() einmal augerufen.

Nun kommen wir zum Loop.
Da später viele Prozesse quasiparallel ablaufen werden, darf die Loop natürlich wie immer nicht blockieren.
Der Nachtwächter lässt grüßen und ich beginne die Loop mit currentMillis = millis();
Ich habe eine einfache Schrittkette (Merker "AlternateLoop") in deren ersten Zweig geprüft wird, ob der Stepper bereits am Ziel angekommen ist. Wenn ja, wird die Zeit gemerkt stepperMillis = currentMillis; und die Variable "n" (wird für das Array der relativenPositionen benutzt) um eins erhöht. Ebenfalls wird die Variable "TurnCount" (zählt wie viele Turns geschwenkt bzw. Bügelperlen gefördert wurden) um eins erhöht. Falls "n" > 3 ist werden von "n" wieder 4 abgezogen. "n" ist also immer im Wertebereich 0 bis 3. "AlternateLoop" wird auf false gesetzt, um im nächsten Loop Durchlauf den anderen Zweig anzufahren.
Wenn der Stepper noch nicht am Ziel angekommen ist wird geprüft, ob currentMillis - StepperMillis >= 500 ist. Es wird also in dieser Position 500ms gewartet. Hier soll später Prozedur der Farbmessung aufgerufen werden. Wenn ja, dann wird dem Stepper die nächste Zielposition gegeben. "AlternateLoop" wird wieder auf true gesetzt, um im nächsten Loop Durchlauf wieder den ersten Zweig anzufahren.
Der Stepper wird nun mit Stepper.run() angesprochen und darf also ein wenig laufen.
Nun wird mit (currentMillis - previousMillis >= PosMeasureInterval) geprüft, ob der 50ms SOLL-IST Abgleich Messzyklus erreicht ist. Wenn ja, werden die Encoderposition und Stepperposition eingelesen, und berechnet wie groß der Unterschied von beiden ist. Liegt der Unterschied unter oder über dem zulässigen Toleranzbereich, dann wird PosErrorCount um 1 erhöht.
Liegt der Unterschied innerhalb der zulässigen Toleranz, dann wird PosErrorCount wieder auf Null gesetzt.
So wird ausgeschlossen, dass bereits eine Fehlmessung oder ein Aussreisser ausreicht um die Fehlerprozedur aufzurufen.
Es sind mindestens 10 aufeinander folgende Fehler nötig um die Fehlerprozedur aufzurufen.

Wer bis hierher durchgehalten hat: Vielen Dank für das Interesse!

Ich vermute der Fehler liegt irgendwo in der Überprüfung der SOLL und IST Werte. Da werde ich nochmal weitersuchen müssen.

Lieben Gruß,
Chris


combie

Ah, ja...

Dein Sensorrad, ist also gar kein Sensor, sondern ein Aktor.
Da muss man auch erstmal drauf kommen.


Quote
Leider steht der Stepper ja nach dem Einschalten und auch nachdem es eine Blockade gab 'irgendwo'.
Da dieser Teil von verschiedenen Teilen aus aufgerufen werden kann habe ich diesen in eine eigene Prozedur gesteckt, die ich StepperFindOrigin() nenne.
Woher bekommt die Referenzfahrt ihre Referenz?

Klarer: Was kennzeichnet den Origin als einen besonderen Ort/Stellung?




> Das größte Problem, ist die Wahl der richtigen Gedanken <
Frei nach Dale Carnegie

Go Up