Arduino, Frequenz mittels Encoder einstellen und ausgeben.

  • Hallo Kai,

    ich möchte für dieses Projekt ein Platinenlayout erstellen. Die Schaltung in #48 wird noch um ein solid state Relais für die 230V Spannungsversorgung des Luftkompressor und die Ansteuerung über Pin 13 erweitert. Ich muss noch eine möglichst kleine 12V Spannungsversorgung 2-3A für die Ansteuerung des Magnetventil finden. Das 16 x 2 LCD Display, grün mit schwarzer Schrift, ist furchtbar schlecht ablesbar. Hier möchte ich auch noch was ändern.

    Das Gehäuse für die Steuerung wird aus 6mm HPL gefertigt. Aus HPL sind fast alle meine Projekte gefertigt. HPL ist Witterungs- und Feuchteunempfindlich, stabil wie Alu. HPL wird häufig bei Fassadenverkleidungen und Balkonverkleidungen eingesetzt.


    In irgendeinen Thread von Dir hast Du fertige Platinen, hergestellt nach Deinen Layouts, auf Bildern gezeigt. Wo hast du die Platinen fertigen lassen?

    Oder ich muss die Platine im Frühjahr selber fräsen. Das habe ich aber bis heute noch nicht gemacht.

    Grüße, Franz

  • Hallo Kai.

    Ich habe noch 2 Arduino Nano mit Klemmenadapter bestellt. Für die Eieruhr und für dieses Projekt. Für die Eieruhr wäre evtl. ein Pro mini Arduino wegen des Stromverbrauchs besser geeignet. Heute sind für dieses Projekt die MOSFET (5 Stück Mindestbestellmenge) geliefert worden.

    Wenn die CAD Zeichnungen fertig sind und ich die Gehäuse gedruckt habe, werde ich die neue Software laden.

    An meinem Arduino Testboard habe ich die Hardware von diesem Projekt entfernt und nur noch die Eieruhr Hardware angeschlossen.

    Ich habe Deinen Beitrag erst jetzt gesehen.


    Ich wünsche Dir und allen hier im Forum ein schönes Weihnachtsfest.


    Grüße, Franz

  • @Franz: Nachdem Du in dem anderen Thread zur Eieruhr geschrieben hast, dass Du Schwierigkeiten mit dem Verständnis der Funktion askRotaryEncoder() hast, habe ich mir den Code noch einmal angeschaut.


    Dabei ist mir aufgefallen, dass er doch noch etwas gekürzt und vereinfacht werden kann. Die Merkervariablen data.pos sowie data.newPos  sind überflüssig (Da sieht man was passiert, wenn man ohne zu überlegen, Codeteile aus einem anderen Projekt übernimmt).


    Die Merkervariablen können aus der Struktur EncoderData entfernt werden. Die Initialisierung von EncoderData encData muss dann aber angepasst werden.



    Vielleicht ist die Funktion jetzt auch verständlicher. Es wird lediglich immer die Drehrichtung des Encoders angefragt. Und je nach, durch den Tasterdruck eingestellten Eingabestatus (InputState), wird entweder die Hertz-Zahl oder das Tastverhältnis verändert.


    Ich habe den Code bei der Simulation auf Wokwi angepasst. Über den Link in Beitrag #35 kommst Du dahin. Bei dem "Eieruhr Beispiel" im anderen Thread habe ich das inzwischen auch geändert.

  • Scheint OK, allerdings würde ich den 10K Pulldown (R1) Widerstand links vom R2 anschließen. Sonst hast Du einen Spannungsteiler aus 220Ω und 10KΩ.


    Das macht zwar wegen des beträchtlichen Größenunterschieds nur etwas 0,1V aus... aber trotzdem ;).

  • Reden wir jetzt von Transitoren (BJTs, stromgesteuert) oder von MOS-Fets (spannungsgesteuert?


    Wenn von MOS-Fet, dann wäre dieser hier wohl für viele Anwendungsfälle und eine LOW Side Schaltung geeignet: IRLZ44N


    Ich weiß nicht wie genau Du da baust, aber hier sind einige Schaltvarianten mit MOS-Fets und eine Angabe von geeigneten Typen (Logic Level MOS-Fets) die auch mit 5V Gate-Spannung betrieben werden können:


    B9BB18A8-DA6A-4C90-B1F2-00E7A95C5C52.jpeg


    Variante eins (oben links), dürfte die gebräuchlichste sein.

  • Kai, Du hast recht.

    Ich habe ohne zu rechnen und zu überlegen einfach so geschrieben. Richtig ist 12 Schaltungen in 1000 ms.

    Richtig ist, z.B. Das Ventil soll in einer Sekunde 12mal schalten. 12Hz =1000mS / 12 = 83 ms . Das Ventil ist dann 12 mal 41,5 ms angesteuert, bei einem Tastverhältnis von 50%.

    Der Widerstand der Spule ist 12 Ohm.

    Ich denke, der Leistungstransistor sollte schon ca.35V abkönnen.

    Einen Schaltplan habe ich nicht gezeichnet.

  • Hast Du einen Schaltplan?


    https://www.electronics-tutori…/mosfet-als-schalter.html


    Wenn es so geschaltet ist wie im verlinkten Text in der Abbildung unter der Überschrift "Ein Beispiel für die Verwendung des MOSFETs als Schalter", verstehe ich nicht, warum eine Freilaufdiode am Einspritzventil die Schaltzeit des MOS-Fets beeinträchtigen sollte.


    Da ist eher die Kapazität zwischen Gate uns Source ein Faktor, welcher das Schaltverhalten des FETs beeinflusst. Aber da musst Du dir bei max. 15 Hz sicher keine Gedanken machen.


    Wenn die induktive Spannung der Spule beim Abschalten über der Spannungsverträglichkeit des MOS-Fets liegt, dann wird er das nicht lange aushalten.


    Wie kommst Du auf 12 Schaltungen pro 100ms? Das sind doch eher 120Hz, was immer noch nicht besonders viel ist.

  • Ich habe mal eine Aufnahme für ein 12V Einspritzventil gedruckt. An klemme 9 wird das Gate eines Mosfet angeschlossen, der das Ventil ansteuern soll. Zum Schutz des Mosfet müsste eine Freilaufdiode parallel zur Einspritzventilspule verdrahtet werden. Ich habe aber die Befürchtung, dass sich die dann die Schaltzeiten verändern werden. Irgendwo habe ich gelesen, dass es Mosfet Transistoren gibt, die eine hohe Spannung, erzeugt beim schalten einer Induktivität, abkönnen. Oder gibt es andere Möglichkeiten?

    Ein Relais würde z.B. 12 Schaltungen in 100mS nicht lange mitmachen.


    003.JPG006.JPG

  • Danke für Deine Hinweise.

    Die Pin 13 Zeile war nur ein Beispiel. Pin 13 benötige ich aber noch, weil ein Luftkompressor mit einem solid state relais bei Start des Programm eingeschaltet werden soll.

  • Die Fortsetzung in C++ ist die Gleiche wie in Deinem Code:


    C
    1. constexpr byte pin_led {13};
    2. [...]
    3. pinMode(pin_led, OUTPUT);
    4. digitalWrite(pin_led, HIGH);


    Ob das jetzt PIN_LED, led_pin oder ledPin oder pinLed heißt ist ja erst einmal wurscht. Variablen- Konstanten-Namen sind frei wählbar.

    Allerdings gibt es gewisse allgemein anerkannte Regeln, wie die Benamung erfolgen sollte: https://luna.informatik.uni-mainz.de/eis2021/codingstyle.md


    Was der Vorteil von constexpr und die Definition mit {} ist, haben andere schon aufgeschrieben, darum verlinke ich mal hierhin.


    Auf der verlinkten Seite steht ein Satz "Es ist immer besser, wenn man so programmiert, dass schon der Compiler unsinnigen Code erkennt."

    und constexpr ist ein großer Schritt dahin.


    Das mag bei einem 20ig Zeiler trivial klingen, aber wenn die Programme größer werden, in viele Module aufgeteilt, mehrere 100 oder mehrere 1000 Zeilen Code, da wird das immer wichtiger. Darum sollte man sich gewisse Dinge gleich angewöhnen, auch wenn es am Anfang vielleicht nicht notwendig erscheint. Aber wenn die Projekte größer werden es ist schwerer sich umzugewöhnen als wenn es von Anfang an "richtig" gemacht wird.


    Im Internet schreibt sehr oft einer vom andern ab. Darum sind viele Beispiele für z.B. Arduino einfach nur schlecht bzw. bleiben weit hinter den Möglichkeiten der Sprache zurück.


    Eine sehr gute Seite, aber leider nur in englisch: CPP Core Guidelines


    Im aktuellen Code kann die von Dir angesprochene Zeile mit dem Pin13 aber gelöscht werden, weil er nicht mehr verwendet wird. Da habe ich bei der Änderung des Codes die überflüssige Zeile übersehen. Die LED wird ja über den Timer1 an Pin9 angesteuert.

  • Hallo Kai,

    die Arduino Pin Definition z.B. für Pin 13 wie ich sie kenne



    Code
    1. # define LED_PIN 13
    2. // und weiter
    3. pinMode(LED_PIN, OUTPUT);
    4. digitalWrite(LED_PIN, HIGH);
    5. //In deinem Code in C++,
    6. constexpr byte pin_led {13};
    7. //wie ist jetzt die Fortsetzung in C++ und welche Vorteile hat die Codeänderung?
  • Ich finde es toll, dass Du das noch so machst. Darum habe dann doch noch weiter geholfen, obwohl ich eigentlich den Ball ganz an Dich abgeben und die Speichergeschichte nicht mehr "abhandeln" wollte. Wenn Du Verständnisfragen zum Code hast, kann ich auch versuchen etwas zu erklären.


    Ich habe halt eine Erfahrung geschildert, die ich auch in diesem Forum gemacht habe. Da lässt die Lust etwas nach, behilflich zu sein.


    Ansonsten, ist meine kleine Button Bibliothek inzwischen auch direkt über die Bibliotheksverwaltung der Arduino IDE installierbar:


    Arduino_SC4.jpg        Arduino_SC5.jpg



    Allerdings musst Du dann die #include Anweisung von #include "Button.hpp" in #include <Button_SL.hpp> ändern.

    Sollte es da mal ein Update geben, bekommst Du das dann automatisch mitgeteilt.

  • Ich kann deine Argumente gut nachvollziehen und gebe dir in allem Recht. Eigentlich wollte ich Dir deshalb auch nicht antworten.

    Aber ich muss an dieser Stelle für mich sprechen weil man das, was du schreibst, nicht verallgemeinern kann.

    Ich beschäftige mich jetzt im hohen Alter mit Modellbau, mit dem Bau einer Portalfräse, eines 3D Drucker und 3 D -Scanner und zwangsläufig auch ein wenig mit CAD Programmen und Programmierung, weil ich in meinem Berufsleben plus große Familie und Haus u. Garten für solche Dinge keine Zeit hatte. In der Hauptsache mache ich das weil mir die Dinge Spaß machen und damit der Kopf nicht einschläft. Das ist und war evtl. alles etwas zu viel. Aber ich meine immer, mir läuft die Zeit davon und ich müsste alles schnell noch nachholen. Ich wollte noch eine neue Fräse bauen, aber das habe ich auch aus Kostengründen schon aufgegeben. Jetzt beschränke ich mich nur noch auf die Verbesserung und Optimierung meiner früher fertig gestellten und sehr gut funktionierenden Projekte, für die ich mir auch eine Menge an Wissen aneignen musste, was als Einzelkämpfer viel Zeit in Anspruch nahm. Hier haben mir User aus guten Foren und Videos sehr geholfen, weil alles neu für mich war. Die Videos von René habe ich mir fast alle einmal angesehen. Gerne hätte ich mich tiefer in die Programmierung eingearbeitet, aber dann hätte ich die anderen Dinge vernachlässigen müssen.

    Ich bin jedenfalls nicht diesem sehr guten Forum beigetreten, in der Hoffnung, andere User schreiben mir Programme, sondern weil ich die Videos von René gesehen habe und auf dieses Forum hingewiesen wurde. Ich hätte auch weiter dieses Forum besucht, wenn keiner geholfen hätte.

    Eigentlich gehört mein jetziger Beitrag auch nicht in ein Elektroniker Forum.

    Kay, gäbe es nicht Leute mit der Geduld und Hilfsbereitschaft wie die von René und dir, gäbe es auch keine gute Foren.

  • Wenn mich das Thema nicht interessiert hätte, hätte ich das nicht gemacht. Ich hoffe wir bekommen von Deinem Projekt hier noch etwas zu lesen oder sogar sehen. Was den "Expertencode" angeht, ist in der Hauptsache nur das angewendet worden, was René in seinen Videos gezeigt hat.


    Ich kann nur immer wieder die sehr guten Videos von René empfehlen, in denen er die Grundlagen der objektorientierten Programmierung erklärt. Dazu noch seine Erklärungen zu der Programmierung einer "State Machine" und etwas nachlesen über den (Aufzählungs-)Datentyp "enum" und man hat im Wesentlichen die Erklärung für Funktionsweise des Codes in diesem Projekt.


    Im Detail gibt es einige C++ Elemente, die in gängigen Beispielprogrammen i.d.R. nicht verwendet werden. Darum sieht das Ganze wahrscheinlich mehr "expertenmäßig" aus, als es in Wirklichkeit ist. Evtl. verwirrt, dass Variablen mit "{}" und nicht mit "=" definiert werden. Hier wird aber eine klare Unterscheidung zwischen der Definition einer Variable mit einem Initialwert und einer Zuweisung eines Wertes zu einer Variablen getroffen. Halt C++ und nicht C.


    Ich bin aber selber noch am lernen. Auch dieses Projekt war für mich eine Übung. Wirkliche Experten werden da sicher auch noch andere und evtl. elegantere Wege finden. Es gibt da immer etwas zu verbessern. Die Hauptsache ist immer noch, dass der Code in den Speicher passt und dass er mögl. fehlerfrei macht was er soll.


    Anscheinend schrecken aber viele vor der Mühe zurück, sich von der Struktur der üblichen Beispielprogramme zu lösen und programmieren lieber elende, am Ende kaum überschaubare IF/THEN/ ELSE Würste in einer aufgeblasenen loop() Funktion. So sehe ich das oft (auch in Arduino Forum). Man möchte was mit Arduino machen, kopiert sich die Codeteile aus dem Internet zusammen und dann funktioniert es nicht, weil gar nicht verstanden wird, wie die Dinge zusammenhängen. Dokumentation suchen und lesen ist anstrengend und mühsam.


    Darum wird sich in einem Forum angemeldet, gruselig zusammengestuppelter Codeschrott in den Thread gekippt und irgend ein "Dappes" programmiert es dem Fragenden dann schon zurecht. Das Projekt läuft am Ende. Und weil das so gut geklappt hat kümmert man sich wieder nicht darum, was man da eigentlich für ein Stück Code hat und wie das funktioniert. Das ist dann ein sog. "Maker".


    Üblicherweise werden die Fragenden dann auch nie, oder bis zum nächsten Problem nicht mehr wiedergesehen. Der Fragende hat ja was er wollte.


    Also eigentlich muss man schon ein ziemlicher "Idiot" sein, sich in einem Forum zu engagieren. Darum hoffe ich, dass es bei Dir anders ist ;).

  • Hallo Kai, ich weiß nicht , was ich sagen soll? Danke für deine nicht selbstverständliche Hilfsbereitschaft und damit verbundene Mühe und Geduld.

    Ich habe nicht gedacht, dass aus meiner Frage und Anliegen bei der Threaderstellung, so ein mächtiges Programm wird. Es ist jedoch sehr deprimierend für mich, dass ich deinen Expertencode überhaupt nicht verstehe. Was du wahrscheinlich wiederum nicht verstehen kannst. In den nächsten Wintermonaten versuche ich das etwas zu ändern. Dein lächelnder Smile zeigt hoffentlich, dass es dir auch ein wenig Spaß gemacht hat.


    Jetzt versuche ich mal die 3 Dateien als Projekt zusammenzufassen und in die Arduino IDE einzuspielen.


    Ein schönes Wochenende

    Franz

  • Teckelfreund: Nach Deiner PM habe ich mich noch einmal an den Code begeben und eine Speicherfunktion eingebaut. Ich habe es so gemacht, wie in #33 beschrieben. Ein kurzer Tastendruck schaltet zwischen den Einstellungen Hertz, Tastverhältnis und Speichern durch.


    Der Modus "Speichern" wird durch ein S in der zweiten Zeile angezeigt. Drückt man den Encoder-Button eine Sekunde lang, werden die auf dem Display angezeigten Werte im EEPROM dauerhaft gespeichert.


    Arduino-SC-3.jpg


    Das S verschwindet. Ansonsten hat sich an der Benutzung nichts geändert. Der Code wurde um einen Input Status, einen Programm Status und zwei Funktionen erweitert.


    Das Auslesen des Speichers erfolgt in der setup() Routine, das Speichern der Daten im Bereich der Tasterabfrage. Das erste Zeichen das geschrieben wird (@) dient nur dazu festzustellen, ob überhaupt jemals etwas im EEPROM gespeichert wurde. Ist das nicht der Fall sollte der Speicher normalerweise mit dem Wert 0xFF beschrieben sein. Wurde nie etwas gespeichert, werden Defaultwerte verwendet und in den Speicher geschrieben, andernfalls die gespeichert Werte ausgelesen.


    Vielleicht kann man das eleganter lösen, aber so funktioniert es zumindest.



    Am einfachsten wird es wohl sein, die zwei folgenden Dateien als zusätzliche Tabs in der IDE zu speichern.


    Arduino-SC-2.jpg


    Die PwmTimer1 Klasse (Headerdatei)



    Und die entsprechende C++ Datei


    Das soll es dann aber gewesen sein. Weitere Features musst Du selber einbauen :) .


    Hier noch der Link zur Simulation: https://wokwi.com/projects/349326402260042322


    Das Speichern kann man testen, indem man auf dem Nano Board auf die Reset Taste klickt (der kleine dickere graue Knopf etwa in der Mitte des Boards).

    Es wird ein Neustart des Controllers simuliert. Es sollten im Anschluss die Einstellungen angezeigt werden, die zuletzt gespeichert wurden.

  • Moin Franz,


    zu 1. Es ist ein R&S RTB2004. Also Hardware. Kein Softwareoszi.


    zu 2. Die zwei Werte können im EEPROM gespeichert werden.

    Hier steht wie es geht: https://docs.arduino.cc/learn/built-in-libraries/eeprom. Falls es mit dem Englisch hapert, Deepl ist eine sehr gute übersetzungsmaschine.


    Tipp: Verwende EEPROM.put zum Schreiben.

    Dann werden die Daten nur geschrieben, wenn sie ungleich zu den gespeicherten Werten sind.


    Für die Eingabe kann beim Wechsel zwischen Hertz und Tastverhältnis noch ein dritter Status zum Sichern der eingestellten Werte eingeführt werden. Dann wird nicht bei jeder Wertänderung in das EEPROM geschrieben.


    Z.B. ist der Status auf hertz oder duty startet ein langer Tastendruck die Frequenzausgabe. Beim noch einzuführenden Status Sichern, wird bei einem langen Tastendruck gespeichert. Ist nur so eine Idee wie man es machen könnte.


    Das Gerüst ist ja schon da.


    Wofür brauchst Du das überhaupt? Ein „Frequenzgemerator“ bis 15Hz ist ja schon etwas ungewöhnlich.