Arduino C++ Nachkommastellen sammeln und verrechnen.

  • Es entstehen nie zu viele oder zu wenig K-zähne weil sie nicht von den Rundungsfehlern abhängen, sondern nur vom errechneten Gesamtfehler. Das habe ich ja versucht zu erklären. Die Nachkommastellen haben lediglich Einfluss auf den Abstand von den Korrekturzähnen. Diese Nachkommastellen verteilen sich aber auf den Gesamtumfang. darum gibt es beispielsweise mal zwei Regelzähne einen Korrekturzahn, drei Regelzähne einen Korrekturzahn dann wieder zwei Regelzähne oder es gibt 3,3,4 er Gruppen usw.


    Wenn Du dir das Programm mal anschaust, wirst du nicht eine double oder float Variable finden. Es werden nur (gerundete) Ganzzahlen verwendet. Das Aufrechnen von Nachkommastellen macht das Ganze nur unnötig kompliziert.,


    Ich habe es jetzt nicht getestet, aber das Programm wird auch bis 500 Zähne funktionieren.

  • Das Problem ist, das die errechneten Abstände der Korrekturzähne auch wieder Nachkommastellen haben. Also muss man wieder auf- oder abrunden.

    Dadurch entsteht rechnerisch auch mal ein K-Zahn zu viel oder zu wenig. Praktisch will das Programm einen K-Zahn ausgeben, um auf die auf gerundete Anzahl zu kommen. der letzte Filter verhindert in meinem Programm den K-Zahn, wenn die noch nicht gemachten Stepps mit Regelzähnen genau passend ausgeführt werden können. So erhält man am Ende einen Regelzahn mehr, der aber immer noch in den 2 möglichen Abständen liegt. Also kein Ausreißer aus den vorgegebenen Regeln.

    Gestern habe ich das Programm mit bis zu 500 Zähnen getestet. Dabei habe ich plötzlich 9 Abstandsfehler erhalten, die nicht auftreten durften. Ich habe aber schnell festgestellt, dass es nur bei Zahnrädern war, wo der Zähnezahlen ohne Korrektur aufgingen. und die Zähnezahlen über 250 waren.

    Daraufhin habe ich meine Min-Max-Zähler für den Abstand von int auf double umgestellt. Da gab es einen Überlauf, der nicht vorkommen sollte.

    Das Programm hatte ich schon mal bis 360 Zähne getestet, aber da gab es diese Min-Max-Zähler noch nicht.


    Hans

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Nach meinem Verständnis ist der ganze Sermon ist doch gar nicht nötig, weil die Werte rechnerisch ermittelt werden. Somit müssen die Korrekturzähne pro Zahnrad immer eine identische Größe haben, sie können nicht direkt aufeinander folgen. Der Korrekturwert für einen Korrekturzahn ist im Beispielprogramm fest auf einen Step eingestellt. Es wird entweder -1 oder -(-1) gerechnet. Je nachdem ob der Gesamtfehler positiv (zu viele Steps) oder negativ (zu wenig Steps) ist. Aus dem Gesamtfehler ergibt sich die Aufteilung über den Kreisumfang aufgrund der Gesamtsteps.


    Das heißt, wenn ich ein Zahnrad habe, dessen Berechnung am Ende beispielsweise 20 Steps zu viel ergibt, müssen diese überzählige Steps gleichmäßig über den Kreisumfang abgezogen werden um am Ende auf die Gesamtstepzahl, die richtige Anzahl Zähne und eine mögl. gute Symmetrie zu kommen. Es ergibt sich ja schon aus der Rechnung Gesamtstepzahl / 20, wieviele Steps zwischen zwei Korrekturzähnen liegen müssen um diese gleichmäßig aufzuteilen. Ergibt die Berechnung zu wenig Steps, gilt das Gleiche nur dass dann ein Korrekturzahn einen ( -(-1) )Step mehr als ein Regelzahn hat


    Darum passt am Ende auch immer die Gesamtstepzahl. Das lässt sich ja auch am Wert (Step pro Zahn) bei der Programmausgabe ablesen. Da kann es gar keine Überläufe oder so etwas geben.


    Naja … lassen wir es dabei. Kann ja durchaus sein, dass da noch einige Aspekte sind, die ich nicht kapiere, aber ich baue das Ding ja auch nicht :). Ich habe hier nur versucht zu erklären, welcher Algorithmus hinter dem Beispielprogramm steckt.

  • Hallo Kai,

    es war klar, dass Du es kannst.

    Dein neues Programm habe ich mal laufen lassen, und auf den ersten Blick keinen Fehler erkannt.

    Deine Beschreibung: "Es gibt nie mehr als einen Stepp-Differenz zwischen zwei aufeinanderfolgenden Zähnen." ist etwas vage.

    Deshalb habe ich hier nochmal die "Bilanz" von meinem Programm bei Zahnrad = 10 -140 Zähne hineinkopiert:

    Die oberste Zeile ist noch vom 140er Zahnrad, SpaceMax= 2 und SpaceMin= 1 gibt die Max und Min Abstände der Korrekturzähne wieder. Die Differenz darf nie mehr als 1 Zahn betragen, sonst wird für die Bilanz ein Abstandsfehler registriert. Ich kann nicht sehen, ob dein Programm pro Zahnrad auch immer nur eine Größe Korrekturzahn verwendet.

    Um das nicht im Ausgabetext genau suchen zu müssen, habe ich in mein Programm die Bilanz eingebaut.

    Der Zähler-Überlauf tritt ein, wenn vom Rhythmus her ein Korrekturzahn folgen soll, aber von den restlichen Stepps zur vollen Drehung kein Stepp mehr berichtigt werden muss/darf. Das darf auch nur beim letzten Zahn vorkommen, weil sonst der Abstand "SpaceMax : SpaceMin" > 1 wird.

    Der verhinderte Korrekturzahn wird natürlich auch als Regelzahn ausgegeben und so in der Bilanz erfasst. Der Überlauf hat also keinen negativen Einfluss auf die Berechnung, sondern erfasst nur, wie oft ein Korrekturzahn zu viel verhindert wurde.

    Wie schon gesagt, es ist nur ein Prüfprogramm für alle möglichen Zahnräder, damit sicher ist, dass nachher im Programm für einzeln ausgewählte Zahnräder kein Fehler vorkommen kann. Dann ist es immer noch nicht für die Tonne, denn man kann damit auch andere "Hardware (Motorsteppzahlen und Getriebeübersetzungen testen.


    Hans

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Ich habe heute auf der Terrasse beim relaxen nochmal das Programm welches ich seinerzeit als Beispiel unten verlinkt habe angefasst eine kleine Änderung vorgenommen und es so programmiert, dass immer mit einem Korrekturzahn angefangen wird. Diese werden gleichmäßig auf eine komplette Drehung verteilt. Es gibt nie mehr als einen Step-Differenz zwischen zwei aufeinanderfolgenden Zähnen. Die Gesamt-Stepzahl von 2048000 Steps wird immer erreicht. Nie unter- oder überschritten.


    Die Verteilung entspricht dem, was Dein Programmcode auch so "ausspuckt".


    https://wokwi.com/projects/333730702599127635

  • Hallo Arduinofreunde,

    Mit dem Berechnungsprogramm für definierte Teilschritte von einer Drehbewegung bin ich soweit fertig und das mathematische Ergebnis kann sich mit der Hardware nicht mehr verbessern. Der Programmcode ich nach meinem Wissensstand recht einfach gestrickt, und es gibt noch Routinen, die mehrfach im Code stehen, weil ich noch nie Funktionen programmiert habe. Außerdem ist die Ausgabe schlecht formatiert.

    Jetzt habe ich noch ein paar Ereigniszähler eingebaut, damit ich am Ende eine Bilanz habe. Dur Änderungen der Bilanz erkennt man schnell, wenn eine Änderung nicht alle möglichen Eventualitäten berücksichtigt.

    Das Programm teilt die Stepps einer Umdrehung gleichmäßig auf den Umfang eines zu fertigenden Zahnrads auf. Da es kein halben oder andere Teilzähne gibt, muss man überzählige oder unverbrauchte Stepps so gleichmäßig wie möglich auf den ganzen Zahnkranz verteilen. Mein Programm kommt mit 2 Schrittweiten für die Zähne aus, und die Verteilung der korrigierenden Zähne ist auch sehr gleichmäßig, wenn auch nicht absolut symmetrisch.

    Für die Zähler habe ich im Verhältnis zu eigentlichen Programm viel Code gebraucht. Ich hatte auch länger gebraucht, um den Zähler für die minimalen Abstände zu realisieren. Es gibt ja Zahnräder, wo die Stepps in den Zähnen glatt aufgehen, dann bekommt man einen minimalen Abstand von 0 Zähnen heraus. die Differenz zwischen der maximalen Zähneanzahl und Null ergibt dann einen sehr großen Fehler.

    Hier nun der aktuelle, funktionierende Stand.

    Hans

    Teilungsberechnung-zahnrad12.ino.ino

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Alles richtig, was Du schreibst, von deinem Programm bin ich begeistert und kann sicherlich viel daraus lernen.

    Ein Regelzahn ist ein normaler, berechneter Zahn mit auf ganze Stepps gerundeter SteppAnzahl. Ein Korrekturzahn ist ein Zahn mit einem Stepp mehr oder weniger als ein Regelzahn. Alle Korrekturzähne sind gleich und sollen so gleichmäßig wie möglich auf dem Umfang des Zahnrads verteilt werden. Da die Anzahl der Korrekturzähne sich nicht immer ganz gleichmäßig zwischen den Regelzähnen verteilen lässt, versuche ich, die Abstände auf 2 Schrittweiten einzuhalten, die ebenfalls nur um einen Zahn differieren. Trotzdem sollen die notwendigen Stepps immer auf 2048000 Stepps enden. Bisher habe ich in meiner letzten Version keine größeren Abweichungen in der Verteilung festgestellt. Letztendlich werde ich die größten und kleinsten Abstände der Korrekturzähne vom Programm selbst erfassen und vergleichen lassen. An der Bilanz arbeite ich bereits mit 7 Zählern.


    Ein Zahnrad ist doch rund, und die letzten Zähne schließen doch in der Praxis an die ersten Zähne wieder an. Wenn man jetzt vorne zB. 5 Regelzähne hat, und hinten ebenfalls 5 Regelzähne bekommt man am Umfang eine Strecke von 10 Regelzähnen, die weit von den berechneten Abständen der Korrekturzähne abweicht.


    Meine Konstruktion ist ein Teilapparat mit Getriebe 40:1, Handkurbelantrieb und wird normalerweise mit festen Lochscheiben positioniert. Genauer geht es mechanisch, wenn man zusätzlich die Lochscheiben mit einem weiteren Getriebe feinverstellen kann. Professionelle Teilapparate haben Getriebe mit Übersetzungen von 90:1 oder 120:1. Mein Teilapparat sieht so aus: Bild Teilapparat Es ist nicht der Gleiche, aber auf diesem Bild sieht man den Aufbau gut und kann sich die Funktion leicht vorstellen. Mit der Kurbel verdreht man über das 40:1 Getriebe das Futter und kann mit der Kurbel ebenfalls eine Stift in der fest montierten Lochscheibe einrasten. Drei Lochscheiben mit insgesamt 21 Lochkreisen habe ich auch. Dazu verwendet man eine Exeltabelle, die für jede Winkelteilung die beste Lochscheibe, die Schrittweite und die Abweichung anzeigt.


    Angeblich kann man mit Hobbyelektronik die Genauigkeit wie mit einem mechanischen Zusatzgetriebe, dass die Lochscheibe feinjustiert nicht erreichen. Genau Das möchte ich mit meinem Close-Loop Steppermotor NEMA23, einem preiswerten Steppertreiber und dem Arduino erreichen. Mit dem Steppermotor statt der Handkurbel macht ein Stepp etwa eine halbe Winkelsekunde aus. Das ist auch der Bereich, den man mit der Mechanik einstellen kann. Nur wird die Mechanik mehr aufsummierte mechanische Toleranzen haben als die Elektronik.

    Falls mir die Auflösung noch nicht ausreicht, kann ich ein weiteres Getriebe an den Nema23 bauen. Die bezahlbaren Getriebe gibt es von 3:1 bis 100:1. Damit kann ich dann den Zahlenbereich des Arduinos sprengen.


    Schönen Abend und nochmals vielen Dank für deine Hilfe


    Hans

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Hallo Hans,


    Ich bin lediglich davon ausgegangen, dass es notwendig ist, die Brüche gleichmäßig auf eine komplette Drehung zu verteilen. Die zweite Annahme war, dass für jeden Zahn des Zahnrades eine bestimmte Stepanzahl notwendig ist und dass es nichts ausmacht, wenn bei einem Zahn ein Step mehr oder weniger erfolgt.


    Da ich Deine Konstruktion aber nicht kenne, sagt mir das nichts, was ein "Regelzahn" und was ein "Korrekturzahn" ist. Ist aber auch egal.

    Du hast ja anscheinend was gefunden das passt.

  • Nachtrag:

    Hallo Kai,

    deine Ausgabe sieht auf den ersten Blick s u p e r aus.

    Mr. Monk wäre aber mit der Berechnung nicht zufrieden.

    Du hast den gleichen Fehler wie ich anfangs gemacht.

    Wenn Korrekturzähne erforderlich sind, dann musst Du mit einem Korrekturzahn beginnen. Wenn Du das nicht machst, summieren sich die Regelzähne am Anfang und am Ende zu einer übergroßen Lücke zwischen den Korrekturzähnen.

    Deswegen habe ich in meinen Code 2x eine "erster Zahn Behandlung" eingebaut. :-)


    Hans

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Danke Kai.

    Den Code werde ich sicher ausprobieren und versuchen zu verstehen. Toll, dass Du sogar ein ganzes Brogramm geschrieben hast. Ich habe dazu fast 3 Wochen gebraucht.

    Gestern Abend habe ich das Auf und Abrunden gedanklich durchgespielt. In der Nacht konnte ich nicht schlafen und habe den Code geschrieben. Das Programm hat aber noch gehumpelt.

    Heute Morgen habe ich dann gesehen, dass ich den neuen Code nicht an allen notwendigen Stellen eingefügt hatte.

    Jetzt läuft die Aufteilung so gleichmäßig dass sogar Mr. Monk zufrieden wäre. Ich habe es sogar bis 360 Zähne getestet. Es juckt mir in den Fingern, noch ein paar Zähler für die besonderen Ereignisse zu installieren und am Ende eine Statistik auszugeben.

    Den jeweiligen Datensatz am Kopf möchte ich noch etwas formatieren und unnötige Ausgaben entfernen.

    Die K+ und V+ werde ich nur auskommentieren, damit sie bei Bedarf wieder aktiviert werden können.

    Die Zahn-Nrs. möchte ich auch gleich lang machen und die Nachkommanullen bei den Stepps sollen auch weg. Die Stepps passen aber nur in double. und da muss ich wohl einen String draus machen und kürzen.

    Danke nochmals für deine tatkräftige Unterstützung.


    Hans

    Teilungsberechnung-zahnrad10.ino

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Hans:

    Ich habe hier mal einen Code geschrieben, den Du ausprobieren kannst. Hier werden die Korrekturschritte (sofern sie nötig sind) gleichmäßig auf die Gesamtschrittmenge verteilt:


    Du kannst den Code auch hier gleich online ausprobieren: Programmsimmulator. Einfach auf den grünen Button klicken und damit die Simulation starten.

    Die Textausgabe erfolgt wie gewohnt auf einer "seriellen Konsole". Es werden Schritte und Ausgleichsschritte pro Zahn eines Zahnrades angezeigt.

    Der Trick ist, nicht mit einzelnen Brüchen zu arbeiten, sondern mit "Gesamtschrittzahl / Fehler" die Spanne zu ermitteln zu der jeweils ein Korrekturschritt eingefügt oder abgezogen werden muss.


    Ist der Fehler ( zahnrad.stepsProZahn * zahnrad.zaehne - zahnrad.gesamtSteps ) negativ (es werden zu wenig Schritte/Zahnrad gemacht) wird einfach das Vorzeichen des Korrekturwertes beim initialisieren herumgedreht. So bleibt die Rechenvorschrift immer gleich und es muss keine Fallunterscheidung bei der laufenden Berechnung erfolgen.

  • Ich demonstriere mit dem Beispielcode lediglich, wie die Nachkommawerte von drei Bruchzahlen die in einem Array gespeichert sind aufaddiert werden.

    Damit werden die Funktionen "double nachkommateil(double)" und "double modf(double,*double)" vorgestellt. Mehr ist das nicht.

  • Vielen Dank Kai.

    So ganz verstehe ich Deinen Code noch nicht, und habe ihn auch noch nicht ausprobiert.

    Nachdem ich 14 Tage an der gleichmäßigen Verteilung erfolglos herumgetüftelt habe, hatte ich gestern Abend vor dem TV eine neue Idee. Da ich ha schon mit dem mathematisch berechneten Abstand und dem Abstand in natürlicher Schrittzahl gearbeitet habe, brauche ich doch nur die Ganzzahl von der Kommazahl abziehen und bekomme als Resultat die gesuchte Differenz.

    Die Differenz bei jedem Korrekturzahn nach dem ersten nächsten Korrekturzahnin einen Speicher summieren und mit >=1 vergleichen ist einfach.

    Jetzt habe ich den letzten Korrekturzahn vor dem Ereignis gesucht, an dieser Stelle den Abstand zum nächsten Korrekturzahn um 1 erhöht. Dadurch kommt der nächste Korrekturzahn 1 Zahn später. Mit dem nächsten Korrekturzahn im vergrößerten Abstand werden dann die hier verwendeten Counter, Umstellungen und Merker aktualisiert, bzw. resettet. So funktioniert die Korrektur erst einmal leidlich, nachdem ich keine Merkereinstellung mehr in die Rechnung für das nächste Zahnrad verschleppe.

    Den Überlauf-Filter, der vor zu vielen Korrekturzähnen schützt brauche ich noch, und der spuckt mir bei den letzten Abschnitten manchmal auch noch in die Suppe. Ich habe bei der Sichtung der Ausgabe noch ein paar optimierbare Verteilungen gefunden. Noch habe ich nicht alle Zahlenreihen gesichtet, aber bei Reihen gefällt mir die Ausgabe noch nicht. Das Problem immer auftritt wenn die Differenz > 0,5 liegt. Da muss ich in diesem Fall einfach aufrunden. Was wieder jeweils eine neue Routine zum verkürzen der Abstände erfordert. Dann sollte das Programm alle Zahnräder gleichmäßig berechnen.


    Hans

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)

  • Variante 1 ohne spezielle Bibliotheksfunktion:

    Funktioniert aber nur bei "Vorkommazahlen" von -32768 bis 32767


    Variante 2 mit Bibliotheksfunktion

  • Ich möchte einen Drehtisch zur Anfertigung von Zahnrädern mit einem Steppermotor jeweils genau einen Zahn weiterdrehen.

    Der Tisch hat eine Getriebeübersetzung von 40:1 und der Steppertreiber ist auf 51200 Microschritte eingestellt. Das macht 2048000 Stepps für eine Tischumdrehung.

    Die Zahnräder sollen von 10 bis 140 Zähne erhalten können. Den Steppertreiber steuert ein Arduino Uno direkt an, dieser Teil funktioniert schon gut. Später sollen die jeweiligen Zähnezahlen über ein Keypad eingegeben, und auf einen LCD-Display angezeigt werden. Dieser Teil ist noch nicht fertig, aber ich habe schon getestet, wie man das Keypad abfragt und das Display ansteuern muss.

    Dazwischen habe ich ein Rechenprogramm, um die Motorstepps zu berechnen. Das Grundprogramm habe ich schnell entwickelt, und es würde auch ausreichend genau mit um ein Stepp variierenden Korrekturzähnen rechnen und immer auf die 204800 Schritte pro Umdrehung abschließen. Mein Luxusproblem ist nun, dass es mir nicht gelungen ist, diese Korrekturzähne geleichmäßig auf dem Umfang des Zahnrads zu verteilen.


    Mein Problem stellt sich zum Beispiel so da:

    Für ein Zahnrad mit 140 Zähnen errechnet das Programm für einen Regelzahn 14629 Microstepps. Daraus ergeben sich 60 Microstepps pro Tischumdrehung zu viel. Deshalb muss ich 60 Korrekturzähne mit einem Stepp weniger einfügen um die überzähligen Stepps zu verhindern. Rechnerisch ergibt das nach 2,33 Zähnen einen Korrekturzahn. Praktisch muss ich aber abrunden und komme mit einem Abstand von 2 Zähnen bereits beim Zahn Nr .120 auf die 60 Korrekturzähne. Deshalb habe ich vor die Ausgabe eines Korrekturzahnes eine Prüfung eingebaut, um eine zu große Anzahl von Korrekturzähnen zu verhindern. Als Resultat habe ich so einen Abschnitt, mit dicht folgenden Korrekturzähnen und einen Endbereich von 21 Zähnen ohne Korrektur.

    Bei anderen Zähnezahlen sieht es teilweise viel schlimmer aus.

    Die Berechnung soll für alle Zähnezahlen passen, wobei mir klar ist, dass dass es nicht immer mit einer gleichmäßigen Korrektur der vorhandenen Korrektur ausgehen wird. Allerdings möchte ich dass ich mit 2 Zähnezahlen mit einem Unterschied von einem Stepp auskomme und es auch nur 2 unterschiedliche Abstände der Korrekturzähne mit einem Zahn Unterschied gibt. Wobei der letzte Abschnitt nicht immer in dieses Schema passen muss. Das müsste mit der Einrechnung der Nachkommastellen zu lösen sein.


    Deshalb möchte ich die Nachkommastellen vom errechneten Zahnabstand sammeln, addieren und beim erreichen/überschreiten von 1,00 den Abstand um ein Zahn vergrößern, und mit dem Rest der Summe wieder eine neue Addition beginnen. So müsste ich jeweils nach 3 Korrekturzähnen im Abstand von 2 Zähnen den 4. Korrekturzahn im Abstand von 3 Zähnen erhalten.

    Leider weis ich nicht, wie ich die Nachkommastellen mit dem Arduino abtrennen und zur Weiterverarbeitung nutzen kann.


    Mein Testprogramm, dass alle Berechnungen von 10 - 140 Zähnen pro Rad in einer Schleife auf dem Monitor ausgibt, habe ich angehängt.


    Bleibt noch zu erklären, dass es sich um ein reines Hobbyprojekt geht. Zahnrad Rohlinge bekommt man zum Preis vom Rohmaterial und muss nur die Breite und die Achsbohrung individuell anpassen. Ich möchte aber in der Lage sein, spezielle Zahnräder die nicht im Handel erhältlich sind, mit meiner Fräsmaschine zu fertigen. Spezielle Werkzeuge um Zahnräder zu fräsen besitze ich nicht. Ich habe ein Buch über "Gears and Gear Cutting" und möchte sehen, dass die Theorie mit einem Schrittmotor präzise umzusetzen ist.


    Teilingsberechnung-zahnrad7.ino

    Wenn ich Schuhe und Strümpfe ausziehe, kann ich bis 20 zählen. ;)