Weil es mir jetzt einfach keine Ruhe läßt. Es geht darum, dass ein
Lehrling, 2 Lehrjahr, Ausbildungsberuf Physiklaborant in der
Berufsschule die Aufgabenstellung hatten, mittels Arduino ein
Lauflichprogramm zu erstellen.
Die originale Aufgabenstellung habe ich gerade nicht parat, aber sie
mußten Arduino dafür verwenden, dürfen (weil wohl nicht besprochen
wurde) keine Interrupts verwenen und die LEDs sind über ein
Schieberegistermodul angeschlossen, für das sie eine Beschreibung
erhalten hatten und vorgestellt wurde, wie dem Schieberegister Werte
zugewiesen werden. Jetzt ist mein Lehrling - aus meiner Sicht der Dinge
- (weit) über dem, was ein 18-jähriger im 2. Lehrjahr können muß, er
interessiert sich hier sehr stark für Arduino und auch grundsätzlich
Mikrocontroller. Grundsätzlich erkennt man von seiner Art und Weise
schon auch meine Handschrift in der Programmierung wie ich ihm manche
Dinge gezeigt habe, bspw. das Zerlegen in kleine Funktionen und
insbesondere auch das Kommentieren des Codes.
Das Lauflicht sollte über einen Trimmer in der Ablaufgeschwindigkeit
geändert werden können und über einen 2 pol. Dipschalter 4 verschiede
Auswahlmuster wählbar sein.
Im Anhang könnt ihr sehen, was er in der Schule abgeliefert hat und ganz
ehrlich hat es mich "beeindruckt", wie er as gelöst hat (ich bin ganz
sicherich nicht mehr von einem LED-Laulicht beeindruckt).
Grundsätzlich hat er etwas gemacht, von dem er wahrscheinlich die
Fachbegriffe gar nicht kennt. Aus meiner Sicht der Dinge hat er so etwas
wie ein "event-pollinggetriebenes" Programm geschrieben, das aus Sicht
der I/O Devices (Trimmer, DIP-Schalter, LED) noch nicht einmal
blockierend ist. Änderungen am Trimmer oder eine Änderung an den
DIP-Schaltern erzeugen relativ unmittelbar Änderungen im Programmablauf.
Ich habe viele Lauflichtprogramme von Lehrlingen gesehen, aber das hier
ist mit Abstand das beste (für mich).
Mich würde jetzt echt interessieren, welche Note aus einer
"Lehrersichtweise" hier angemessen ist?
PS: natürlich werden jetzt wieder die ewigen Nörgler und Trolle
aufschlagen, aber auf eine neutrale, sachliche Aussage freue ich mich!
Ralph S. schrieb:> Mich würde jetzt echt interessieren, welche Note aus einer> "Lehrersichtweise" hier angemessen ist?
Die kommt auf die Aufgabenstellung, den Lehrstoff und die Erwartung des
Dozenten an.
Wenn die Erwartung (aka "Musterlösung") ge- oder übertroffen wurde,
sollte es eine 1 geben.
Ralph S. schrieb:> Physiklaborant
Erfordert der schon eine (Fach-) Hochschulreife?
Von den meisten meiner Mitschülern meine Berufschulklasse hätte ich man
sowas nicht bekommen.
Die Quellcode-Formatierung (inkl. Kommentare) finde ich vorbildlich,
nachdem ich schon von Quellcode von E-Technik-Mastern pflegen durfte,
die an sowas gar kein Interesse hatten.
Stefan S. schrieb:> Warum i+1? Denn so wird das erste Element (mit Index 0) nie angesprochen> und die Array-Grenze überschritten. Oder sehe ich da was falsch?
1
len = laufl_prog[0];
übersehen?
Da mit Pointern auf (unterschiedlich lange) Arrays gearbeitet wird,
braucht man die Längeninformation explizit.
Stefan S. schrieb:> Denn so wird das erste Element (mit Index 0) nie angesprochen
Dort wird die Länge herausgeholt:
1
len=laufl_prog[0];
> die Array-Grenze überschritten.
Nein, weil das Pascal-String-mäßig ja explizit über diesen Längeneintrag
an Index 0 abgehandelt wird.
Ralph S. schrieb:> Ich habe viele Lauflichtprogramme von Lehrlingen gesehen, aber das hier> ist mit Abstand das beste (für mich).
Sieht gut aus. Es wurden einige Gimmicks verwendet, die durchaus als
"fortgeschritten" eingestuft werden können.
Allerdings muss der Schreiber noch die "Potenz" aus dem Potentiometer
raushalten ;-)
- https://de.wikipedia.org/wiki/Potentiometer
Ahhhh Danke für die Korrektur!
Rahul D. schrieb:> Stefan S. schrieb:>> Warum i+1? Denn so wird das erste Element (mit Index 0) nie angesprochen>> und die Array-Grenze überschritten. Oder sehe ich da was falsch?> len = laufl_prog[0];> übersehen?
Tatsächlich übersehen! Danke!
Rahul D. schrieb:> Ralph S. schrieb:>> Physiklaborant> Erfordert der schon eine (Fach-) Hochschulreife?
erfordert "nur Realschulabschluß, obwohl dort einige Abiturienten und
Fachhochschulreife Auszubildende dabei sind.
Lothar M. schrieb:> Allerdings muss der Schreiber noch die "Potenz" aus dem Potentiometer> raushalten ;-)> - https://de.wikipedia.org/wiki/Potentiometer
Dass man "Potentiometer" jetzt mit "z" schreibt.... tut nicht nur dir
weh.
Diese Schularbeit wurde - mir komplett unverständlich - mit einer 3,2
bewertet und ich bin am Überlegen, ob ich da beim Lehrer "vorstellig"
werden sollte. Auch um dem Auszubildenden zu zeigen, dass ich nicht
hinter der Lehrerentscheidung stehe.
Nach meinen Kriterien hätte ich 1,5 gegeben ... auch wegen
"Flüchtigkeitsfehler" in den Kommentaren:
1
ADC / 3 = 341; 341 + maxspeed (40) = 381
2
3
Rueckgabewerte je nach Potenziometereinstellung 0..381
denn es hat eine Spannweite von 40..381, zudem ein Fehler eines
Funktionsprototypen:
Lothar M. schrieb:> Mich würde jetzt echt interessieren, welche Note aus einer> "Lehrersichtweise" hier angemessen ist?
Wie schon andere gesagt haben: Es kommt darauf an, was GENAU die Aufgabe
war und was gekonnt werden hätte sollen. Das ist also ein subjektiver
Maßstab, den können wir hier mangels Wissen nicht anlegen. Rein objektiv
wäre es für einen "richtigen" Programmierer Schulnote 4 minus -
vorausgesetzt, es läuft wenigstens richtig, was ich bezweifle.
Allerdings muss so ein Azubi nicht das können, was ein richtiger
Programmierer kann. Anders gesagt: Relativ gesehen mag dieser Azubi gut
sein, absolut gesehen ist er es nicht.
Nur ein paar Punkte:
Insbesondere die Routine polled_delay() ist misslungen: Es werden dort
zwei Dinge vermischt, und zwar so unübersichtlich, dass man nicht leicht
erkennen kann, was da bewirkt wird.
Der zweifache Aufruf von dipkey_get() (einer sichtbar in loop, einer
unsichtbar in loop) macht das dann noch schlimmer. Mag sein, dass es mit
diesem und anderen Tricks funktioniert, aber gut im Sinne einer sauberen
Programmierung ist das nicht. Es sind "schmutzige" Tricks.
Das Arduino-Paradigma (setup vs. loop) ist auch nicht eingehalten, die
Initialisierungen am Anfang von loop() gehören da nicht hin.
Zur Unübersichtlichkeit:
Deswegen ist es wohl auch passiert, dass der Programmierer selbst nicht
gemerkt hat, dass die Variablen dipkey_status zwar ausgelesen, ihr aber
im gesamten Programm nirgendwo ein Wert zugewiesen wird. Läuft das
Programm denn so überhaupt richtig?
Ralph S. schrieb:> Dass man "Potentiometer" jetzt mit "z" schreibt.... tut nicht nur dir> weh.
Das ist ein Fachwort und darf deshalb laut Duden weiterhin mit 't'
geschrieben werden. (Ich schreibe das auch mit 't'.)
Ralph S. schrieb:> Diese Schularbeit wurde - mir komplett unverständlich - mit einer 3,2> bewertet
Vielleicht weil die Urheberschaft der dafür genutzten KI nicht mit
angegeben wurde?
Ralph S. schrieb:> Dass man "Potentiometer" jetzt mit "z" schreibt.... tut nicht nur dir> weh.
Das macht man jetzt für die GenZ so.
Ralph S. schrieb:> Nach meinen Kriterien hätte ich 1,5 gegeben ... auch wegen> "Flüchtigkeitsfehler" in den Kommentaren:
Ich hatte den Quellcode nur überflogen und fand die Aufgabe gut (2)
gelöst.
Rolf schrieb:> Das Arduino-Paradigma (setup vs. loop) ist auch nicht eingehalten, die> Initialisierungen am Anfang von loop() gehören da nicht hin.
Die der static-Variablen?
Alexander schrieb:> Vielleicht weil die Urheberschaft der dafür genutzten KI nicht mit> angegeben wurde?
Wäre die Software per KI entstanden, deren Verwendung aber augeschlossen
worden und der Lehrer hätte es rausgefunden / nachgewiesen, wäre
sicherlich keine 3,2, sondern 5 oder 6 als Note rausgekommen.
Nicht jeder geht den einfachsten Weg...
Rolf schrieb:> Rein objektiv> wäre es für einen "richtigen" Programmierer Schulnote 4 minus -> vorausgesetzt, es läuft wenigstens richtig, was ich bezweifle.> Allerdings muss so ein Azubi nicht das können, was ein richtiger> Programmierer kann.
Das Ding läuft sogar sehr gut und auf eine Drehbewegung beim
Potentiometer (jetzt mit "t") reagiert das Programm sofort mit einer neu
eingestellten Geschwindigkeit. Gleiches gilt für das Erfassen der
Dipschalter.
Ich werde heute abend mal die originale Aufgabenstellung hier posten,
allerdings ist diese wirklich sehr "allgmeine" gehalten und da kann man
alles hineininterpretieren.
Rolf schrieb:> Das Arduino-Paradigma (setup vs. loop) ist auch nicht eingehalten, die> Initialisierungen am Anfang von loop() gehören da nicht hin.
Arduino-Paradigma hin- oder her. Für die Initialisierungen hier
(last_mode und i) hätte er diese global machen müssen um sie nach setup
zu verfrachten. auch nicht schön. Grundsätzlich lasse ich mich zu
Arduino-Paradigmen nicht wirklich aus, aber ich gebe dir recht.
Rolf schrieb:> Deswegen ist es wohl auch passiert, dass der Programmierer selbst nicht> gemerkt hat, dass die Variablen dipkey_status zwar ausgelesen, ihr aber> im gesamten Programm nirgendwo ein Wert zugewiesen wird. Läuft das> Programm denn so überhaupt richtig?
Natürlich liest er das aus. Der "Trick" seiner polled_delay ist der,
dass er den letzten Status der DIP-Schalter mit übergibt (hier als
"mode" bezeichnet, was ich in der Bezeichnung inkonsistent finde) und in
der delay dann selbst als dipkey_status. hier wäre es besser gewesen
einheitliche Namen zu wählen.
Und ja, wie oben bereits gesagt läuft das sogar sehr gut. Seine
polled_delay soll mehr oder weniger einen Eventstatus zurückliefern:
0x80 für korrekt durchgelaufene Delay, jeder andere Wert eine neue
Schalterkombination im Vergleich beim Eintritt in die Delayroutine,
damit direkt darauf eingegangen werden kann. :-) er hat sogar eine
Funktionsbeschreibung seines Programms gemacht, wie und warum das so
funktioniert.
Alexander schrieb:> Vielleicht weil die Urheberschaft der dafür genutzten KI nicht mit> angegeben wurde?
Bei einigen Teilen war ich dabei wie er das geschrieben hat. Wenn er
hier KI (chatgpt ?) eingesetzt hat, dann aber garantiert nicht für
dieses Programm. Ich habe die Originalanforderung der Schule bei chatgpt
eingegeben, es kam ein Programm heraus, das zum einen schon syntaktisch
nicht korrekt war und zum aderen einen komplett anderen Ablauf hat.
Schon gar nicht, dass im Grunde ein "Leuchtmusterabspielprogramm" dabei
herausgekommen wäre.
Rahul D. schrieb:> Wäre die Software per KI entstanden, deren Verwendung aber augeschlossen> worden und der Lehrer hätte es rausgefunden / nachgewiesen, wäre> sicherlich keine 3,2, sondern 5 oder 6 als Note rausgekommen.> Nicht jeder geht den einfachsten Weg...
Hätte er es abschließend durch eine KI gejagt (ich habe das gemacht),
dann ist eines der ersteren Teile was chatgpt bemängelt, dass es bei:
uintt8_t dipkey_get(void) richtigerweise void dipkey_get(void) heißen
muß und der Kommentar für den runspeed_get falsch ist. Ein paar weitere
Kleinigkeiten auch und dann hätte er das sicherlich selbst noch
geändert. Ich möchte meine Hand nicht ins Feuer legen, dass er vllt.
auch chatgpt bemüht hat, aber sicherlich hat chatgpt das Programm so
nicht erzeugt!
Norbert schrieb:> Bei zweien davon ist static unnötig.
Hm, ich sehe nur "event" als unnötig statisch an, alle anderen brauchen
das doch (ich kann mich aber auch täuschen).
Ralph S. schrieb:> Arduino-Paradigma hin- oder her. Für die Initialisierungen hier> (last_mode und i) hätte er diese global machen müssen um sie nach setup> zu verfrachten. auch nicht schön. Grundsätzlich lasse ich mich zu> Arduino-Paradigmen nicht wirklich aus, aber ich gebe dir recht.
Das sind teilweise Variablen, welche erhalten bleiben müssen und daher
in loop() goldrichtig aufgehoben sind.
Weil sie auch nur dort sichtbar sein sollen.
Nur eben nicht alle der als static ausgewiesenen Variablen.
Das macht's entweder unschön oder unüberlegt. je nach Betrachtungsweise.
Ralph S. schrieb:> Norbert schrieb:>> Bei zweien davon ist static unnötig.>> Hm, ich sehe nur "event" als unnötig statisch an, alle anderen brauchen> das doch (ich kann mich aber auch täuschen).
mode ebenfalls. Wird gleich ein paar Zeilen darunter überschrieben.
Rolf schrieb:> Das Arduino-Paradigma (setup vs. loop) ist auch nicht eingehalten, die> Initialisierungen am Anfang von loop() gehören da nicht hin.
Wo steht denn geschrieben, dass alles, also auch Variablen in setup()
initialisiert werden müssen?
Die Variablen die nur in einer Funktion genutzt werden (hier in loop())
sind als lokale Variablen dort besser aufgehoben weil es weniger
Verwirrung stiftet. Die hätten sonst, wie schon angemerkt, global sein
müssen. Und das wäre eher ein "Mangel" für mein dafürhalten.
Ja, in Arduino ist viel global was in meinen Augen nicht zu den guten
Eigenschaften dieser Umgebung zählt.
Rolf schrieb:> Rein objektiv wäre es für einen "richtigen" Programmierer Schulnote 4> minus - vorausgesetzt, es läuft wenigstens richtig, was ich bezweifle.
Ja, eine 4 minus hätte diesen Azubi ganz sicher motiviert, es das
nächste Mal besser zu machen. :(
Ihm eine Anerkennung zeigende Note zu geben und ihm erklären wo die
Schwächen seines Programmes liegen sind mit Sicherheit zielführender.
Bzw. ihn selber nochmal nachdenken lassen, ob er nicht dich
Verbesserungspotenzial findet. Um sich beim nächsten mal nochmal genau
anzusehen was man ihm dann bei dieser Aufgabe erklärt und gezeigt, oder
er selbst erkannt hat.
Eine 4 minus dafür, empfinde ich als Ohrfeige. Erinnert mich an meinen
Opa.
Eine eins ist es sicher nicht. Aber eine 4 minus noch viel weniger.
Ich sehe es auch besser als drei an.
Auch gut zu strukturieren braucht Übung und muss man lernen. Und es sind
gute Ansätze in der Struktur drin.
Ralph S. schrieb:> Diese Schularbeit wurde - mir komplett unverständlich - mit einer 3,2> bewertet und ich bin am Überlegen, ob ich da beim Lehrer "vorstellig"> werden sollte. Auch um dem Auszubildenden zu zeigen, dass ich nicht> hinter der Lehrerentscheidung stehe.
Solange du die Gründe des Lehrers nicht kennst, würde ich den
Auszubildenden heraushalten. Also persönliches Gespräch suchen, und wenn
du dann mit der Entscheidung nicht einverstanden bist, kannst du dich
immer noch hinter deinen Azubi stellen.
Auch wenn vielleicht keine KI genutzt wurde, der vergessene Kommentar
"Schrittmotormuster" deutet an, dass es da eine Vorlage gab. In meinen
Augen nicht unbedingt etwas negatives, vorhandenen Code sinnvoll für
eigene Zwecke nutzen zu können ist auch eine wichtige Fähigkeit.
Jetz mal ehrlich: Wenn das Programm richtig gut funktioniert, sollte das
allein schon eine 2 sein (Genauer gesagt: 80%). Schlechter als 3 kann es
eigentlich nur sein, wenn es irgendwo hakt und das nicht im Vorfeld
beschrieben wurde, z.B. eine nicht sofortige Reaktion auf Zeitänderung.
Ob das jetzt 1 oder 2 ist, kann nur das Klassenniveau zeigen. Wenn die
einen Super Lehrer haben und alle liefern sowas ab, dann halt eher 2.
Es gibt eigentlich nur 2 Gründe für die schlechte Note: Der Lehrer
konnte das Programm aus dem Tritt bringen oder der Azubi konnte eine
Zeile nicht erklären.
Wenn es das nicht war, gehe ruhig zum Lehrer und frage ihn, worauf genau
Du bei Deinem Ausbilden künftig achten solltest.
Für die Nicht-Laboranten: Programmierung ist nur ein Teilbereich von
ganz vielen anderen: Quasi so, wie SPS-Programmierung beim Schlosser
oder CNC-Programmierung beim Schreiner.
Ralph S. schrieb:> Weil es mir jetzt einfach keine Ruhe läßt.
In dipkey_get(): geschweifte Klammern plus Einrückung des Code hinter
den ifs. Ja, kann man weglassen, macht man aber nicht, meine Entwickler
würden dafür einen zwischen die Hörner bekommen. Zudem braucht { keine
eigene Zeile, sowas macht man nur bei Chefs die die Leistung von
Entwicklern anhand von LOC beurteinen wollen. Für solche Idioten will
man aber eh nicht arbeiten und dann ist es auch wieder egal, ob man
Zeilen schindet oder nicht.
Hallo,
ich möchte jetzt nicht unhöflich sein, aber die Handschrift von Ralph
sieht man im Code. Ich hatte es schon einmal woanders erwähnt, dass
static Variablen in main(), hier loop(), sinnlos sind, sie sind
praktisch gesehen global und sollte demzufolge auch global sein.
> Aus meiner Sicht der Dinge hat er so etwas> wie ein "event-pollinggetriebenes" Programm geschrieben, das aus Sicht> der I/O Devices (Trimmer, DIP-Schalter, LED) noch nicht einmal> blockierend ist.
Doch, es ist leider blockierend geschrieben. Die Funktion polled_delay()
blockiert immer eine gewisse Zeit. Vielleicht unterhalb der
Wahrnehmungsgrenze, aber blockiert. Die Arduino IDE bringt dafür ein
Bsp. mit - BlinkWithoutDelay.
1
intrunspeed_get(void)
2
constintspeedctrl=A0;
Sollte beides unsigned int sein.
Die Mustersteuerung hätte man mit enum + switch als Ablaufsteuerung
erschlagen können. Aber dafür gibt es mehrere Möglichkeiten. Bin nicht
so der Zeigertyp, nur wenn es nicht anders geht.
Die "frei liegende" i Inkrementierung gefällt mir auch nicht.
Schulnote vergebe ich keine, weil ich nicht weiß welchen Wissenstand der
Azubi haben muss bzw. sollte. Nur da es in der Schule eine Aufgabe war,
muss vorher dahingehend Wissen vermittelt wurden sein. Auch hier wissen
wir nicht welches. Das kann um Welten besser sein wie der Lehrer
erwartet muss aber nicht. Mit 3,5 wohler weniger wie erwartet. Kann ich
jedoch nicht beurteilen. Wie sehen die Programme der anderen Azubis aus
mit welcher Benotung?
Ich sage einmal so. Wenn es funktioniert und die Blockierung geduldet
wird, ist es schon deutlich besser was sonst so im Arduino Forum
reinflattert. Allerdings weiß ich auch, dass man die erwähnten
Feinheiten erst später im Grundsatz versteht, wenn man sich näher damit
beschäftigt. Ist als nicht Lehrer für mich schwer zu benoten. Zudem wie
gesagt paar unschöne Eigenarten vom Ausbilder mit reinspielen. Ich muss
das leider so sagen.
Beklage dich nicht beim Lehrer. Das sollte der Schüler besser selbst
tun. Idealerweise nicht als Klage formuliert, sondern erfragen, wie es
dem Lehrer besser gefallen hätte.
Loco M. schrieb:> Auch wenn vielleicht keine KI genutzt wurde, der vergessene Kommentar> "Schrittmotormuster" deutet an, dass es da eine Vorlage gab.
Nein, die gab es nicht. Ich hatte ihm erzählt, das ein einfacher
Schrittmotor mit diesem Lauflicht als Bitmustergenerator verwendet
werden könnte und darauf hin wurde das Bitmuster von ihm hinzugefügt
(schmunzeln muß, jetzt verteidige ich ihn auch hier). Allerdings ist das
gut zu sehen (oder interessant), dass nicht alle ihn für so gut wie ich
halten.
Veit D. schrieb:> Ist als nicht Lehrer für mich schwer zu benoten. Zudem wie> gesagt paar unschöne Eigenarten vom Ausbilder mit reinspielen. Ich muss> das leider so sagen.
Kann ich so akzeptieren, ich bin schon auch kritikfähig.
Ralph S. schrieb:>> Deswegen ist es wohl auch passiert, dass der Programmierer selbst nicht>> gemerkt hat, dass die Variablen dipkey_status zwar ausgelesen, ihr aber>> im gesamten Programm nirgendwo ein Wert zugewiesen wird. Läuft das>> Programm denn so überhaupt richtig?>> Natürlich liest er das aus.
??? Du hast meinen obigen Text nicht richtig gelesen. :-(
Der Variablen "dipkey_status" wird nirgendwo explizit ein Wert
zugewiesen. Somit ist ihr Wert undefiniert und/oder konstant. In beiden
Fällen ist es unsinnig, auf ihren Wert lesend zuzugreifen: Wenn
undefiniert, dann ist es per se sinnlos, wenn konstant, dann ist die
Variable überflüssig.
Im selben Zusammenhang: Auch die Variable "last_mode" ist unsinnig
verwendet. Nach dem allerersten Auslesen der Dip-Schalter ist die
"letzte" Schalterstellung später logischerweise(!) niemals mehr
unbekannt. Trotzdem hat der Programmierer den Wert der Variablen
zwischendurch völlig unnötig wieder auf "unbekannt" gesetzt (last_mode =
0xff). Unlogisch und ein ganz schmutziger Trick, der keinerlei Vorteile
bringt, wohl aber die Übersichtlichkeit und Funktions-Sicherheit
verschlechtert.
Falls man es wirklich braucht verwendet man eine zusätzliche
bool-Variable dafür ("DipHasChanged"), die man in der Funktion X setzt,
in der die Schalterstellung eingelesen wird - und nirgendwo anders. So
wird die Logik übersichtlich und der Code sauber.
900ss schrieb:> Eine 4 minus dafür, empfinde ich als Ohrfeige. Erinnert mich an meinen> Opa.>> Eine eins ist es sicher nicht. Aber eine 4 minus noch viel weniger.
Du hast richtig gelesen? Für eine "richtigen" Programmierer ist es 4
minus, für den Azubi aus einem anderen Fach nicht.
Rolf schrieb:> Der Variablen "dipkey_status" wird nirgendwo explizit ein Wert> zugewiesen. Somit ist ihr Wert undefiniert und/oder konstant. In beiden> Fällen ist es unsinnig, auf ihren Wert lesend zuzugreifen
1
uint8_tpolled_delay(uint8_tdipkey_status)
dipkey_status in polled_delay wird beim Aufruf aus loop übergeben, hat
daher den Wert von mode. Ihr Wert ist nie undefiniert und es ist normal,
lesend darauf zuzugreifen.
Ralph S. schrieb:> Kann ich so akzeptieren, ich bin schon auch kritikfähig.
Da bin beruhigt. :-)
Mir wäre es jedoch wichtiger, wenn man über die vermeintliche
Nichtblockierung nicht hinweg sehen würde. Deshalb nochmal der Hinweis,
dass polled_delay() blockierend wirkt.
Veit D. schrieb:
> Mir wäre es jedoch wichtiger, wenn man über die vermeintliche> Nichtblockierung nicht hinweg sehen würde. Deshalb nochmal der Hinweis,> dass polled_delay() blockierend wirkt.
Natürlich ist das blockierend, sonst wäre es kein delay. Ich sagte, dass
es für die benötigten I/O Dinge ( ADC und Dip-Schalter ) nicht
blockierend ist. Der Wert des ADC manipuliert hier das Ende der
Wartezeit und eine Veränderung der Dip-Schalterstellung beendet die
Delay sofort, damit sich im "loop" darum gekümmert werden kann.
Normalerweise würde man einen Timerinterrupt mit einem ISR-Aufruf jede
Millisekunde initialisieren, einen Interrupt für den ADC, der eine
Variable
ständig neu beschreibt ebenso. In der Timer ISR selbst wird dann nur
noch da
Ende einer laufenden Sequenz berechnet und entsprechend eine globale
Variable gesetzt über die in der "loop" gepollt werden kann. Gleiches
gilt für den Dip-Schalter: Pinchange-Interrupt initialisieren und Flag
setzen.
Aber: Interrupts waren nicht erlaubt. Hier ist der Aufgabentext, 1:1 aus
der Aufgabenbeschreibung übernommen (aus meiner Sicht der Dinge hat sich
jemand bei dieser Beschreibung jemand nicht wirklich mühe gemacht.
Aufgabenbeschreibung:
---------------------------------------------------
Programmieren Sie ein Lauflicht mit 8 Leuchtdioden, dessen
Ablaufgeschwindigkeit über
ein Potenziometer einstellbar ist. Das Lauflicht soll insgesamt 4
Leuchtmuster beinhalten,
die über einen zweipoligen Mini-Dipschalter auswählbar sind.
Verwenden Sie bei der Programmierung KEINE Interrupts. Die Ansteuerung
der Leuchtdioden
erfolgt über ein Schieberegister SN74HC595. Verwenden Sie aus der
Library "sn74hc595"
nur den Konstruktor und bilden Sie ein Objekt aus der Klasse
"shiftreg595" ab.
Aus diesem erstellten Objekt ist die Methode "setvalue" zur Ansteuerung
der LEDs
zu verwenden. Die Dokumentation der Library finden Sie auf dem Server.
Versehen Sie Ihr Programm mit Kommentaren. Im Kopfkommentar ist
anzugeben:
- Sketchname "sr595_lauflicht.ino"
- Ihr Name
- Ihre Schulklassenbezeichnung
- Ihr Ausbildungsberuf
- Schularbeit: Lauflichtprojekt 1b
- Framework: Arduino
Gegeben ist:
- Arduino mit ATmega328p Prozessor
- Schieberegistermodul mit SN74HC595 und 8 Leuchtdioden
- 10 KOhm Potenziometer
- Library "sn74hc595"
Viel Erfolg und Spaß beim Tüfteln
Hallo,
ich möchte jetzt nicht über Aussagen streiten. Kann jeder nachlesen. Nur
wie man die Blockierung weg bekommt hatte ich auch gesagt. Die Arduino
IDE bringt dafür ein Bsp. mit - BlinkWithoutDelay. Man muss nur die
vorhandene millis() Funktion richtig nutzen. Dann hat man zu keiner Zeit
eine Blockierung - egal wofür. In der Hinsicht verstehe ich bis heute
nicht, warum man dann immer wieder und wieder und wieder mit dem
Scheinargument um die Ecke kommt
> Normalerweise würde man einen Timerinterrupt mit einem ISR-Aufruf> jede Millisekunde initialisieren, ...
Weil das muss man nicht tun, wenn man millis() verwendet. Das ist dafür
da.
Also entweder man verwendet Arduino und nimmt millis(). Oder man
programmiert ohne Framework und programmiert seinen eigenen Timer. Weil
Arduino verwenden und eigenen Timer für solche Zeitfunktionen/Vergleiche
ist so richtig Sinnfrei. Aber dieses gegenseitige Ausspielen von
Argumenten die in der Beziehung zueinander einfach nur sinnlos sind,
dass stört mich maßlos. Das bringt auch diese Unterhaltung nicht weiter.
Man tritt auf der Stelle. Man benötigt schlicht und ergreifend für diese
Aufgabe keine eigene Interrupt Routine.
Rolf schrieb:> Du hast richtig gelesen? Für eine "richtigen" Programmierer ist es 4> minus, für den Azubi aus einem anderen Fach nicht.
90% aller “richtigen“ Programmierer hätten es nicht besser gemacht. Sie
halten sich höchstens an willkürlich von Dir favorisierte Paradigmen,
wenn Du sie bewertest.
Bruno V. schrieb:> Für die Nicht-Laboranten: Programmierung ist nur ein Teilbereich von> ganz vielen anderen: Quasi so, wie SPS-Programmierung beim Schlosser> oder CNC-Programmierung beim Schreiner.
Wenn dem so ist, dann sieht das gezeigte Programm gar nicht schlecht
aus. Bewerten in Noten kann ich es dennoch nicht.
Abgesehen davon hätte die Schule die Aufgabe anders stellen können.
Weniger Klimmbimm mit den Mustern. Dafür den 74HC595 zu Fuss
angesprochen ohne fertige Lib. Das ist nämlich gar nicht so schwer. Dann
hätte man gelernt bzw. abgefragt ob man das Datenblatt lesen und damit
paar wenige benötigte Zeilen schreiben kann. Dann reicht es ein
einfaches Lauflicht zu programmieren. Hätte mir besser gefallen. ;-)
Veit D. schrieb:>> Normalerweise würde man einen Timerinterrupt mit einem ISR-Aufruf>> jede Millisekunde initialisieren, ...> Weil das muss man nicht tun, wenn man millis() verwendet. Das ist dafür> da.> Also entweder man verwendet Arduino und nimmt millis(). Oder man> programmiert ohne Framework und programmiert seinen eigenen Timer.
ich hätte wohl dazuschreiben sollen, was für mich "normalerweise" ist.
Wie du ganz richtig erkannt hast: Programmieren OHNE Arduino-Framework !
Meine Güte. Es ging hier darum, wie etwas zu bewerten ist.
Sagen wir es so: Wärst du Berufsschullehrer, würde ich nicht gerne dein
Schüler sein wollen!
Aber: das ist deine Meinung und aus dieser Sache heraus erklärt sich
vllt. auch die Note, die vergeben worden ist.
Ich bleibe auch dabei, dass das für den Lehrling eine gute bis sehr gute
Arbeit war, schlicht weil er sich ein paar Gedanken mehr gemacht hat,
als einfach nur Hexzahlen einzugeben und die nacheinander herunterlaufen
zu lassen. Blockierend hin, blockierend her (mal so ganz davon
abgesehen, dass das für dieses Programm so überhaupt keine Rolle
spielt).
Vom Schreibstil der Kommentare erinnert der Sourcecode schon etwas an
das, was Claude Sonnet o.ä. ausgeben würde.
Wenn er es wirklich selbst programmiert hat, dann finde ich die 3,2 aber
echt zu schlecht bewertet. Es ist strukturiert programmiert. Er nutzt
Funktionen. Es ist gut kommentiert. Da sieht man von Schülern oft viel
schlechteres.
Nützt aber leider nix, weil wenn der Lehrer das anders sieht, wird er
sich wahrscheinlich nicht umstimmen lassen.
PS:
Weil hier ChatGPT in Zusammenhang mit programmieren erwähnt wurde.
Probiert mal Claude Sonnet oder besser noch Claude Opus aus. Ist echt
erstaunlich was diese KIs für Sourcecode erstellen können. Da frage ich
mich, ob der Beruf des reinen Programmierers noch eine Zukunft hat.
Veit D. schrieb:> Abgesehen davon hätte die Schule die Aufgabe anders stellen können.> Weniger Klimmbimm mit den Mustern. Dafür den 74HC595 zu Fuss> angesprochen ohne fertige Lib. Das ist nämlich gar nicht so schwer. Dann> hätte man gelernt bzw. abgefragt ob man das Datenblatt lesen und damit> paar wenige benötigte Zeilen schreiben kann.
Wir reden hier nominell von einem 17jährigem, der nicht das Zeug zum
Abitur hat.
Ich bitte doch mal alle Programmierer hier, das mit ihrem Code mit 17 zu
vergleichen. Und zu bedenken, dass 80% in diesem Beruf niemals embedded
programmieren.
Dass es auch Lehrlinge mit Abitur gibt, geschenkt.
Ralph S. schrieb:> Bei einigen Teilen war ich dabei wie er das geschrieben hat. Wenn er> hier KI (chatgpt ?) eingesetzt hat, dann aber garantiert nicht für> dieses Programm.
Ich habe mir den Code nicht angesehen da ich den wohl sowieso nicht
verstehen würde. KI für Hausaufgaben hatte ich in der heutigen Zeit als
normal vorausgesetzt.
Aber stimmt, KI hätte nicht die Transliteration für Umlaute benutzt, und
außerdem fehlen da jede Menge Emojis, Pfeile und Kästchen ;)
Alexander schrieb:> Ich habe mir den Code nicht angesehen da ich den wohl sowieso nicht> verstehen würde.
Aber ein Urteil raus posaunen.
Ohne Fundament.
Bri schrieb:> Vom Schreibstil
Er entspricht, in großen Teilen, nicht den üblichen
Konventionen/Vereinbarungen in der Arduino (oder auch C++) Welt.
Je nachdem was vorher in der Schule gelaufen ist, kann das den
Punktabzug begründen.
Alexander schrieb:> Vielleicht weil die Urheberschaft der dafür genutzten KI nicht mit> angegeben wurde?
Das ist ein Urteil!
In Form einer vernichtenden Behauptung, die sich offensichtlich als
falsch herausgestellt hat.
Arduino F. schrieb:> Das ist ein Urteil!
Nö! Das ist eine Anfrage, maximal eine Suggestion, auch Anregung
genannt. Mit Urteilen sind hier andere gut dabei.
Alexander schrieb:> Das ist eine Anfrage
Nein!
Eher eine rhetorische Frage.
Eine rhetorische Frage ist eine Scheinfrage, auf die keine Antwort
erwartet wird, da die Antwort offensichtlich ist oder die Frage als
nachdrückliche Aussage dient. Sie wird als stilistisches Mittel
eingesetzt, um Aufmerksamkeit zu steigern, Meinungen zu verstärken oder
das Gegenüber zu manipulieren/überzeugen.
Ralph S. schrieb:
eigentlich ging es mir nur darum der Aussage es wäre nicht blockierend
zu widersprechen und nun sehen wir was aus dem Wortwechsel geworden ist.
> Sagen wir es so: Wärst du Berufsschullehrer, würde ich nicht gerne dein> Schüler sein wollen!
Die Vorlage muss ich nutzen. ;-) Dann würdest du nicht lernen wie man
millis() für alles mögliche verwenden kann, wie man damit nicht
blockierend programmiert und wie man C und C++ Code Style nicht
vermischt. :-)
Wegen der Benotung nochmal. Man müsste wissen was in der Schule
behandelt wurde. Das ist ja ganz sicher keine fakultative Aufgabe
gewesen. Es reicht schon aus, wenn der Berufsschullehrer und du einen
anderen Code Style an den Tag legt. Schon hat der Azubi, der zwischen
den Stühlen steht, schlechte Karten usw. Auch ist die Priorität der
Aufgabe nicht bekannt. Muss es nur funktionieren. Muss der Code gut
aussehen. usw.
Ich will jetzt nicht weiter darauf rumhacken.
Ich wünsche dir Ralph dennoch bei allen Wortwechseln hier und da paar
ruhige Tage. Alles gut.
Veit D. schrieb:> Die Vorlage muss ich nutzen. ;-) Dann würdest du nicht lernen wie man> millis() für alles mögliche verwenden kann, wie man damit nicht> blockierend programmiert und wie man C und C++ Code Style nicht> vermischt. :-)
Die Arroganz und die Überheblichkeit auf mikrocontroller.net kennt keine
Grenzen und der Wettbewerbssiege in dieser Dispziplin ist, "the winner"
is (darf man Englisch und Deutsch miteinander vermischen?!?): Tatäääää
(suche es Dir raus).
Nur um es zu verdeutlichen: Das Lauflichtprogramm ist nicht von mir. Ich
verwende im Normalfall auch keine millis, weil ich im Normalfall auch
kein Arduino verwende. Aber ich habe in Arduino etwas hereingesehen, so
wie du das in einem anderen Thread bereits kommentiert hast. Bisweilen
sollte man manchmal manche Menschen an der Nase packen und sagen, dass
vieles nicht zwingend in einem akademischen Stil gemacht werden muß und
das gilt insbesondere im Embeddedbereich.
Also, ich weiß wie man NICHT blockierend programmiert, ich kann (und das
schon lange, allerdings nicht in Arduino) mittels Interrupts GPIOs, ADC,
UART oder auch anderes lesen und einen Ringpuffer befüllen der
ausgewertet wird. Stell dir vor ich kann sogar DMA auf unterschiedlichen
Controllern (sorry an alle anderen dass ich das jetzt "raushängen
lasse"). Diese Frechheit von "sugestiven" Äußerungen die jemand anderen
dumm dastehen lassen ist bald nicht zum Aushalten.
By the way: Ich habe hier noch kein Projekt, noch keine Arbeit, kein
nichts gesehen, jedoch grundsätzliche Nörgelei en Masse. Wenn etwas
größer wird, gibt es auch immer mehr Dinge daran zu kritisieren, was
normal ist. Menschen wie du jedoch werden persönlich und das ist absolut
daneben.
So, weil ich von dir lernen könnte (was ich extrem stark bezweifle, denn
von Menschen, die stur an Paradigmen festhalten und nicht wissen, wann
es sinnvoll ist, davon abzuweichen, kann ich nichts lernen).
Zu deiner "genialen" Darstellung von blockierend hast du das hier
gemacht:
1
uint8_t polled_delay(uint8_t dipkey_status)
2
3
{
4
Serial.println("polled");
5
6
uint32_t start = millis();
7
uint32_t runtime;
8
uint8_t dipkeys;
9
10
while (1)
11
{
12
dipkeys = dipkey_get();
13
if (dipkeys != dipkey_status)
14
{
15
Serial.println("return A");
16
return dipkeys;
17
}
18
19
runtime = millis() - start;
20
if (runtime >= runspeed_get())
21
{
22
Serial.println("return B");
23
return 0x80;
24
}
25
Serial.println("while");
26
}
27
}
gibt es eine nette Aussage meines Lehrlings: "Wenn er doch dort, wo er
Serial.println("while") schreibt, die Funktionen einhängt, die während
der Wartezeit bearbeitet werden sollen, dann blockieren die doch dort
nicht. Er hatte da ja sogar genug Zeit, wiederholt println aufzurufen".
Ich sage dir was: Er hat im Prinzip schlicht recht. An genau dieser
Stelle blockiert nichts. Jetzt kann man sich über die Paradigmen von
Arduino streiten oder nicht, manchmal kann man Werkzeuge (und Arduino
ist ein Werkzeug) auch anderst benutzen als es ursprünglich gedacht war.
Ich muß zugeben, "Asche auf mein Haupt", je mehr ich mich damit
beschäftige, verändert sich meine Meinung darüber und verstehe, warum
das für einige eine gute Lösung und sogar mehr als ein Einstieg in die
Embedded-Welt sein kann).
Immerhin: :-) ich weiß schon, warum ich mit dir nicht mehr "diskutieren"
wollte. Götter machen Regeln, sie diskutieren nicht. Schade nur, dass
ich an Götter nicht glaube!
Ralph S. schrieb:> An genau dieser> Stelle blockiert nichts.
Ich stimme nicht zu!
Ich sage:
Man braucht nur eine while(1) bzw. Endlosschleife in einem Programm.
Und die steckt bei Arduino unzugänglich in main()
Bei Nutzung eines Multitaskingsystems wird das anders aussehen.
Hallo Ralph,
ich belasse das unkommentiert. Es ist mir egal was du von mir denkst.
Die Standpunkte können klarer nicht sein.
Und wegen Code zeigen o.ä..
Habe ich hier hin und wieder getan, bin aber meistens im Arduino Forum
unterwegs. Dort wird meine Hilfe dankend angenommen.
Ralph S. schrieb:> Grundsätzlich hat er etwas gemacht, von dem er wahrscheinlich die> Fachbegriffe gar nicht kennt.
Gott bist du naiv. Die KI hat das gemacht. Wach auf.
Re D. schrieb:> Die KI hat das gemacht
Sehe ich nicht so, evtl. hat er sich per KI Informationen besorgt. Was
aber spricht dagegen in der heutigen Zeit wo KI ein Werkzeug ist?
Und damit man sehen kann wie KI erzeugter Code zu der Aufgabe aussieht,
habe ich diese in 3 unterschiedliche KI gesteckt und die jeweiligen
Ergebnisse hier angehängt.
Ich habe keine Datei verändert.
Eine Ähnlichkeit mit dem Code des Azubis ist nicht zu erkennen. Und mir
sieht sein Code auch nicht nach KI aus.
Es wird einmal sogar einmal der Wunsch nach nicht blockierendem "Warten"
bedient.
Ich sehe das in dieser Aufgabe aber als völlig unerheblich an.
Die Aufgabe ist klar gestellt und für diese ist die Lösung des Azubis
völlig ausreichend.
Er hat es sogar so implementiert, dass das "Nutzerinterface" garnicht
verzögert reagiert. Also der Delay ist nicht zu merken. Er hat sich
darüber also Gedanken gemacht und das entsprechend gelöst. Ich finde
immer noch dass er die Ausgabe gut gelöst hat.
2 der KIs haben das nicht geschafft.
Klar findet man Stellen die man "verbessern" kann. Aber einiges sind
auch eher persönliche Vorlieben.
Man darf auch nicht vergessen dass es ein völliger Anfänger ist.
900ss schrieb:> Er hat es sogar so implementiert, dass das "Nutzerinterface" garnicht> verzögert reagiert. Also der Delay ist nicht zu merken. Er hat sich> darüber also Gedanken gemacht und das entsprechend gelöst. Ich finde> immer noch dass er die Ausgabe gut gelöst hat.
Volle Zustimmung...
900ss schrieb:> Klar findet man stellen die man "verbessern" kann. Aber einiges sind> auch eher persönliche Vorlieben.
Auch hier: volle Zustimmung. Hier muß ich zugeben, dass ich ihm im
Grunde meinen "Stil" aufzwinge. Weiß ich nicht ob das gut oder schlecht
ist. Aber zumindest im Sinne der Kommentare möchte ich das so haben.
Zudem muß ich sagen, dass im Zuge der Ausbildung nur der Schule wegen
Arduino benutzt wird, ansonsten ist bei Unterweisungen C angesagt (was
viele Aussagen der Vorredner erklären dürfte)
Veit D. schrieb:> den 74HC595 zu Fuss> angesprochen ohne fertige Lib. Das ist nämlich gar nicht so schwer. Dann> hätte man gelernt bzw. abgefragt ob man das Datenblatt lesen und damit> paar wenige benötigte Zeilen schreiben kann. Dann reicht es ein> einfaches Lauflicht zu programmieren.
Ich hatte auch damit gerechnet, dass es dem Lehrer um das direkte
ansprechen des Schieberegisters gegangen sein könnte, und die Verwendung
der Library dann zur Abwertung geführt hat. Nachdem jetzt aber der
originale Aufgabentext gezeigt wurde, und da sogar explizit drin steht,
dass man die Library benutzen soll, fällt das auch flach.
Mein Fazit: Die Lösung ist deutlich besser als 3,2.
Leider ist es in vielen Schulen so, dass die Aufgabenstellung nicht
alles enthält. Man muss seine Lehrer und deren Vorlieben kennen, und
(leider) immer auch interpretieren, was sie mit bestimmten
Formulierungen oder auch generell wohl meinen und erwarten. Es ist
schade, dass die Abwertung hier offenbar jemanden trifft, der sich
eigene und gute Gedanken zum Problem gemacht hat.
Ob man sich hier als Ausbilder einschalten sollte, ist allerdings nicht
unbedingt klar. Ich denke ich würde dem Azubi meine Wertschätzung für
seine Leistung deutlich machen, und ihm klar sagen, dass für mich nicht
ersichtlich ist, warum die Note nicht besser ausgefallen ist. Je nach
Mentalität von sowohl Azubi als auch Berufsschullehrer (und vielleicht
auch dem Klassenzusammenhalt - Stichwort Mobbing von vermeintlichen
"Strebern") könnte sich der Azubi dazu entschließen, selbst beim
Berufsschullehrer nachzufragen.
Hallo
Ich fasse das einmal zusammen.
Es wird leider bis jetzt nicht verstanden, dass die polled_delay() mit
ihrer while(1) zur neuen Hauptschleife geworden ist. Alles was in loop()
steht wird davon blockiert. Man muss alles in die neue Ersatz - while(1)
schreiben damit nichts blockiert. Offensichtlich wurde hier etwas nicht
verstanden. Nun gibt Ralph offen zu, dass der Azubi seinen
Programmierstil übernommen hat und fragt sich gleichzeitig ob das gut
oder schlecht ist. Wenn ich um die Ecke komme und den negativen Teil
bestätige, gibt's Streit. Will man nicht hören. Würde hier im Forum
jemand eine Hauptfunktion polled_delay() benennen? Mit versteckten
while(1)? Ich denke nicht. Warum redet man das schön?
Wenn der Azubi und Ralph verstehen wollen, warum es nur eine 3,2 gab,
dann hätte man den Berufsschullehrer schon längst danach gefragt,
welches Ziel er hatte und was er bemängelt. Oder wie seine Musterlösung
aussieht. Dann hätte man konkret darüber reden können.
> Zudem muß ich sagen, dass im Zuge der Ausbildung nur der Schule wegen> Arduino benutzt wird, ansonsten ist bei Unterweisungen C angesagt (was> viele Aussagen der Vorredner erklären dürfte)
Eine Salamischeibe. Das bestätigt meine Einschätzung und zeigt das
Problem. Es gab keine Absprache wie man den Stoff "Programmierung"
gemeinsam vermittelt. Der Azubi ist der Leid tragende und steht zwischen
Stühlen.
Ich hatte ja schon geschrieben, wenn es nur um die reine Funktion geht,
dann ist es okay. Geht es dem Berufsschullehrer um andere Aspekte, die
wir eben nicht kennen, dann ist der Raum für alle Kritik offen. Leider
geht es hier nur darum, dass man eine Einschätzung bestätigen soll und
keine Kritik zulässt. Widerspricht man der Einschätzung knallt es. Dann
sollte man jedoch keinen Thread dazu eröffnen.
Wünsche dennoch allen einen ruhigen Feiertag.
Veit D. schrieb:> Widerspricht man der Einschätzung knallt es.
Bei mir knallt nichts. Ich sehe die Notwendigkeit eines "nicht
blockerens" hier eher nicht als gegeben an.
Wenn man vermitteln möchte, wie man es machen kann, damit loop() nicht
blockiert, dann ist dein Vorschlag gut.
Aber ist in der Aufgabe meines Erachtens nicht gefragt und auch nicht
notwendig.
Und der Azubi hat sich Gedanken gemacht, wie er es löst, damit das "UI"
nicht hängen bleibt und hat es gut gelöst.
Ich sehe nur einen der hier mit den Füßen trampelt ;)
Veit D. schrieb:> Alles was in loop() steht wird davon blockiert.
Aber genau das ist doch der Zweck der Funktion. Darf man Dich so
interpretieren dass Du grundsätzlich jedes delay() in der loop()
kritisierst?
Wenn mich etwas triggert, dann ist es while(1).
Ich habe zu wenig Ahnung von C++ oder Arduino. Und für alle hier scheint
das normal. In C würde das bei uns nicht durchgehen, wegen der
Warnungen. Es gibt dafür ja extra ein eigenes Konstrukt.
900ss schrieb:> Ich sehe nur einen der hier mit den Füßen trampelt ;)
Ich nehme an du meinst mich und nicht Ralph. ;-) Eine eher einseitige
Betrachtung, weil ich konkrete Dinge angesprochen habe, die zur
Verbesserung des Programm dienen sollen. Wenn das nicht gehört werden
möchte, soll es mir nun auch langsam egal sein. Was ich nicht leiden
kann, ist dieses schön reden, wenn man doch Probleme sieht und diese
anspricht. Mir ist Klartext um Welten lieber.
Alexander schrieb:> Veit D. schrieb:>> Alles was in loop() steht wird davon blockiert.> Aber genau das ist doch der Zweck der Funktion.
Das ist jedoch im Zusammenhang mit der ohnehin vorhandenen loop()
doppelt gemoppelt und Irreführend. loop() dient nicht dazu von irgendwas
blockiert zu werden. Alles andere hatte ich geschrieben.
> Darf man Dich so interpretieren dass Du grundsätzlich jedes delay()> in der loop() kritisierst?
Ja darf man. Über 1ms hartes delay kann man mit mir noch reden. :-) Aber
wie hier 40 bis 381ms würde ich nicht zulassen. Zudem ja hier millis()
verwendet wird und dennoch die loop() blockierend programmiert wurde.
Stell dir einmal vor du müsstest das Programm erweitern und erwartest
kurze Reaktionszeiten. Du hast mit der loop() keine Chance. Du wärest
gezwungen alles in die while(1) zu schieben bzw. darin aufrufen zu
lassen. Ich weiß das es hier keine Rolle spielt, so wie das Programm
geschrieben ist. Nur sollte ich unschöne Dinge dennoch ansprechen können
dürfen. Das wird mir jedoch mit Argumenten die nichts mit Programmierung
zu tun haben praktisch untersagt bzw. will man das nicht hören. Das kann
es nun auch nicht sein.
Bruno V. schrieb:> Wenn mich etwas triggert, dann ist es while(1).>> Ich habe zu wenig Ahnung von C++ oder Arduino. Und für alle hier scheint> das normal. In C würde das bei uns nicht durchgehen, wegen der> Warnungen. Es gibt dafür ja extra ein eigenes Konstrukt.
Da kann ich aushelfen.
Klassisch C oder C++
Bruno V. schrieb:> Wenn mich etwas triggert, dann ist es while(1).Alexander schrieb:> schlimmer finde ich `for (;;)`
In irgendeinen Framework bin ich mal auch ein "forever" Makro gestoßen.
Habe aber keine Anwendung davon zu Gesicht bekommen, nur die Definition.
Gut dass wir hier vom selben reden. Dann habe ich auch mal etwas
verstanden. Wenn man mehrere Sachen hat muss man sich natürlich Gedanken
machen. Auf dem ESP32 kann man auch Sachen auf mehrere Tasks aufteilen.
Da ist die loop() ein Task wie jeder andere für mich, eine der Sachen
darf ruhig die loop() für sich alleine haben. Für den Arduino bleibt
dann wohl nur die millis() zu pollen, wenn die sich die loop() teilen
müssen.
Veit D. schrieb:> Stell dir einmal vor du müsstest das Programm erweitern und erwartest> kurze Reaktionszeiten. Du hast mit der loop() keine Chance. Du wärest> gezwungen alles in die while(1) zu schieben bzw. darin aufrufen zu> lassen.
Ja, wenn man das Programm so erweitern müsste wäre das in der Tat
schwierig. Aber diese Aufgabe war klar umrissen und Erweiterbarkeit war
nicht gefordert.
Insofern hat der Azubi alles richtig gemacht. Sogar erkennbar mit
Nachdenken.
Die Kritik mit dem Blockieren ist richtig wenn es hier ein Problem wäre.
Es ist allerdings ein hypothetisches Problem. Insofern weiß ich nicht
weshalb sich so dagegen gewehrt wird, dass die Aufgabe hinreichend gut
gelöst wurde.
Man könnte dem Azubi jetzt die Aufgabe geben, in loop() eine LED mit
konstanter Zykluszeit blinken zu lassen. Dann würde er das vermutlich
erkennen was anders sein muss und das umsetzen. Zur Übung sicher ganz
gut für ihn.
So, jetzt weiter Trampeln ;)
Arduino F. schrieb:> Veit D. schrieb:>> while(1)> Üblich und völlig OK
Jedoch nicht als verkorkster verschachtelter Ersatz für loop(), wenn
loop() ohnehin verwendet wird.
Veit D. schrieb:> Arduino F. schrieb:>> Veit D. schrieb:>>> while(1)>> Üblich und völlig OK>> Jedoch nicht als verkorkster verschachtelter Ersatz für loop(), wenn> loop() ohnehin verwendet wird.
Ja, nee....
Es drehte sich mir um die Glaubensfrage, welche der Endlosschleifen
jetzt besser oder schöner ist.
Und ich sage: Egal!
Der Compiler macht in allen 3 Fällen das gleiche draus.
Wenn es hier schon die ganze Zeit um Stil, Schönheit, Klarheit und
Lesbarkeit geht, stellt sich mir eine Frage.
Wieso heißt die Funktion bei Arduino eigentlich ›loop()‹, obwohl sie
genau das eben nicht macht?
Sie wird aufgerufen und beendet. Und zwar wiederholt und unregelmäßig,
zudem auch noch in noch nicht einmal festen Zeitrastern.
Da hätte sie also schon von Anfang an einen vernünftigen und passenden
Namen verdient.
›occasionally()‹, ›every_once_in_a_while()‹, …
›thanks_for_calling()‹ wäre ja mein persönlicher Favorit. ;-)
Norbert schrieb:
Wenn du nachgeschaut hast, müsstest du gesehen haben, dass zusätzlich
ein Serial Eventhandler aufgerufen wird. Warum du loop() in einem
zusätzlich bremsenden Zeitraster haben möchtest weiß ich nicht.
Es wird unmittelbar so schnell und so oft wie möglich aufgerufen.
> ›occasionally()‹, ›every_once_in_a_while()‹, …>> ›thanks_for_calling()‹ wäre ja mein persönlicher Favorit. ;-)
Stell ein Request.
Veit D. schrieb:> Norbert schrieb:>> Wenn du nachgeschaut hast, müsstest du gesehen haben, dass zusätzlich> ein Serial Eventhandler aufgerufen wird. Warum du loop() in einem> zusätzlich bremsenden Zeitraster haben möchtest weiß ich nicht.> Es wird unmittelbar so schnell und so oft wie möglich aufgerufen.>>> ›occasionally()‹, ›every_once_in_a_while()‹, …>>>> ›thanks_for_calling()‹ wäre ja mein persönlicher Favorit. ;-)>> Stell ein Request.
1. Du zitierst falsch. Sehr falsch sogar.
2. Was intern passiert, hat mit der Frage nach dem irreführenden Namen
nichts zu tun.
3. Ich will kein Zeitraster. Ich weiß noch nicht einmal wo du das
gelesen haben willst.
4. Ich benutze das Zeug nicht. Dennoch muss eine solche Frage legitim
sein.
5. Nicht gleich auf den Schlips getreten fühlen.
Veit D. schrieb:> Lies bitte deinen eigenen Text von 16:35 Uhr.
Ich kenne den. Habe ihn selbst geschrieben.
Aber du möchtest mir bestimmt die Stelle zeigen, an der ich angeblich
>> Warum du loop() in einem>> zusätzlich bremsenden Zeitraster haben möchtest weiß ich nicht.
gefordert haben soll. Das wird spannend.
Norbert schrieb:> Veit D. schrieb:>> Lies bitte deinen eigenen Text von 16:35 Uhr.>> Ich kenne den. Habe ihn selbst geschrieben.> Aber du möchtest mir bestimmt die Stelle zeigen, an der ich angeblich>>>> Warum du loop() in einem>>> zusätzlich bremsenden Zeitraster haben möchtest weiß ich nicht.>> gefordert haben soll. Das wird spannend.
Nichts leichter als das.
> Sie wird aufgerufen und beendet. Und zwar wiederholt und unregelmäßig,> zudem auch noch in noch nicht einmal festen Zeitrastern.
Du wunderst dich über fehlende feste Zeitraster. Demzufolge wünscht du
dir diese indirekt mit dieser Aussage. Warum muss ich fremder Leute
Texte erklären?
Veit D. schrieb:> Du wunderst dich über fehlende feste Zeitraster. Demzufolge wünscht du> dir diese indirekt mit dieser Aussage. Warum muss ich fremder Leute> Texte erklären?
Ich wundere mich nicht, ich liste eine Reihe von Fakten auf.
Und nirgendwo steht, dass ich mir irgend etwas wünsche.
Das findet nur in deinem Kopf statt.
Wenn ich deine Replik lese, bei einer KI würde man jetzt von
Halluzination sprechen.
Und zu guter Letzt, nein, du musst Texte nicht erklären. Das setzt
nämlich vorhergehendes Verständnis voraus, was klar nicht gegeben ist.
900ss schrieb:> Veit D. schrieb:>> mein Beitrag zur Güte>> Der ist gut.... "zur Güte".... ;)
Ich wusste das sowas positiv aufgenommen wird.
Meinen Humor lasse ich mir nicht nehmen.
So, :-) zu "Meiner Güte" und für mich hier jetzt abschließend (weil mir
manche Dinge eben wirklich keine Ruhe lassen und ich wie so oft von
geneigten Forenmitglieder so dargestellt werde, als ob ich der Stümper,
Nichtskönner und blabla bin, nur weil ich anderer Ansicht bin) hier
meine Version eines Lauflichts, das - zumindest aus meiner Sicht -
nichtblockierend ist.
Für das Programm hier habe ich sogar Teile des Lehrlingprogramms
genommen und weiter "entwickelt".
Grundsätzlich ist das Programm hier etwas, das ich interruptbasierend
auf einem STM32F030 und einem STM32F411 am Laufen hatte / habe, dort
jedoch im Gegensatz zu hier in "Plain-C" und mit Interrupts.
Also habe ich mir einmal die Mühe gemacht, und mein eventbasierendes
Rumpfprogramm nach Arduino portiert. Hier - so glaube ich - habe ich
dann für Arduino dann glaube ich doch etwas gelernt (ohne Kommentar von
mir ob mir das gefällt oder nicht), wie in Arduino etwas gerne
gehandhabt werden sollte. Hier dann einen Dank an Arduino F. auch für
Anmerkungen in einem anderen Thread (und garantiert keinen Dank an
Nörgler, Besserwisser und Paradigmenfesthalter).
Ich habe das, auch wenn es immer noch "nur" ein Wrapper ist, so gut ich
das konnte an Arduino angepasst und heraus gekommen ist mein
"Eventbasierendes System unter bewußter Nichtnutzung von Interrupts).
Kern des Programms sind 2 Funktionen:
- event_scan
- event_handler
event_scan erfasst, wenn auch nur durch den Handler zyklisch gepollt,
eventuell auftretende Events (bspw. das Ablaufen eines Timers, geänderte
Schaltereinstellung oder das Eintreffen eines Zeichens auf der seriellen
Schnittstelle).
event_handler wird durch die loop permanent aufgerufen und pollt dadurch
permanent die "Events".
Als "Streitpunkt" stellte sich hier ja heraus, wie das zu realiseren sei
(und das das von meinem Auszubildenden wohl nicht gut gemacht gewesen
sei - was ich anderst sehe) und es natürlich nur über millis() gehen
kann. Also habe ich (und nein, ich habe nicht von Veit abgeguckt) so
etwas wie Softtimerfunktionen realisiert, einmal einen der mittels ADC
seine Intervallzeit einstellen kann und einmal einen, der einfach nur
per Vorgabewert seine Zeit einstellt.
Und - wie Veit das in seinem Programmschnippsel gezeigt hat - können von
diesen class beliebig Objekte instanziert werden.
Um im Ganzen zeigen zu können, dass das hier nicht blockiert, habe ich
dem Programm auch noch mittels Serial.available ein Event hinzugefügt,
mit dem ausgewertet werden kann, ob es eine Aktivität auf der seriellen
Schnittstelle gegeben hat. In diesem Falle erfolgt dann ein Speichern in
einem Bufferstring durch anhängen des eingehenden Zeichens an den
Bufferstring. Sehr deutlich ist hier zu sehen, dass, obwohl auf der
seriellen Schnittstelle ein String eingegeben werden kann, dennoch das
Lauf- und das Blinklicht schön weiter vor sich hin werkeln.
Als kleine Besonderheit kann bei der Eingabe eines Strings über ein
Terminal (hier meine ich nicht das wirklich unsägliche Terminal von
Arduino, sondern ein "besseres" wie bspw. puTTY oder picocom oder
ähnliches) das letzte eingegeben Zeichen gelöscht werden (über das - so
denke ich - allseits bekannte "\b \b").
Zuvor schon hatte ich die sn74hc595 Library nach der
Funktionsbeschreibung der Schule nachprogrammiert gehabt, die ich hier
auch mit einstelle, damit das auch alles schön nachvollziehbar und
compilierbar ist.
-------------------------------------------------
Grundsätzlich jedoch (und Arduino F.) möge es mir verzeihen, stellt sich
mir die Frage, wieviele typische Arduino-Nutzer diesen Code hier
verstehen und wieviele Anfänger diesen Code hier verstehen. Von daher
ist eine Frage nach der Sinnhaftigkeit meines Codes schon berechtigt.
So, ich hoffe, dass damit die Diskussion ein Ende hat und noch einmal
ein Danke an Arduino F., der unaufgeregt erzählt hat, wie Arduino-User
etwas sehen und was sie wohl von Code erwarten.
Viele Grüße und gute Nacht, Ralph
PS: Ein Lehrer würde mir für meine Lauflichtversion wohl eine 4,0 als
Schulnote geben, weil am Thema vorbei: Über 540 Zeilen Code nur für ein
Lauflicht ist sogar aus meiner Sicht der Dinge etwas "zu arg".
Mal abgesehen von dem Stil, der nicht Ardoinotypisch ist, habe ich 2
massive Fehler gefunden.
> if (millis() > (starttime + getadcmillis()))> if (millis() > (starttime + overflow))
Beide if Statements fallen nach 49,x Tagen auf die Fresse!
millis() läuft irgendwann über.
kurz vorher läuft deine Addition über
Also ein Doppelüberlauf ohne Kompensation.
Dabei ist es doch so einfach, es richtig zu machen.
if (millis() - starttime > getadcmillis())
Auch steckt in deiner class shiftreg595 (min) eine seltsame Sache:
> inline void datHigh() { digitalWrite(dat, HIGH); }
Wenn Methoden innerhalb einer Klasse in einer *.h definiert sind, sind
sie per default schon inline.
Das inline ist damit redundant bzw. flüssiger als Wasser.
Bei mir würde es eher so aussehen:
Ralph S. schrieb:> das - zumindest aus meiner Sicht -> nichtblockierend ist.
Das Originalprogramm sieht eigentlich so aus, als wäre es ursprünglich
nicht blockierend und ist dann "verbessert" worden.
polled_delay kann einfach radikal gekürzt werden und das letzte else in
loop entfallen, dann läuft es schon perfekt.
1
uint8_tpolled_delay(void)
2
{
3
uint32_truntime=millis()-start;
4
5
if(runtime>=runspeed_get())
6
{
7
return0x80;
8
}
9
return0;
10
}
Um nicht jedesmal rauszuhauen, kann man loop geringfügig modifizieren
1
voidloop()
2
{
3
uint8_tmode;
4
uint8_tset=0;
5
staticuint8_tlen;
6
staticuint8_ti=0;
7
staticuint8_tlast_mode=0xff;
8
staticuint8_t*laufl_prog;
9
10
mode=dipkey_get();
11
if(mode!=last_mode)
12
{
13
laufl_prog=progpointer_get(mode);
14
len=laufl_prog[0];
15
i=0;
16
set=1;
17
last_mode=mode;
18
}
19
else
20
{
21
if(polled_delay())
22
{
23
i++;
24
if(i>=len)i=0;
25
set=1;
26
}
27
}
28
if(set)
29
{
30
sr.setvalue(laufl_prog[i+1],1);// Ausgabe eines Leuchtmusters
Grüß Dich Arduino F.
Du hast natürlich Recht, millis() läuft nach knapp mehr als 2 Tagen über
und deine Korrektur ist absolut richtig (habe ich jetzt geändert):
Grundsätzlich ist auch so etwas hier nicht notwendig (bzw. sogar
"falsch"):
1
void TIMERADC::setstarttime(void)
Ich muß den Klassenbezeichner hier nicht angeben und kann entfallen (was
ich dann auch gemacht habe).
Zu der "Library" sn74hc595.h :
Da das Setzen/Löschen eines Pins genau ein einziges mal vorkommt ist
ein:
> inline void datHigh() { digitalWrite(dat, HIGH); }
nicht notwendig und kann entfallen, wenn bei der Ausgabe dann direkt
digitalWrite verwendet wird.
Du hast das so gemacht:
Arduino F. schrieb:> void setValue(const uint8_t value, uint8_t)> {> digitalWrite(stb, LOW);> shiftOut(dat, clk, MSBFIRST, value);> digitalWrite(stb, HIGH);> }
und das funktioniert natürlich. Weil ich - wie du weißt - nicht wirklich
Arduinoprogrammierer bin, kannte ich shiftOut schlichtweg nicht. Hier
ist es sogar egal, (was mir mehr liegt) ob die Strobeleitung nach dem
shiftOut komplett low-high gesetzt wird, was bei mir notwendig ist, da
ich daraus dann tatsächlich eine kleine Erklärung für innerbetrieblichen
Unterricht geben werde um Schieberegister kaskadieren zu können (hier
wird dann nur beim letzten Ausschieben ein Strobe-Impuls gegeben).
Interessanterweise funktioniert shifOut auf AVR erwartungsgemäß korrekt,
aber auf einem CH32V003 mit entsprechendem Core nicht (die "Library"
hier jedoch schon). Aus diesem Grund verwende ich jetzt dann doch eher
sn74hc595.
Arduino F. schrieb:> Mal abgesehen von dem Stil, der nicht Ardoinotypisch ist,
Hier wird es schon etwas schwieriger! Ich denke mir schon, dass das
nicht arduinotypisch ist und ich habe mir überlegt gehabt, wie man einen
Event-Handler arduinotypisch anlegen könnte / kann und bin auf keine
Idee gekommen.
Der grundsätzliche Gedankengang ist ja, dass der Handler in der loop
immer wieder aufgerufen wird und die Funktionalitäten im Handler
gestartet werden und eben nicht in der loop.
Das einzige was ich mir hier vorstellen kann ist, dass der komplette
Handler in die loop gesetzt wird und alles nach dem do-while ist
idle-Mode und dort kann weiteres hinzugefügt werden. Für mich stellt
sich hier die Frage, ob das dann nicht noch unübersichtlicher wird.
Grundsätzlich freut es mich jedoch, dass der Handler so wie er ist,
tatsächlich funktioniert. Natürlich wird bspw. das Einlesen eines
Strings von uart, grundsätzlich wieder anderst vorgenommen, als
arduinotypischerweise Serial.readln (welches meinen Handler blockieren
würde).
Wenn du hier andere Gedankengänge / Ansätze hast würde ich mich schon
darüber freuen, diese zu lesen!
Ralph S. schrieb:> Du hast natürlich Recht, millis() läuft nach knapp mehr als 2 Tagen über> und deine Korrektur ist absolut richtig (habe ich jetzt geändert):
... natürlich sind es 49 Tage: (2^32 / 86400) / 1000 = 49,71 Tage
Veit D. schrieb:> Serial.readIn() gibt es nicht.
du hast Recht, ich meinte aber eher: Serial.readString,
Mache einmal das hier:
[code]
String input;
.... in Setup
input.reserve= maxbufferlen;
input= "";
void loop()
{
event_handler();
// hier alle dem Event-Handler nachgeordneten Funktionen einfuegen
if (Serial.available())
{
input = Serial.readString();
Serial.print("Eingegangener String war: ");
Serial.println(input);
Serial.print("\n\r> ");
input= "";
}
}
[code]
dann wirst du feststellen, dass, so es keine Aktivität auf uart gibt,
die Timer korrekt laufen. Gibst du ein Zeichen auf der Konsole ein
(nicht der Monitor von Arduino), muß zum Einen sehr langsam getippt
werden und zum anderen wird das Einlesen eines Strings bisweilen von
einem NICHT gesendeten CR Zeichens der String abgeschlossen.
Außerdem hält hier das Lauflicht dann immer wieder einmal an.
Von daher ist es - für mich - besser, man erzeugt eine eigene
Stringlesefunktion, verwendet NICHT die Klasse String und hat dann als
"Regelverstoß" Arduino einen Mischmasch aus C, C++ und
Arduinoeigenheiten (weil klassischerweise ein char stringbuffer[maxlen]
verwendet wird).
Der Eventhandler liest immer nur ein Zeichen und setzt ein Flag, wenn
ein String komplett eingelesen ist. Hier ist dann String natürlich ein
Array of Char und kein Objekt der Klasse String. Den Eventhandler könnte
man jetzt in der Art und Weise modifizieren, dass eine Funktion das
gesetzte Flag strreadln_ready ausliest welches dann wiederum in
event_scan ein Event auslöst. Hier müsste dann im Eventhandler als
eigenes Event reagiert werden und wäre dann - entgegen den
Arduino-Paradigmen - wieder nicht in loop zu sehen.
Ralph S. schrieb:> wird das Einlesen eines Strings bisweilen von> einem NICHT gesendeten CR Zeichens der String abgeschlossen.
Welch ein Unsinn .....
Ralph S. schrieb:> Außerdem hält hier das Lauflicht dann immer wieder einmal an.
Serial.readString() ist blockierend.
Bis zum Zeilenende oder zum Timeout.
Ist also für deine Zwecke unbrauchbar.
String ist ok, solange genug Speicher dafür da ist.
Mein Rat:
Implementiere die "weak Function" serialEvent()
Lese mit Serial.read() ein!
Auch Serial.available() brauchst du nicht.
Arduino F. schrieb:> Ralph S. schrieb:>> wird das Einlesen eines Strings bisweilen von>> einem NICHT gesendeten CR Zeichens der String abgeschlossen.>> Welch ein Unsinn .....
Kein Unsinn, denn, wie du hier schreibst:
Arduino F. schrieb:> Bis zum Zeilenende oder zum Timeout.
Wird das durch Timeout automatisch erzeugt.
Grundsätzlich: Hier geht es nicht um Serial.read oder .print, sondern
darum, einen Event-Handler zu verwenden um blockierendes zu vermeiden.
Aber ich erkenne, dass das alles nicht so wirklich zur
Arduino-Philosophie passt.
Arduino F. schrieb:> Mein Rat:> Implementiere die "weak Function" serialEvent()> Lese mit Serial.read() ein!>> Auch Serial.available() brauchst du nicht.
Mag sein, dass das so funktioniert. Die Methode einen eigenen Puffer zu
haben finde ich dennoch übersichtler. Grundsätzlich habe ich das
"eingefügt" um zu zeigen, dass der Event-Handler eben nichts blockiert
und da war mir Serial.available ganz recht...
Leider leider leider bin ich jedoch jetzt "angetriggert", was man damit
alles anstellen kann, ob und wie ich das gesamte Dokumentiere ( :-) mit
dem Hinweis: "Nicht ganz Arduino konform" ) ... und ich bin am
Überlegen, aus den Softwaretimern eine Library zu machen um den Sketch
übersichtlicher zu machen. Außerdem würde hier dann meine Softwareuhr,
basierend auf den Sekunden, die seit dem 01.01.1970 vergangen sind,
relativ gut passend (mit Ausgleichssekunden für falsch laufende Quarze).
Grundsätzlich jedoch vielen lieben Dank (genau so gemeint) für die
Anmerkungen von dir, sehr hilfreich um das Framework Arduino besser zu
verstehen (und einige Vorbehalte und Voruteile auszuräumen). Ob ich
allerdings ein "Fan" von Arduino werde, bleibt dennoch fraglich.
Interessant ist es allemal, abseits von blink, delay und digitalWrite.
Ralph S. schrieb:> Grundsätzlich: Hier geht es nicht um Serial.read oder .print, sondern> darum, einen Event-Handler zu verwenden um blockierendes zu vermeiden.
Ich weiß!
Wenn du die falsche Methodik anwendest, schießt du dir selber ins Knie.
Ralph S. schrieb:> Aber ich erkenne, dass das alles nicht so wirklich zur> Arduino-Philosophie passt.
KA, was du damit meinst....
Ich kann dir zeigen, wie sowas bei mir aussehen könnte:
Ralph S. schrieb:> bin am Überlegen, aus den Softwaretimern eine Library zu machen
für wen?
Ralph S. schrieb:> ob und wie ich das gesamte Dokumentiere
für wen?
Ralph S. schrieb:> Kein Unsinn, denn, wie du hier schreibst:
Du haust dir selber mit dem Hammer auf den Daumen.
Und beschwerst dich dann, dass es weh tut.
Mag sein, dass dir das gefällt, aber ich halte das für unsinnig.
Arduino F. schrieb:> switch(in)> {> case '\r': /* fallthrough */> case '\n': if(input.length())> {> Serial.println(input);> input = "";> }> break;> default: input += char(in);> }
Das hier ist prinzipiell das, womit ich leben kann / könnte und
zumindest von der Methodik her nicht so wirklich anderst, als das, wie
mir das vorschwebt. Hmmm... Nur dass du dann dann ein Objekt String
(großgeschrieben) mit seinen eigenen "Verwaltungsmethoden" hast. Dieses
dürfte dann einer der Gründe sein, warum das ganze irgendwann zu einem
Resourcenfresser wird (und warum die Boards für Arduino immer größer
werden). Ich schaue mir mal an, was die class String so alles zu bieten
hat, in Arduino ist ja scheinbar die <string.h> verpönt.
Ralph S. schrieb:> in Arduino ist ja scheinbar die <string.h> verpönt.
Ist sie nicht!
Leider ist bei dem AVR-GCC die libstdc++ nicht dabei.
Damit gibts kein std::string
Verpönt ist nicht das gleiche, wie unmöglich.
Die 32Bit und 64Bit Arduinos oder auch Fremdprodukte haben std::string
durchaus dabei.
Ralph S. schrieb:> Nur dass du dann dann ein Objekt String> (großgeschrieben) mit seinen eigenen "Verwaltungsmethoden" hast. Dieses> dürfte dann einer der Gründe sein, warum das ganze irgendwann zu einem> Resourcenfresser wird (und warum die Boards für Arduino immer größer> werden).
Ähh....
Du hast eine rege Fantasie!
Keiner sagt, dass du String verwenden musst.
Du kannst durchaus deine heiß geliebten C-Strings verwenden.
In Arduino kannst du alles verwenden, was in C/C++ ASM geht.
Das schöne ist, dass String unendlich oft getestet wurde.
Und z.B. RAII implementiert.
Soweit ich mich erinnern kann, sagt sizeof 6 Byte zu String
Ralph S. schrieb:> in Arduino ist ja scheinbar die <string.h> verpönt.
In der Arduino.h findet sich
#include <string.h>
Die Nutzung der dortigen Dinge ist also standardmäßig
aktiviert/vorbereitet.
Habe keine Hemmungen, das zu nutzen.
Auch String bedient sich da.
Ralph S. schrieb:> Nach meinen Kriterien hätte ich 1,5 gegeben ... auch wegen> "Flüchtigkeitsfehler" in den Kommentaren:
Er hat's gut kommentiert und die würde ich gar nicht bewerten, es sei
denn es war in der Aufgabenstellung verlangt.
Wenn die Aufgabenstellung wie gefordert umgesetzt wurde, dann ist das
ein sehr gut, also besser als 1,5 und wenn da besondere Schmankerl
eingebaut wurden, dann ist das halt noch ein bissel besser eine 1,3 oder
1,2.
Warum muß bei Projekten immer das Haar in der Suppe gefunden und die
Arbeit dann überproportional abgewertet werden.
Ich kenne das noch als meine Tochter zur Schule gegangen ist. Wenn dort
ein Projekt anlag, dann war da nie mehr als eine 2 drin - irgendwas hat
der Lehrer immer gefunden und da waren Dinge dabei die an den Haaren
herbeigezogen waren.
Wenn eine 1 niemals erreichbar ist, dann ist das wenig motivierend und
wir müssen uns nicht wundern, wenn die jungen Leute die Lust verlieren.
Hallo Ralph,
Arduino typisch ist eigentlich setup() und loop(). Daran erkennt man das
Arduino Framework. Ob man dann die vorhandenen Libs/Funktionen/Methoden
verwendet, das ist einem selbst überlassen, vereinfacht jedoch vieles.
Echte Strings machen nur Probleme, wenn man reserve() nicht verwendet
bzw. zu klein gewählt wurde und dann den String ständig modifiziert.
Halte dich an das Gesagte von Arduino F.
Noch ein Bsp. ohne String mit char Array, ganz klassisch. Die Funktion
readline() ist wiederverwendbar, also unabhängig der Schnittstelle und
Buffer.
1
Stream&cout0{Serial};
2
Stream&cout3{Serial3};
3
4
constexprbyteREAD_BUFFER_SIZE{20};
5
6
structSerialDaten{
7
charbuffer[READ_BUFFER_SIZE+1];// Platz für 20 Zeichen + Null-Terminator
8
size_tindex{0};
9
};
10
11
SerialDatenrx0Daten;
12
SerialDatenrx3Daten;
13
14
voidsetup()
15
{
16
Serial.begin(9600);
17
Serial3.begin(9600);
18
}
19
20
voidloop()
21
{
22
// liefert true wenn das LF eingelesen wurde
23
if(readLine(cout0,rx0Daten)){
24
cout0.print("Eingelesen cout0: ");
25
cout0.println(rx0Daten.buffer);
26
}
27
28
if(readLine(cout3,rx3Daten)){
29
cout3.print("Eingelesen cout3: ");
30
cout3.println(rx3Daten.buffer);
31
}
32
}
33
34
boolreadLine(Stream&stream,SerialDaten&rx)
35
{
36
boolstatus{false};
37
38
while(stream.available()){
39
constcharc=stream.read();
40
if(c=='\n'){// wenn LF eingelesen
41
rx.buffer[rx.index]='\0';// String terminieren
42
rx.index=0;
43
status=true;// String fertig eingelesen
44
}
45
elseif((c>=32)&&(rx.index<READ_BUFFER_SIZE)){// solange noch Platz im Buffer ist
46
rx.buffer[rx.index++]=c;// Zeichen abspeichern und Index inkrementieren
47
}
48
}
49
returnstatus;
50
}
Nochwas, eine Bitte an dich selbst. Lass einmal dein negatives Gerede
weg. Wenn dich Arduino nervt dann lasse es. Wenn du damit umgehen
möchtest, dann lerne es. Kann ja nicht so schwer sein wenn man DMA
beherrscht. ;-) Wenn sich jemand immer wieder über irgendwas beschwert,
irgendwelche Kleinigkeiten, die gar keine Rolle spielen bzw. falsch
sind, bspw. Serieller Monitor oder wegen Strings angeblich größer
werdende Boards, dann nervt das und man verliert die Lust noch irgendwie
überhaupt Hilfe zu leisten.
Hallo,
noch ein anderes Bsp. für Events, wenn das millis() Intervall gültig
wird. 0xEFFFFFFF ist eine künstliche "Überhöhung", damit gleich nach µC
Reset das Event ausgelöst, statt mit 0 initialisiert. Macht etwas
sinnvolles damit. :-)
Veit D. schrieb:> Nochwas, eine Bitte an dich selbst. Lass einmal dein negatives Gerede> weg. Wenn dich Arduino nervt dann lasse es. Wenn du damit umgehen> möchtest, dann lerne es. Kann ja nicht so schwer sein wenn man DMA> beherrscht. ;-)
Einen Vorschlag zur Güte (weil du hier gerade tatsächlich Recht hast):
Ich lasse das weg und Du läßt es, mich wie einen Stümper dastehen zu
lassen. Das wäre doch glatt eine Win-Win Situation. Außerdem habe ich ja
auch gesagt, dass ich bestimmte Vorurteile gegenüber Arduino beiseite
schiebe und manche Dinge darin "gar nicht schlecht sind" (und das von
jemandem - der sich bisher dagegen gesträubt hat, schlicht weil ich
viele Beispiele von Leuten gesehen habe, die wohl wirklich absolutes
Anfängerniveau haben. Was ich explizit von Dir und Arduino absolut NICHT
behaupte. Ihr seid offensichtlich extrem tief in dieser Materie drin).
Hand zur Güte reiche!
Hallo Ralph,
es war nie meine Absicht dich als Stümper o.ä. dastehen zulassen.
Wirklich. Ich sprach nur direkt an was mir auffiel. War zu direkt, okay,
habe es verstanden. Ich habe das auch nie für mich so böse gesehen,
deswegen habe ich auch im Thread weiterhin gelesen und geantwortet.
Okay, manchmal wollte ich dich necken, aber eher zum Spass. Habe
verstanden, kam nicht so gut an.
Handshake von mir jederzeit. Kein Problem. Ich werde versuchen weniger
direkt zu sein. :-)
Hallo Ralph,
ich hatte mich nochmal hingesetzt und mir Gedanken gemacht wie man das
vielleicht aufgeräumter hinbekommt. Das Schiebregister habe ich
weggelassen, ich denke das Schema wird auch so ersichtlich. Hier nutze
ich Lambda Funktionen, sodass am Ende in der loop nur immer eine Timer
Methode Namens update() aufgerufen werden muss.
Hier im Bsp. werden mit 50ms Entprellzeit die DIP Switche abgefragt.
Im 100ms Rhythmus wird das Poti eingelesen und gefiltert.
Im 1s Rhythmus wird ein aktueller Wert Serial ausgegeben.
Das kann man fortführen oder auch nicht. :-)
Man kann Hunderte DIP Switch Instanzen anlegen.
Man kann Hunderte Poti Instanzen anlegen.
Verknüpft diese mit einer Timer Instanz und lässt sie ihr Ding machen.
Das Einzigste was Arduino Nutzer machen müssen, ist eine Compiler
Einstellung auf C++17 statt Standard C++11.
Dort wo die platform.txt liegt eine platform.local.txt anlegen und diese
Zeile einfügen.
Veit D. schrieb:> ich hatte mich nochmal hingesetzt und mir Gedanken gemacht wie man das> vielleicht aufgeräumter hinbekommt.> template<uint8_t pin, uint8_t FF>> …> ** FF = Filterfaktor;
1
template<uint8_tpin,uint8_tFilterfaktor>
Selbstdokumentierender Code macht’s einfacher.
Oliver
Oliver S. schrieb:> Filterfaktor
FilterFactor
English ist zu bevorzugen.
Machts für den Rest der Welt leichter zu lesen.
Die KamelHöckerSchreibweise hilft Missverständnisse zu vermeiden.
Hallo,
muss noch eine kleine Korrektur erledigen. newValue in der AnalogRead
Klasse war "doppelt". Habe mich dabei für die Beibehaltung von
readAnalog() entschieden.
Hallo,
ich wollte soeben das Programm erweitern, da fiel mir auf, dass das
Timing nicht stimmt. Eigentlich hatte ich damit noch nie Probleme. So
schief kann der Resonator vom Arduino Mega2560 Board nicht takten.
Daraufhin habe ich den Sketch auf das Minimum reduziert und das Problem
bleibt. Das Intervall von 1s ist meistens kürzer und zwischendrin 20,
30ms länger. Solche Abweichungen mit so einem simplen Sketch sind mir
bis heute nicht bekannt. Das es manchmal paar ganz wenige ms größer ist
normal, aber kürzer? Übersehe ich irgendwas? Oder täuscht mich alles und
es ist normal so?
1
classSimpleTimer
2
{
3
private:
4
unsignedlonglastMillis{0xEFFFFFFF};// provoziert eine sofortige Auslösung nach uC Reset
Wenn ich das richtig sehe, dann misst du zwar deinen PC, das
Betriebssystem, die Datenverbindung und die IDE.
Was du nicht misst ist die Gleichförmigkeit des µC selbst.
Die USB-Verbindung zum PC? Da hab ich auch schon ein paarmal "größere"
Abweichungen beobachtet.
Wolltest du das nicht unbedingt ohne blockierendes Warten bauen? ;)
Sorry, aber das war eine Steilvorlage ;)
Lass doch einen Pin wackeln und messe mit dem Scope.
900ss schrieb:> Die USB-Verbindung zum PC? Da hab ich auch schon ein paarmal "größere"> Abweichungen beobachtet.
Ernsthaft? Gibt's Erkenntnisse weshalb das passiert?
Hier getestet, Daten kommen auf die Millisekunde genau an.
Norbert schrieb:> Ernsthaft? Gibt's Erkenntnisse weshalb das passiert?> Hier getestet, Daten kommen auf die Millisekunde genau an.
Also ich bin mir ziemlich sicher dass ich das auch bei mir schon
beobachtet habe und ich schließe da den Fehler des absendenden uC aus.
Und ich habe es auch mit Linux und irgendeinem USB-seriell Wandler
laufen gehabt. Du hast wahrscheinlich einen Raspberry Pi Pico genommen?
Aber da du ja schon ein Testprogramm gepostet hast fühle ich mich jetzt
genötigt das zu testen. ;) Aber vermutlich nicht mehr heute. Aber
morgen.
900ss schrieb:> Du hast wahrscheinlich einen Raspberry Pi Pico genommen?
Ich bin nun mal ein zutiefst müßiger Mensch! ;-)
Ohne RP2xxx USB, dafür über UART und Seriell<->USB Kabel (PL2303).
Gleiches Ergebnis.
Anderer PC, anderes Debian (13,Trixie), anderer PICO (China Klon)
Gleiches Ergebnis, na ja fast, 2ms Varianz (vmtl. wegen der laufenden
OBS Aufnahme)
Hab die Änderung für UART mal angehängt.
Veit D. schrieb:> Was mich besonders stutzig macht ist die Abweichung kleiner dem> Intervall.
Wenn die davor liegenden (noch stärker) verzögert waren, kommt das hin.
Norbert schrieb:> Hier getestet, Daten kommen auf die Millisekunde genau an.
Ist bei mir unter Linux hier auch so. Gesehen hab ich es aber schon.
Aber was da dann der Grund war kann ich jetzt auch nur in die Glaskugel
schauen.
Wenn ich noch genau wüsste bei welcher Spielerei, hätte ich es auch
nochmal ausprobiert.
Aber egal, einen Portpin schalten und das mit dem Scope zu messen ist
dann die sichere Variante das Timing zu testen.
Hallo,
also Pin Toggle passt. Oszi zeigt stabile Werte an. Soweit alles normal.
Also erzeugt Windows eine Miniverzögerung. Hätte ich jetzt nicht
gedacht. Danke.
Edit:
Also nur an Windows liegt es nicht. Wird wohl allgemein am OS hängen.
Denn unter Fedora KDE habe ich ähnliches Verhalten. Generell immer
leichter unter 1s. Oben sieht einen Sprung .245 > .237 > .265, weiter
runter Mitte erneut .237 > .265
Veit D. schrieb:> Hallo,>> also Pin Toggle passt. Oszi zeigt stabile Werte an. Soweit alles normal.> Also erzeugt Windows eine Miniverzögerung. Hätte ich jetzt nicht> gedacht. Danke.>> Edit:> Also nur an Windows liegt es nicht. Wird wohl allgemein am OS hängen.> Denn unter Fedora KDE habe ich das gleiche Verhalten.
Vielleicht hat's auch einfach nur mit dem Verhalten der Arduino IDE zu
tun.
Schon mal alternativ mit CuteCom und dessen Timestamp Mechanismus
getestet?
Hallo Norbert,
es ist deutlich stabiler, aber nicht so astrein wie bei dir.
Ist schon irgendwie irre. ;-) Danke für den Tipp.
Ich glaube die Beweisaufnahme ist damit abgeschlossen.
Hallo,
habe es erweitert. Wirkt vielleicht etwas kompliziert, mag sein, dient
aber nur einem handfesten Zweck, keine händische Berechnung und
Eintragung im Array für irgendwelche Array Größen für das eigene Array.
Das ist der Ursprungsgedanke für den Aufwand. Daraus folgend ist der
Programmcode der das selbstständig erledigt. Vielleicht gibt es hier und
da noch Ecken wo man aufräumen könnte, mag alles sein. Der Knackpunkt
war der Umgang mit unterschiedlichen Array Größen. Im Lambda Ausdruck
der Instanz timerLauflicht oder einer extra Funktion müsste dann die
Übergabe des aktuellen Wertes an das echte Schieberegister erfolgen. Das
was aktuell mit Serial "BMP 0x" ausgegeben wird. Wenn man am Poti dreht
ändert sich die Ausgabegeschwindigkeit und wenn man die DIP Switche
ändert (ich drücke Tasten), wechselt das Array woraus die Werte
ausgelesen werden.
Mehr mach ich nicht, abgesehen von Fehlerbehebung. ;-)
Hmmmm... Veit, ich habe da so etwas draus gemacht (und ist noch nicht
vollständig dokumentiert... wollte ich aber erst gar nicht hier
einstellen, jetzt aber doch)...
Wenn ich die Doku fertig habe, werde ich das als Projekt hier
veröffentlichen... hier jetzt aber nur mal (die größere Menge)
Sources....
... mit dem eigentlichen Sketch, der die Libs halt eben braucht ...
Eventsources spielen da eine Rolle, bei dem Gedanken von Arduino F. von
dem Thread hier mit reinfließen.
Das ganze ist ein "Interruptloses eventgesteuertes System" welches
nichtblockierend ist und auf einem Terminal (nicht Serialmonitor aus
Arduino) Kommandos entgegen nehmen kann und auf die der Controller
reagiert.
Es wird gesteuert, ob die Eingabezeile den "Fokus" hat oder eine
eventuell laufende Funktion. Grundsätzlich wird zudem aus millis() eine
Hardwareuhr gebildet, die sich an der Unix-Zeit und dem Zeitstempel aus
Unix orientiert. Im übrigen (getestet) läuft die uhr nach 5 Tagen ca. 8
bis 10 Sekunden falsch, was wohl dem Quarz des Arduino geschuldet ist
(ich hatte das schlechter erwartet).
smile , ich weiß: eine Menge Dateien und eine Menge zu kritisieren.
Mir ging es hier um das eventgesteuerte System.... prinzipiell habe ich
ähnliches mit einem STM32F4 mit Interrupts schon gemacht.
Und ja, das ist einfach nur eine Demo.... smile, wie du weißt: ich lerne
jetzt sogar noch Besonderheiten von Arduino... meinen Programmierstil...
gewöhnt man mir in meinem Alter nicht mehr ab.....
Und grundsätzlich: das hier ist prinzipiell an das uralte TurboVision
System aus Borland C++ angelehnt.... Eventnumber, Eventhandler, Idle
.... und er Interrupt wird durch eventscan ersetzt, der praktisch
permanent pollt, ob ein Event (gerne von millis() ausgelöst) aufgetreten
ist.
Bernd N. schrieb:> Frage mich, welche Schulnote es nun gibt?
stand irgendwo oben, er hatte eine 3 bekommen.
Bernd N. schrieb:> Aber wenigstens weiß ich nun> warum man einen STM-32 für ein Lauflicht nimmt :-). da geht bestimmt> noch mehr.
es ging hier nicht um die Hardwareplattform, für ein Lauflicht reicht
jeder Controller, von PFS154 über MCS-51 ..... oder jeder Controller der
in Arduino funktioniert (dann fallen PFS154 und MCS-51 raus, weil es für
die keinen Core gibt der C++ kann)
Ralph S. schrieb:> stand irgendwo oben, er hatte eine 3 bekommen.
Hast du denn den Lehrer mal gefragt, was man hätte besser machen können,
und was für eine 2 oder gar 1 erwartet wurde?
Oliver
Oliver S. schrieb:> Ralph S. schrieb:>> stand irgendwo oben, er hatte eine 3 bekommen.>> Hast du denn den Lehrer mal gefragt, was man hätte besser machen können,> und was für eine 2 oder gar 1 erwartet wurde?>> Oliver
Genau das hätte mich auch interessiert, was der Lehrer hätte sehen
wollen.
Hallo Ralph,
sieht erstmal okay aus. Haste dir Mühe gegeben. :-)
Du verwendest viel constexpr, sehr schön, da kannst du die letzten
define Variablen auch constexpr machen. ;-)
Beim kompilieren fallen paar Dinge auf, die zukünftig Probleme bereiten
können.
Ralph S. schrieb:> bei dem Gedanken von Arduino F. von> dem Thread hier mit reinfließen.
Ich danke dir für die Erwähnung.
Muss aber bemerken, dass du nicht viele meiner Vorschläge übernommen
hast.
Das ist natürlich kein echtes logisches/Programm Problem. Aber dennoch
etwas überraschend für mich. Obwohl du vorher irgendwann mal gesagt
hast, dass du deinen Stil gegen alle Widerstände beibehalten willst.
Schlussendlich, alles OK, denn es ist ja dein Programm, und nicht meins.
Arduino F. schrieb:> Ich danke dir für die Erwähnung.>> Muss aber bemerken, dass du nicht viele meiner Vorschläge übernommen> hast.
Sagen wir es einmal so: es gab da schon einige Sachen die ich da im
Hinterkopf hatte... fängt mit der loop an (kein while (1) dort)...
irgendwo anderst nicht hier , hast du geschrieben: würde den stream
erwarten ... von daher. Zudem habe ich mir bspw. die Klasse String
angesehen und du meintest es wäre absolut erlaubt, meine "heißgeliebten
Ascii-Z Strings" zu verwenden. Außerdem habe ich angefangen in einem
anderen "Projekt" doch tatsächlich auch innerhalb eines Sketches eine
Klasse zu definieren (und nicht nur in einer Lib). Allerdings weiß ich
nicht, ob Anfänger damit zurecht kommen (die Rückmeldungen die ich da
habe sind eher nicht positiv) . Einige deiner Vorschläge behalte ich im
Hinterkopf, wenn es um Arduino geht. Grundsätzlich hat sich dafür meine
Meinung über Arduino geändert. Die Prämisse heißt nicht mehr Arduino
gegen Embedded oder C oder ähnlich, sondern eher "Parallelexistenz" ....
(auf anderer Ebene praktiziere ich das bspw. auch: Nicht Delphi
(Lazarus) oder C++ (QT5), sondern sowohl als auch.
@Veit... hier ging es mir in erster Linie um das "Eventsystem" ... die
anderen Teile sind schon älter und die werde ich wohl alle noch, wenn
Sinnvoll, umarbeiten...
Veit D. schrieb:> Das halte ich für gefährlich. Was passiert wenn v Parameter 0 ist?void> dice_show(uint8_t v)> {> uint16_t m = diceint[v - 1];> textcolor(v+8);> for (int i = 0; i < 15; i++)> {> if (m & (1<<(15-i))) printf("o"); else printf(" ");> if (i % 5 == 4) printf("\n\r");> }> textcolor(7);> printf("\n\r");> }
:-) zum einen ist das ja "nur" Demo für das Eventsystem und zum anderen
seh dir an, wer dice_show aufruft und unter welchen Bedingungen. Von den
Zufallsbedingungen wird dice_show niemals mit 0 aufgerufen werden, aber
natürlch könnte man den Fall "0" abfangen, die Frage lautet nur: warum,
wenn 0 nicht auftritt.
Anderst wäre es, wenn das ein universelles Modul wäre oder dergleichen.
Hast du dir das Teil angesehen in einem Terminal?
Ralph S. schrieb:> Allerdings weiß ich> nicht, ob Anfänger damit zurecht kommen (die Rückmeldungen die ich da> habe sind eher nicht positiv) .
Das ist verdächtig!
Erfahrungsgemäß haben absolute Anfänger weniger Probleme mit der OOP als
erfahrene C Leute.
Irgendwie sehe ich das auch in deinem Code.
Vermutlich behindert das auch die Übermittlung von dir zum Anfänger.
Hallo Ralph,
> Hast du dir das Teil angesehen in einem Terminal?
Ich erhalte das "Menü" siehe Bild.
Keine weiteren Ausgaben.
Led13 blinkt. Schieberegister funktioniert, reagiert auf Modiwechsel und
Poti-Geschwindigkeitsänderung. :-)
Mit 'stb' musste ich überlegen, ist eine andere Bezeichnung wie 'LATCH'
bzw. 'STCP'. Du könntest noch eine Resetfunktion mit '/MR' Pin einbauen.
NTC ist nicht dran.
Poti an A0.
Verwendet wird ein Arduino Mega2560.
Soweit so gut.
Warum nichts weiter im Terminal erscheint weiß ich noch nicht.
> Außerdem habe ich angefangen in einem> anderen "Projekt" doch tatsächlich auch innerhalb eines Sketches eine> Klasse zu definieren (und nicht nur in einer Lib). Allerdings weiß ich> nicht, ob Anfänger damit zurecht kommen (die Rückmeldungen die ich da> habe sind eher nicht positiv).
Das lässt sich für Neulinge einfach erklären. Eine Library ist erstmal
nichts weiter wie ausgelagerter Code, meist mit dem Ziel der
Wiederverwendbarkeit. Das betrifft nun einmal vorwiegend Klassen. Wo
diese stehen, ob im Hauptsketch oder Library ist erstmal egal. Meistens
entwickelt man am Anfang im Hauptsketch und lagert es später aus bzw.
wenn die Klasse wächst.
Und eine Struktur, was auch nur eine Klasse ist, nur meistens nicht so
bewusst gesehen wird, hat jeder ziemlich schnell in der praktischen
Anwendung. Und ratz fatz weiß jeder was eine Klasse ist. Ich würde mit
einer Struktur anfangen, diese einfach anwenden, dann Methoden
hinzufügen und wenn das klar ist auf class wechseln und klar machen das
sich die Sichtbarkeit ändert und wie man das steuert. Dann sollte das
schon jeder verstehen, unabhängig wo die Codezeilen lagern.
Grüß Dich Veit,
weil ich hier ja nichts anderes zu tun habe (immer noch nicht zu Hause),
kann ich hier viel experimentieren. Meine Frau hat die richtige Box
mitgebracht in der auch die von mir nicht verwendeten Arduinos drin
liegen, namentlich u.a. ein Arduino Due und ein Arduino Mega2650.
Zudem hat sie mir auch noch das zweite alte Notebook mitgebracht auf dem
Win10 drauf ist (mit dem Kommentar von ihr: du spinnst doch). Wie dem
auch sei, ich habe jetzt ein Testequipment und kann nicht
nachvollziehen, warum in deinem Teraterm-Fenster das nicht geht.
Den Code des Eventhandlers (und nur den) habe ich jetzt einmal leicht
angepasst (und die anderen von dir angemerkten Dinge noch nicht).
Zudem habe ich, weil du Tera Term auf deinem Rechner hast, das hier auch
installiert und das ganze ausprobiert.
Es läuft auf Arduino Uno Nano Due / Mega2650 und CH32V003 (ich weiß
von vor dem Unfall, dass das auch auf STM32 läuft, habe ich aber hier
nicht zum testen).
Hast du im Fenster des Terminals versucht etwas einzugeben? Im Terminal
kannst du eben den Dispatcher ja unterschiedliche Funktionen aufrufen,
den Sketch habe ich dahingehend verändert, dass beim Start angezeigt
wird, welche Kommandos eingebbar sind (während das Blinklicht und das
Lauflicht weiter munter vor sich her werkeln).
So, hier habe ich jetzt das ganze mal mit angehängt, dieses mal als
gezippte Libraries, die du ja wieder einfach löschen kannst, wenn du dir
das ganze angesehen hast.
Eine Library ist etwas umfangreicher die eigentlich gar nicht gebraucht
wird: extended_serial.zip. Sie ist deswegen mit dabei, weil dort 2 .cpp
Dateien enthalten sind, wovon eine benötigt wird, wenn man das ganze für
einen ch32v003 machen möchte.
:-) vllt. hast du ja noch einmal die Muse, das ganze bei dir laufen zu
lassen. Eingebbare Befehle siehst du im Screenshot des Terminalfensters
(ich habe das Kommand "list" mit hinzugefügt).
Gruß,
Ralph
Soweit funktioniert der Sketch. Auf Tasten reagiert er nicht, dafür auf
Terminaleingabe für den Led Moduswechsel. Bestimmt so gewollt.
Und wegen
1
(mit dem Kommentar von ihr: du spinnst doch)
du bist damit sinnvoll beschäftigt und kommst nicht auf dumme Gedanken
mit den Krankenschwestern. ;-) Sie wird dir alles mitbringen was du
möchtest. :-) Wünsche gute Genesung.