Wie im Postingstitel geschrieben werden Arduino und struct in einer .ino Datei nicht wirklich Freunde werden.
Zugegeben (und dafür schäme ich mich mal ausnahmsweise nicht), bin ich ja nun wirklich ein Arduino-Anfänger (und will das so auch bleiben), aber andererseits möchte ich auch, wenn ich schon etwas für Arduino mache, das dann auch halbwegs richtig machen und genauso eben auch verstehen.
Im Moment erzeugt Arduino bei mir (mal wieder) ein Kopfschütteln:
1
typedef struct
2
{
3
int x1, y1;
4
int x2, y2;
5
int upborderattr;
6
int dwnborderattr;
7
int txfieldattr;
8
} txbox_t;
9
10
txbox_t tbox;
11
12
// Arduino braucht diesen Funktionsprototyp, das ist doch bescheuert !
13
void ansi_txbox(const txbox_t *box);
14
// und hier die Funktion selbst, direkt darunter
15
void ansi_txbox(const txbox_t *box)
16
{
17
int x;
18
19
x = box->x1;
20
}
Ehrlich, wie "bescheuert" ist das denn? Und schön aussehen tut's auch nicht! Arduino braucht diesen Funktionsprototypen und warum?
Schlicht deshalb, weil Arduino automatisch Funktionsprototypen vor der Kompilierung generiert. Bei Funktionen mit Struct-Parametern kennt der Compiler den Typ noch nicht und deshalb muss ein Prototyp explizit angegeben werden um einen Fehler beim compilieren/linken:
txbox_t does not name a type.
zu vermeiden.
Ich schreibe einen Funktionsprototypen und darunter dann direkt die Funktion?
Okay, dann kann man das auch noch anderst lösen, verwenden wir halt Zeiger,
aber schön ist das ebensowenig
1
typedef struct
2
{
3
int x1, y1;
4
int x2, y2;
5
int upborderattr;
6
int dwnborderattr;
7
int txfieldattr;
8
} txbox_t;
9
10
// Pointer ist hier ein "Arduino-Hack"
11
typedef txbox_t* ptxbox_t;
12
13
txbox_t tbox;
14
15
// Kein Prototyp notwendig und funktioniert direkt in .ino
16
void ansi_txbox(const ptxbox_t box)
17
{
18
int x;
19
20
x = box->x1;
21
}
Die sauberste Lösung ist dann wohl am ehesten, den struct in eine eigene .h Datei auszulagern, aber: will ein Arduino-User das? Mit mehr als einer Datei hantieren.
Eine Frage an die Cracks (und die Nicht-Anfänger wie mich): wie ist das korrekte Vorgehen?
Wie im Postingstitel geschrieben werden Arduino und struct in einer .ino
Datei nicht wirklich Freunde werden.
Ein lösbares Problem.
mache, das dann auch halbwegs richtig machen und genauso eben auch
verstehen.
Gute Einstellung.
Im Moment erzeugt Arduino bei mir (mal wieder) ein Kopfschütteln:typedef
struct
{
int x1, y1;
int x2, y2;
int upborderattr;
int dwnborderattr;
int txfieldattr;
} txbox_t;
txbox_t tbox;
Zeig und VOLLSTÄNDIGEN, compilerbaren Quelltext als Anhang.
// Arduino braucht diesen Funktionsprototyp, das ist doch bescheuert !
Nein, das ist es nicht. Wer C mal verstanden hat, weiß auch warum.
Ehrlich, wie "bescheuert" ist das denn? Und schön aussehen tut's auch
nicht! Arduino braucht diesen Funktionsprototypen und warum?
Laber nicht rum! Das habe sich sehr schlau Leute vor verdammt langer Zeit ausgedacht. Es hat seinen Sinn! Wenn man die Funktionen in eine Datei packt, braucht man nicht unbedingt Prototypen. Wenn man die Funktionen aber in mehrere Dateien aufteilt, braucht man sie, denn andere Dateien müssen wissen, wie die Funktionen aufgerufen werden. Also natürlich der Compiler, wenn er eine Datei compiliert.
Schlicht deshalb, weil Arduino automatisch Funktionsprototypen vor der
Kompilierung generiert. Bei Funktionen mit Struct-Parametern kennt der
Compiler den Typ noch nicht und deshalb muss ein Prototyp explizit
angegeben werden um einen Fehler beim compilieren/linken:
Und wo liegt das Problem? Der Rest der Welt hat keins damit.
txbox_t does not name a type.
zu vermeiden.
Ich schreibe einen Funktionsprototypen und darunter dann direkt die
Funktion?
Nö. Man schreibt Header files und bindet die per #inlcude ein. Dort gehören auch die Typdefinitionen rein.
Die sauberste Lösung ist dann wohl am ehesten, den struct in eine eigene
.h Datei auszulagern,
BINGO!
aber: will ein Arduino-User das? Mit mehr als
einer Datei hantieren.
Er wird es lernen müssen. Ist wohl nicht zuviel verlangt.
Arduino ist C++ nicht C, zumindest in *.ino, *.pde und *.cpp Dateien.
C++ kann zwar noch typedef, aber typedef ist in den allermeisten Fällen nicht nötig, oder auch sinnig.
Vor struct ist es flüssiger als Waser.
Sie restlichen typedef lassen sich gerne durch using ersetzen.
Wie im Postingstitel geschrieben werden Arduino und struct in einer .ino
Datei nicht wirklich Freunde werden.
Eine *.ino-Datei ist keine cpp oder c Datei. Die hat ein paar spezielle Eigenheiten um den Syntax für die Arduinonutzer zu vereinfachen.
Du kannst aber in jedem Arduinoprojekt eine *.cpp, *.h, *.c Datei anlegen per "#include" einbinden (bei *.c "extern C" nicht vergessen). Dann verhält sich das Projekt genau wie bei jedem anderen C- oder cpp Projekt.
Um alle Arduino-Defines verfügbar zu haben, brauchst du dann noch #include "Arduino.h".
Wenn du wirklich Hilfe suchst, würde ich dir dringend empfehlen hier etwas weniger überheblich aufzutreten. Glaub mir, die Allermeisten hier brauchen deine Hilfe definitiv nicht (und der Angesprochene schon gar nicht).
Und im Übrigen sollte jemand, der so selbstbewusst daher kommt wie du, zumindest die Grundlagen der verwendeten Programmiersprache beherrschen.
Die sauberste Lösung ist dann wohl am ehesten, den struct in eine eigene
.h Datei auszulagern, aber: will ein Arduino-User das? Mit mehr als
einer Datei hantieren.
Erst den richtigen Weg erkennen, und danach, im gleichen Satz, voll das Arduino Bashing.
Also Nein!
Nicht alle Arduino User sind so blöd wie du dir das wünscht!
Aha. Man muss also Sachen die lediglich in einer Datei verwendet werden
und die Benutzer nichts angehen, veröffentlichen.
Boar, gibt selten Leute denen ich empfehle es einfach sein zu lassen.
Aber wer sogar zu doof ist ne lokale Datei anzulegen und zu verwenden gehört definitiv dazu.
Leg die .h mit in deinen Sketchorder:
1
#include "ZuDoofUmPunktHEinzubinden.h"
Und freu dich das die Funktionen in deiner .ino verfügbar sind!
Und statt struct nimmt man dann eine class. Die bietet einige Vorteile.
Welche? struct und class machen genau das Gleiche, nämlich eine Klasse definieren. In C++ gibt's keine structs, nur Klassen. Das "struct"-Keyword ist fast ein Alias für das "class" Keyword. Bei struct sind die Member per default public, und ich glaub es werden IIRC ein paar default Konstruktoren angelegt... Aber im Endeffekt kann man mit beiden Keywords exakt das gleiche erzielen.
Man kann "struct" zur Dokumentation nutzen um anzudeuten dass es sich um eine simple "Datenklasse" handelt, eben so wie man struct in C verwendet.
Aha. Man muss also Sachen die lediglich in einer Datei verwendet werden
und die Benutzer nichts angehen, veröffentlichen.
Boar, gibt selten Leute denen ich empfehle es einfach sein zu lassen.
Was war jetzt nochmal dein Argument dafür unnötig lokale Informationen nach aussen hin sichtbar zu machen?
Dummheit? Datenkapselung? Schlechte Interfaces?
Was war jetzt nochmal dein Argument dafür unnötig lokale Informationen
nach aussen hin sichtbar zu machen?
Google mal ob du meine lokalen includes irgendwo in Arduino oder online findest! (Tipp: du wirst Jahrhunderte suchen und meine Dateien nicht finden! Außer der VapeDisplayDriver.h und fontandcolor.h , die liegen hier im Forum im Beitrag zur 25k Vape.)
Natürlich kannst du struct Definitionen auch in *.cpp Dateien
verstecken.
OK. Man kann und soll sogar.
Aber sonderlich sinnvoll ist das meist nicht.
Wenn man sich keine Gedanken zu seinen Interfaces macht, dann kann man das so sehen.
Wenn ich nochmal auf Datenkapselung hinweisen darf?
Das Konzept wird ja noch weitergeführt in OOP. Nach aussen hin so wenig wie möglich und nur so viel wie nötig preisgeben. Andere Sprachen ermöglichen sogar lokale Funktionen/Prozeduren. Das erhöht die Lesbarkeit und Wartbarkeit. Manchen mag das egal sein, Hauptsache es läuft.
Oder verwendest du nur globale Variablen, statt lokaler (ggf. sogar nur innerhalb eines Blocks)?
Ich nehme mal an, dass nicht. Aber dann gilt das gleiche Argument auch für die header.
Natürlich kannst du struct Definitionen auch in *.cpp Dateien
verstecken.
OK. Man kann und soll sogar.
Aber sonderlich sinnvoll ist das meist nicht.
Wenn man sich keine Gedanken zu seinen Interfaces macht, dann kann man
das so sehen.
Wenn ich nochmal auf Datenkapselung hinweisen darf?
Das Konzept wird ja noch weitergeführt in OOP. Nach aussen hin so wenig
wie möglich und nur so viel wie nötig preisgeben. Andere Sprachen
ermöglichen sogar lokale Funktionen/Prozeduren. Das erhöht die
Lesbarkeit und Wartbarkeit. Manchen mag das egal sein, Hauptsache es
läuft.
Oder verwendest du nur globale Variablen, statt lokaler (ggf. sogar nur
innerhalb eines Blocks)?
Ich nehme mal an, dass nicht. Aber dann gilt das gleiche Argument auch
für die header.
Lern erstmal, den Unterschied zwischen "Definition" und "Deklaration" zu verstehen, bevor du dich hier so weit aus dem Fenster lehnst, und so einen Bullshit verzapfst!
Lern erstmal, den Unterschied zwischen "Definition" und "Deklaration" zu
verstehen, bevor du dich hier so weit aus dem Fenster lehnst, und so
einen Bullshit verzapfst!
Bist du jetzt schon argumentativ im Endschalter?
Nirgendwo hab ich in meiner Antwort Definition oder Deklaration verwendet.
Dann sind wir uns ja einig.
Und damit ist die "Lösung" den typedef in einen header zu schreiben
(beim Beispiel des TO) eben nur eine unsaubere Lösung.
Nein!
Die Fehler Meldungen im Eingangsposting sagen ganz klar, dass da der Bock geschossen wird.
Dummer weise, hat es der TO vermieden ein testbares Beispiel zu liefern.
Außer jammern und Prosa ist da nix.
ChatGPT kann dir die nicht geben, das erstellt höchstens gleichnamige Dateien mit viel falschem STM Registerzeug, wenn du dem nicht Quasi einprügelst das es Air001 verwendet, baut es nur scheiße zusammen.
Erst den richtigen Weg erkennen, und danach, im gleichen Satz, voll das
Arduino Bashing.
Also Nein!
Nicht alle Arduino User sind so blöd wie du dir das wünscht!
Sorry, wenn das so rüber gekommen ist, das soll mit Bashing nichts zu tun haben. Ich habe hier etwas angefangen (eben in Arduino) und möchte das eben so auch machen, auch wenn das nicht für mich ist.
Und ich möchte das so gut ich das kann machen und ich möchte das so angenehm für einen Arduino User machen wie es geht. Hier stellt sich mir die Frage schlicht, wie fängt ein Arduino User an. Er fängt erst einmal mit nichts an und weiß auch wenig und er weiß auch noch nicht wirklich was eine Inlcude-Datei ist und was da hinein gehört und was nicht. Er wird nur die eine .ino Datei bearbeiten.
Erst im Laufe der Zeit wird er sich vllt. Gedanken darüber machen, wie Libraries aufgebaut sind, was ein Objekt, eine Objektinstanz ein Konstruktor etc. ist. Er wird erst später verstehen, dass er in seinem Ordner seines Projekts nicht nur die .ino Datei liegen haben kann.
Ich habe schon ausgefeilte Algorithmen und Codes in Arduino gesehen, bei denen ich gedacht habe: wow.... aber ich habe auch gestaunt über die Art und Weise, wie der Code aufgebaut war.
Von daher: nein, das soll hier kein Bashing sein und schon gar nicht halte ich die Arduino-User für blöd. Je mehr ich mich damit momentan beschäftige, umso mehr kann ich auch verstehen, dass da manche begeistert sind, auch wenn es genügend Einschränkungen gibt.
Wenn man ein Bashing vornehmen möchte (und eigentlich auch kann), dann in der Richtung, dass es immer häufiger moderne Chips gibt, die auf ein Board geklatscht werden und dann gibt es einen unausgegorenen Core der oft (ogt != selten) nicht das tut was er soll.
Die Fehler Meldungen im Eingangsposting sagen ganz klar, dass da der
Bock geschossen wird.
Dummer weise, hat es der TO vermieden ein testbares Beispiel zu liefern.
Außer jammern und Prosa ist da nix.
:-) nein, der TO war mit seiner Frau einkaufen ... :-)) zudem hat er sich entschlossen, dass in seinen Tests erst einmal mit Funktionsprototypen zu machen, weil die Dinge die er testet, erst einmal in den Structs belässt und dann später sowieso Bestandteil einer Klasse werden. Und, ich muß jetzt irgendwie über mich selbst lachen: ich habe jetzt das ganze ohne Zeiger gemacht und das funktioniert dann erst einmal (von daher ist mein "Problem" gelöst), Die Diskussion hier find ich gar nicht mal so schlecht, nur der Ton ist gewohnt superklasseroberaffentittengeil-gut ... oder auch nicht !
Ach so, ja, bevor gemeckert wird, ein (leider) funktionsfährig und compilierbares Testprogramm:
Und ich möchte das so gut ich das kann machen und ich möchte das so
angenehm für einen Arduino User machen wie es geht.
Ja, aber.
Hier stellt sich mir
die Frage schlicht, wie fängt ein Arduino User an. Er fängt erst einmal
mit nichts an und weiß auch wenig und er weiß auch noch nicht wirklich
was eine Inlcude-Datei ist und was da hinein gehört und was nicht. Er
wird nur die eine .ino Datei bearbeiten.
Und wo liegt das Problem?
werden. Und, ich muß jetzt irgendwie über mich selbst lachen: ich habe
jetzt das ganze ohne Zeiger gemacht und das funktioniert dann erst
einmal (von daher ist mein "Problem" gelöst),
Das ist ein Irrtum. Denn du sollest mal über das Thema "call by value" und "call by reference" nachdenken. Dein Testprogramm schreibt in der Funktion
ansi_txbox() auf eine KOPIE der globalen Variable/Struct tbox. Das ist mit Sicherheit nicht gewünscht. Ein Lesezugriff wäre OK. Structs KANN man als Wert (call by value, KOPIE!) oder als Zeiger auf das Objekt (call by reference) als Parameter übergeben. Meistens ist die Referenz (Zeiger) besser und vor allem das, was man wirklich will.
Ach so, ja, bevor gemeckert wird, ein (leider) funktionsfährig und
compilierbares Testprogramm:typedef struct
Wieso leider? Welche komischen, ästhetischen Ansprüche hast du als ANFÄNGER?
{
int x1, y1;
int x2, y2;
int upborderattr;
int dwnborderattr;
int txfieldattr;
} txbox_t;
txbox_t tbox;
globale Variable
void ansi_txbox(txbox_t box)
{
int x;
x= box.x1;
Zugriff auf lokale Kopie in der Funktion. Die verschwindet beim Verlassen der Funktion!
Und ich möchte das so gut ich das kann machen und ich möchte das so
angenehm für einen Arduino User machen wie es geht. Hier stellt sich mir
die Frage schlicht, wie fängt ein Arduino User an. Er fängt erst einmal
mit nichts an
Doch, doch: Er nimmt den Mauszeiger und bewegt ihn auf das Drop-Down-Menu, bei dem "examples" steht, denn es gilt: Ein Beispiel sagt mehr als 1000 Worte.
Und, ich muß jetzt irgendwie über mich selbst lachen: ich habe
jetzt das ganze ohne Zeiger gemacht und das funktioniert dann erst
einmal (von daher ist mein "Problem" gelöst)
Zeiger sollte man in der Arduinowelt möglichst vermeiden (und das geht auch meistens).
Da sind so viele µC im Spiel, dass ich da nicht die Hand für ins Feuer
legen würde.
Dann probier's aus und meld dich dann wieder.
Übrigens:
Wenns keinen unit8_t gibt ist die Verwendung von unsigned char auch sinnlos. Wobei ich das Gewurstle von "unsigned char" und "long long" etc. schon immer sinnlos fand.
Aber zumindest weiß man es dann nicht. Das hilft ja Einigen schon weiter.
Zeiger sollte man in der Arduinowelt möglichst vermeiden
Nachdem ich HAL für STM32 etwas genauer angekuckt habe, sehe ich, daß Zeiger auf Structur viele Aufgaben erleichtern könnten und auch manche Fehler vermeiden helfen.
Da Arduino GIGA mit STM32H747 bestückt wird, liegt auf der Hand, daß HAL-Vorgehensweise auch für Arduino nicht uninteressant wird.
ansi_txbox() auf eine KOPIE der globalen Variable/Struct tbox. Das ist
mit Sicherheit nicht gewünscht. Ein Lesezugriff wäre OK. Structs KANN
man als Wert (call by value, KOPIE!) oder als Zeiger auf das Objekt
(call by reference) als Parameter übergeben. Meistens ist die Referenz
(Zeiger) besser und vor allem das, was man wirklich will.
ich weiß, und das ist am Schluß auch nicht gewünscht und wird dann in einer Klasse garantiert einen Zeiger haben. Es ging darum, einen compilierbaren Code zu haben.
Das ist mir aber nun wirklich neu, dass man keine Zeiger
verwenden soll !
Du hast anscheinend noch kein Lehrbuch über C++ gelesen. Sonst wüsstest du, dass man in C++ die von C geerbten "rohen" Zeiger nur in bestimmten Fällen nutzt. Ansonsten nimmt man die sogenannten Smart Pointer.
Und du wüsstest dann auch, dass man deinen Beispielcode ganz einfach ohne Zeiger schreiben kann, ohne ihn länger oder unübersichtlicher zu machen. Der Zeiger dort ist völlig überflüssig: Es geht auch mit einer Referenz.
Hier zeigt dir das ein Profi:
Beitrag "Re: Arduino und struct gefallen sich nicht !"
Ich kenne keinen einzigen C Compiler der diese Header Datei nicht hat.
Es dreht sich doch gar nicht um die Datei selber, sondern eher darum was da drin steht!
CHAR_BIT aus limits.h sagt dir wieviel Bit ein char hat.
Wenn ungleich 8, dann gibts auch kein uint8_t.
Früher recht üblich, dass es sowas gab.
Und ist für die Zukunft nicht ausgeschlossen.
Weder C noch C++ legen sich da fest.
Ist kein FW blob, keine Rohdaten, keine Register Map.
Aber integers in deinem Beispiel.
Eventuell könntest du ja auch "https://tinyurl.c*m/4h4mvdre" schreiben. Könnte leserlicher sein. Die \n \r schenk ich dir zu dem kostenlosen Tip noch mit dazu.
Warum sollte ich zur Ausgabe per UART konvertieren wollen?
Da gibts nix zu konvertieren. Nochdazu gibst du deine Daten in Bytes an um Platz zu sparen. Um das sicherzustellen, dass tatsächlich Platz gespart wird, verwendet man uint8_t. Die Größe von char ist implementationsabhängig, uint8_t ist garantiert ein Byte groß.
Genial ist dein Schachzug zuerst einen String in hex zu wandeln und dann zu merken, dass strlen nicht funktioniert, stattdessen sizeof verwenden zu müssen und dann Zeichen für Zeichen in die UART zu schubsen.
Und du wüsstest dann auch, dass man deinen Beispielcode ganz einfach
ohne Zeiger schreiben kann, ohne ihn länger oder unübersichtlicher zu
machen. Der Zeiger dort ist völlig überflüssig
Letztendlich sind Referenzen nur eine Variante von Zeigern, und im Maschinencode sogar exakt das Gleiche, egal wie sehr fragwürdige Lehrbücher das zu leugnen versuchen. Man hat aus einigen Ideen eine krampfhafte Lehre gemacht. Zum Glück muss sich niemand daran halten. Und nein, Arduino ist keine Gotteslästerei.
Lest mal Bücher von Bjarne Stroustrup nach dem Jahr 2000. Er geht mit seiner eigenen Arbeit nachträglich viel entspannter um, als so mancher seiner Jünger.
Das war kurz da hin gerotzt um bei dem Witz zu bleiben.
Hab Gerade gedanklich noch dem RDP1 vom PY32F002A im Hinterkopf und finde es erfrischend nebenher immer mal wieder an der Feelin Vape weiter zu machen. Dump war ja einfach, nach dem ich endlich den blöden Reset am China JLink gefunden habe.
nach dieser Methode kann ich aber die Members der Struct im Programm
nicht mehr ändern
Natürlich geht das!
C++ generiert für dich eine Handvoll Konstruktoren und Operatoren.
Automatisch, für jede Struktur und Klasse, wenn du das nicht unterbindest, kannst du diese nutzen.
Dich zu ignorieren wird jedenfalls helfen das ich weniger Mordgelüste hab! Mann die Menscheit ist so derbe am Arsch wenn nur noch so Leute wie du rumlaufen!
Reiß das nicht aus dem Zusammenhang, deine Möchtegern Konstruktion die du hier starten willst kannste dir als Zäpfchen verabreichen!
WAS STEHT OBEN ÜBER DEM CODE?!
Dissasembly lesen und vernünftig rekonstruieren ist nicht meine größte Stärke, vor allem weil ich nur sporadisch weiter mache wie ich gerade Zeit habe. Der erste Versuch (Grundlagen) war noch mit Forenhilfe, schon ne Weile her, dafür hab ich mich allerdings ganz gut erinnern können was ich versuchen kann und muss.
Und wenn überhaupt, kaper hier nicht mit dem Code der Nevoks Feeling Vape den Thread!
Und wenn du dort schreibst, Konstruktive Sachen, mach einen auf Oberlehrer und du kannst gleich weg bleiben!
Verstehe ich nicht!
Ich dachte es geht um Strukturen im Arduino Umfeld.
Aber wenn du meinst.
Nachtrag:
Wenn du Missverständnisse siehst, dann möchte ich dich bitten diese
aufzulösen, wenn möglich.
Oder wenigstens klar benennen.
doch, ich weiß wie es geht (Schreibfehler bitte entschuldigen, sitze im Auto auf dem Handy). Der letzte Programmpost von Arduino F. ist genau das, wie ich das zuvor auch gemacht hatte und es aufgrund von dämlichen Syntaxfehler von mir Compilerfehler gab. Dann gings hier ab wie Schmidts Katze und es waren zu viele Posts auf einmal, während ich noch am programmieren war... nicht an der Struktur, sondern an den Funktionen selbst. Hm, heute abend vllt. so ein Zwischenpost von dem, an dem ich gerade bin... Schmunzeln muß, das ganze nur deshalb, weil in einem anderen Tread es um Steuerzeichen cr und lf ging... und welches Terminal... hrmpf.. Aber: Arduino F. und Kirnbichler waren sind schon / zielführend (oft) und im Fall hier jetzt war Arduino F. der Experte
Meistens!
Habe aber auch meine Grenzen in Wissen und Können.
Bin seit 2014 im C++ und Arduino Umfeld.
Versuche alle Dokumentation aufzusaugen.
Alle C++ Features/Fähigkeiten so lange auszuprobieren/üben, bis sie sitzen.
na ja.
:-) C mach ich seit 1985... C++ irgendwann mitte 90er... Das Schlimme ist das permanente wechseln der Sprache, weil dazwischen auch immer wieder mal Delphi rutscht... und im moment auch noch Javascript. Viele Köche verderben den Brei. Für Arduino bin ich ein Anfänger, wie bei vielen Frameworks eine Flut von Dateien... Aaaaber so n kleines bischen versteh ich die Philosophie dahinter. Hmmm, ich bin mal gespannt, was ihr zu meinem Zwischenprojekt, wenn man das so sagen kann, sagen werdet. Und alles nur, um mit Arduino Ausgaben auf einem Terminal zu machen.
Zu Arduino bin ich eher durch Zufall gekommen.
Ein Freund brauchte eine kleine Ablaufsteuerung.
Wusste dass ich viel mit SPS gemacht habe, genauer "PS4 201 MM1".
Hatte noch eine liegen und habe ihm den Preis genannt.
Er ist auf den Rücken gefallen.
Dann in den Keller gerannt, mit den Worten "Ich habe da noch was!"
Ein misslungenes Geburtstagsgeschenk für/von seinem Ableger.
Der ist damit nicht warm geworden.
Ein Arduino UNO Starter Kit.
Mit Taster Kabel Relais und Hundert weiterem Rödel.
Nach ca 1 Stunde liefen die ersten Beispiele.
Nach ca 2 weiteren Stunden, war seine Ablaufsteuerung, noch rudimentär, aber funktionsfähig.
Und ich, entgegen meiner anfänglichen Vorbehalte: Begeistert!
:-) C mach ich seit 1985... C++ irgendwann mitte 90er... Das Schlimme
ist das permanente wechseln der Sprache, weil dazwischen auch immer
wieder mal Delphi rutscht... und im moment auch noch Javascript.
Dann solltest du dir zur weiteren Verwirrung noch python antun. ;)
Dann solltest du dir zur weiteren Verwirrung noch python antun. ;)
mag ich schon aufgrund der Einrückungen per Whitespaces nicht... und von daher glaube ich, dass ich mit Computersprachen gut bedient bin. Allerdings: wenn es irgendwann notwendig sein sollte, dann werde ich mich wohl auch noch mit Python beschäftigen.... aber vorerst einmal nicht!
mag ich schon aufgrund der Einrückungen per Whitespaces nicht...
In jeder halbwegs akzeptablen Programmiersprache rückt man ein, um sein strukturiertes Ansinnen zu verdeutlichen. Python forciert dieses an sich sinnvolle Verhalten.
Aber ich gebe es gerne zu, auch ich habe die ersten zwei** Minuten der darauf folgenden vielen Tausenden von Stunden gemeckert und mir Gründe aus den Fingern gezogen warum ausgerechnet dies nun schlecht sein soll. ;-)
Python forciert dieses an sich sinnvolle Verhalten.
Klingt nicht sehr überzeugt.
Aber ich gebe es gerne zu, auch ich habe die ersten zwei** Minuten der
darauf folgenden vielen Tausenden von Stunden gemeckert und mir Gründe
aus den Fingern gezogen warum ausgerechnet dies nun schlecht sein soll.
;-)
Wenn man aus der C/C++/C#-Ecke oder von einer anderen Programmiersprache mit Semikolon am Ende kommt, ist es etwas gewöhnungsbedürftig.
Kam' ich. Plus Assembler. Plus, plus,… Mindestens zwanzig Jahre lang.
Ja, und dann definiert man eine Funktion in einer Klasse und wundert sich, dass deren Aufruf einen Fehler wirft:
Bei jeder klammerorientierten Programmiersprache wäre die Einrücktiefe egal.
Hier war die Funktion Teil einer anderen Funktion.
Also alles einen Tab zurücksetzen, damit sie eine Methode innerhalb der Klasse und nicht einer anderen Methode ist.
Wer's mag... (oder frei nach Else Kling: "Wenn's schee macht!?")
Die einen machen's selbst, die anderen verlassen sich auf ihre IDE.
Oder der Compiler wirft einen Error, dass die öffnende Klammer nicht geschlossen wurde.
Da kann man dann auch gleich Assembler mit Schaltern programmieren und das EPROM regelmäßig ins Löschgerät packen. Been there, done it, diddn't like it.
Auch, wenn ich mit python so langsam zurecht komme, bis ich die mag, wird es noch dauern.
Wenn Niederländer eine Programmiersprache entwickeln... ich habe die Vermutung, dass das in einem Coffee-Shop passierte.
Structs KANN
man als Wert (call by value, KOPIE!) oder als Zeiger auf das Objekt
(call by reference) als Parameter übergeben.
Das Wort "Zeiger" kann sehr leicht zu Missverständnissen führen, weil es eine Übersetzung von "pointer" ist. Referenzen und Pointer sind aber zwei Paar Schuhe:
Oder der Compiler wirft einen Error, dass die öffnende Klammer nicht
geschlossen wurde.
Oder der Compiler wirft keinen Error, weil die öffnende Klammer irrtümlich an der falschen eingerückten Position geschlossen wurde. ;-)
Obwohl's gut aussah…
Man kann sich alles schönreden. Man sollte halt bei der Formatierung
konsequent sein.
Das gilt umgekehrt aber genauso.
Klar, ist nach einer copy'n'paste Aktion noch nie jemandem passiert…
Semikolon am Ende einer ›for‹ Schleife und danach schön eingerückt? Klar, ist noch nie jemandem passiert…
Man kann sich in jeder Sprache ins Bein schießen und es nicht sehen. Oder erst wenn es blutet. Nennt sich expectation bias.
Man kann sich in jeder Sprache ins Bein schießen und es nicht sehen.
Oder erst wenn es blutet. Nennt sich expectation bias.
Was bei klammerorientierten Sprach noch ganz angenehm ist:
Man kann Klammer dazu benutzen, Blöcke zu defininieren, auch wenn das gar nicht notwendig ist.
Aber die "Diskussion" hat zu viel philosophisches. Ich mag sie nicht, und wie Arduion Fanboy, werde ich mit ihr nicht wirklich warm.
Jeder wie er mag.
Bei Übergabe per Pointer geht die Arraygröße verloren. Muss man händische als 2ten Parameter nachreichen. Eine üble Fehlerquelle.
Bei Referenzen steckt die Arraygröße im Datentype.
Was soll der Unsinn?
Referenzen können nicht Null werden. Damit fängts schon an.
Ja, aber das ist auch der einzige Unterschied. Der Rest ist syntactical
sugar.
Oliver
Hallo Oliver und auch Hans W.,
nein. Mit syntaktischen Zucker, was man deutsch schreiben darf, sollte man das nicht so lässig abtun. Bsp. kann man den Adresswert in der Zeigervariable defaultmäßig ändern. Das referenzierte Objekt o.ä. einer Referenzvariable dagegen nicht. Da es mit C++ primär um Datenkapselung und Sicherheit geht, sollte eine Referenz Vorrang haben. Das Gehampel mit dem expliziten Dereferenzierungsoperator fällt auch weg. Der gesamte Umgang ist mit Referenzen einfacher und damit weniger bis kaum Fehleranfällig. Allein schon deswegen ...
Referenzen können nicht Null werden. Damit fängts schon an.
Ja, aber das ist auch der einzige Unterschied.
Pointer sind Variablen mit Typ und Speicherplatz, den man im Maschinencode sieht. Referenzen haben keinen Speicherplatz und treten im Maschinencode gar nicht auf.
Der Rest ist syntactical sugar.
Logik? Rest? Sobald es mindestens einen Unterschied gibt, den man im Maschinencode sehen kann, ist das Ganze kein syntactical sugar.
Klar, der Optimierer kann in manchen(!) Fällen den Unterschied wegoptimieren. Das ist hier aber nicht das Thema.
Bei Übergabe per Pointer geht die Arraygröße verloren. Muss man
händische als 2ten Parameter nachreichen. Eine üble Fehlerquelle.
Bei Referenzen steckt die Arraygröße im Datentype.
Pointer sind Variablen mit Typ und Speicherplatz, den man im
Maschinencode sieht. Referenzen haben keinen Speicherplatz und treten im
Maschinencode gar nicht auf.
Mit syntaktischen Zucker, was man deutsch schreiben darf, sollte
man das nicht so lässig abtun. Bsp. kann man den Adresswert in der
Zeigervariable defaultmäßig ändern. Das referenzierte Objekt o.ä. einer
Referenzvariable dagegen nicht.
Das ändern des Wertes einer Zeigervariablen und das ändern des referenzierten Objekts sind aber zwei völlig verschiedene Dinge. Den "Wert" einer Referenz kann man durch zuweisen eines anderen referenzierten Objekts auch ändern.
Da es mit C++ primär um Datenkapselung
und Sicherheit geht, sollte eine Referenz Vorrang haben. Das Gehampel
mit dem expliziten Dereferenzierungsoperator fällt auch weg. Der gesamte
Umgang ist mit Referenzen einfacher und damit weniger bis kaum
Fehleranfällig. Allein schon deswegen ...
Da bin ich voll bei dir. Raw pointer kann und sollte man vermeiden. Das entkräftet dann auch das Argumemnt, daß ein pointer die Größeninformation eines Array nicht enthält. Auch Array sind letzendlich raw pointer. Dafür nimmt man besser std::vector.
Nee, da wird die Größe der referenzierten Variable ausgegeben, das ändert aber nichts daran, daß Referenzen „under the hood“ nichts anders als Pointer sind.
Einem Zeiger kann man einen neuen Wert zuweisen, einer Referenz nicht
etc.
Aber sicher geht das.
Um das noch etwas zu präzisieren: „natürlich“ war natürlich etwas überspitzt. Seit C++20 ist das möglich, von hinten durch die Brust ins Auge, mit placement new. Ist aber irgendwie ein unschöner Hack, auch wenns kein UB ist.
Nee, da wird die Größe der referenzierten Variable ausgegeben
Eben, und deshalb hat dein Beispiel nicht das bewiesen, was du beweisen wolltest.
das ändert aber nichts daran, daß Referenzen „under the hood“ nichts
anders als Pointer sind.
"Unter der Haube" kann vieles bedeuten. Die Frage ist, wer wann was tut.
Bei Zeigervariablen wird die Verbindung zum referenzierten Objekt im Normalfall erst zur Laufzeit hergestellt, also dynamisch zum Zeitpunkt des Zugriffs. Zur Übersetzungszeit ist der Inhalt einer Zeigervariable im Allgemeinen unbekannt.
Bei Referenzen stellt der Compiler die Verbindung schon zur Übersetzungszeit her. Anders gesagt, die Adresse des Zielobjekts ist dem Compiler bekannt, sie muss nicht erst zur Laufzeit durch Auslesen einer Zeigervariablen beschafft werden.
Zwar kann man das Ziel einer Referenz umdefinieren, aber das passiert dann genau dort, wo es im Quelltext steht. Deswegen braucht man dafür keinen speziellen Speicherplatz für einen Zeiger, wie man ihn für eine Zeigervariable braucht.
Das ändern des Wertes einer Zeigervariablen und das ändern des
referenzierten Objekts sind aber zwei völlig verschiedene Dinge. Den
"Wert" einer Referenz kann man durch zuweisen eines anderen
referenzierten Objekts auch ändern.
Hallo Oliver,
ich denke wir reden etwas aneinander vorbei.
1
#include<iostream>
2
usingnamespacestd;
3
4
intvar1{16};
5
intvar2{32};
6
7
intmain()
8
{
9
// --- mit Referenz --- //
10
cout<<"--- mit Referenz ---"<<endl;
11
int&refVar{var1};
12
cout<<"var1 "<<var1<<endl;
13
cout<<"refVar "<<refVar<<endl;
14
refVar=var2;
15
cout<<"refVar "<<refVar<<endl;
16
//refVar = &var2; // Error
17
18
// Ausgangszustand herstellen //
19
var1=16;
20
var2=32;
21
22
// --- mit Zeiger --- //
23
cout<<"--- mit Zeiger ---"<<endl;
24
cout<<"addr von var1 "<<&var1<<endl;
25
cout<<"addr von var2 "<<&var2<<endl;
26
27
int*pRef{&var1};
28
cout<<"addr in pRef "<<pRef<<" Wert "<<*pRef<<endl;
29
pRef=&var2;
30
cout<<"addr in pRef "<<pRef<<" Wert "<<*pRef<<endl;
31
32
return0;
33
}
Auch wenn der Unterschied in der Betrachtung banal erscheinen mag, er ist da.
Eine Referenzvariable kann ich mit etwas (gleichem Datentyps) initialisieren und dann ist die Referenzvariable wegen ihrem Aliasnamen gleich der initialisierten Variablen oder Objekt o.ä. Zeile 11.
Die Instanz, die Adresse, in Zeile 16 zu ändern geht.
Man kann der Referenzvariablen nur durch kopieren/übergeben von Werten andere Werte zuweisen. Aber die Referenzvariable bleibt in dem Bsp. var1 und wird nicht var2. Man arbeitet weiterhin mittels Referenzvariablen refVar immer noch im Namen von var1.
Bei Zeigern weise ich in Zeile 29 pRef die Adresse von var2 zu und ab dem Zeitpunkt arbeitet man sinnbildlich mittels pRef mit var2 und nicht mehr mit var1. Man ändert nicht nur irgendwelche Werte in var1, sondern man arbeiten mit einem anderen Objekt var2.
Das ist der Unterschied in der Betrachtung oder gar Bedeutung, aber der ist wichtig zu verstehen. Ansonsten ackert man mit der falschen Variablen weiter und will das gar nicht.
Edit:
Natürlich kann man den gleichen Schutz mit Zeiger durch const
1
int*constpRef{&var1};
an der richtigen Stelle auch erreichen, nur ist das nicht "Default". :-) Und eben das Gehampel mit Dereferenzieren usw. bleibt bestehen. Bis ich das damals verstanden hatte, da verging viel Zeit. Arduino F. wird sich vielleicht erinnern. :-)
mag ich schon aufgrund der Einrückungen per Whitespaces nicht...
In jeder halbwegs akzeptablen Programmiersprache rückt man ein, um sein
strukturiertes Ansinnen zu verdeutlichen. Python forciert dieses an sich
sinnvolle Verhalten.
Exkurs: nicht nur das, die Kombination von Klammern {} und Einrückung ist vor allem redundant und insofern überflüssig. Trotzdem erlaubt Python auch eine Formatierung mit Semikola wie beispielsweise
1
import sys; sys.exit()
Aber ich gebe es gerne zu, auch ich habe die ersten zwei** Minuten der
darauf folgenden vielen Tausenden von Stunden gemeckert und mir Gründe
aus den Fingern gezogen warum ausgerechnet dies nun schlecht sein soll.
;-)
** Könnten auch zwanzig Minuten gewesen sein.
Man gewöhnt sich jedenfalls sehr schnell dran, insbesondere wenn der genutzte Editor das ordentlich unterstützt.
Dich stört, dass jemand was gegen dein heiß geliebtes Python hat - dessen Meinung ist für dich demnach irrelevant, was du dadurch ausdrücken könntest, dass du solche Beiträge / Kommentare einfach ignorierst.
stdint.h is a header file in the C standard library introduced in the C99 standard library section 7.18 to allow programmers to write more portable code by providing a set of typedefs that specify exact-width integer types, together with the defined minimum and maximum allowable values for each type, using macros
Da Arduino aber nun C++ ist, ist der passende Header <cstdint>.
Und das Problem dahinter ist, daß der halt manchmal eh schon irgendwo in irgendwelchen Library-headern includiert ist, manchem halt nicht, und daß sich das mit verschiedenen toolchain schonmal ändert.
Mit dem Problem des TO hat das alles aber nun überhaupt nichts zu tun.
Dich stört, dass jemand was gegen dein heiß geliebtes Python hat -
Nö. Mich stört, daß der Betreffende jedes Mal das Maul aufreißen muß, wenn das böse P-Wort erwähnt wird. Mich stört, daß der Betreffende sich dabei jedes Mal auf einen der unwichtigsten Aspekte der Sache kapriziert. Und mich stört, daß sich jemand ernsthaft für einen guten Entwickler mit einer ernstzunehmenden Meinung hält, der sich an solchen Lächerlichkeiten hochziehen kann, und das ständig, jedes Mal, und immer und immer und immer wieder.
Wie schon mehrfach angegeben: "Diskussionen" mit dir sind überflüssig.
Ja, für Dich ist das sicher richtig. Ich habe ja immer Recht. Andere können sehr konstruktiv mit mir diskutieren, aber bei einem, der sich ständig und immer wieder an der Sache mit dem Whitespace hochzieht... mit Kleingeistern zu diskutieren, ist intellektuell anspruchslos und daher Zeitverschwendung.
Hast du schon mal irgendwas sachbezogenes beigetragen?
Ein Problem hier gelöst?
Im Gegensatz zu Dir mache ich das sogar recht oft. Und jetzt zurück zum Thema, Du hast schon genug Threads mit Deiner Pythonophobie zuge^Wgeflutet.
du mir verkaufen wolltest, dass mein OOP Code kein C++ ist.
Schwachsinn. Wie dumm ist das bitte? Wir reden von einer C++ Lib. Ich sage ich versteh das Abstraktionsniveau nicht mehr. Als Antwort kommt ich könnte doch C++ lernen.
Warum sind hier im Forum eigentlich immer die Leute die Experten die nicht sinnerfassend Zusammenhänge lesen können?
Ich schrieb doch ganz klar, Arduino Temp Dateien sind eine mögliche Ursache für nichtreproduzierbare Fehler. Nicht mehr und nicht weniger, nicht ob das hier zutrifft.
Offensichtlich können Tim T. (tim_taylor) und einige andere den Fehler nicht reproduzieren.
Der TO hat keinen testfähigen Code gepostet.
Damit ist jeder Versuch den Fehler zu reproduzieren von Anfang an unmöglich.
Zudem lag der Code in einer *.ino Datei und unterliegt damit deiner heiß geliebten Überwachung.
Deine temp Geschichte ist damit eine Nebelkerze. Ein dummer Versuch den Thread zu hijacken.
Eine Blamage.
Nö. Mich stört, daß der Betreffende jedes Mal das Maul aufreißen muß,
wenn das böse P-Wort erwähnt wird.
Das ich erwähnt habe.
Und mich stört, daß sich jemand ernsthaft für einen guten
Entwickler mit einer ernstzunehmenden Meinung hält, der sich an solchen
Lächerlichkeiten hochziehen kann, und das ständig, jedes Mal, und immer
und immer und immer wieder.
Habe ich irgendwann mal behauptet, dass ich mich "ernsthaft für einen guten Entwickler" halte? Tue ich nicht. Meine Einstellung ist, dass es jemandanders gibt, der es besser kann als ich (z.b. die Kollegen im Büro nebenan).
Du springt doch sofort darauf an, wenn ich mal wieder über python herziehe bzw. es als mittelprächtiges Beispiel einer Programmiersprache verwende.
Es gibt bessere. Das solltest du als "programmiertechnisches Super-GAU" ja bestens wissen (der Begriff stammt von einem Uni-Prof)-
Du könntest das auch einfach sein lassen und mal still schweigen, dann
störte es gar niemanden.
Ich habe Ralph nur vorgeschlagen, sich auch mit python zu beschäftigen.
Dass das nicht so ganz ernst gemeint war, hat er zumindest verstanden (siehe Smilie)
Du bist doch auf Ralphs Aussage eingegangen:
Norbert schrieb im Beitrag #8023306:
Aber ich gebe es gerne zu, auch ich habe die ersten zwei** Minuten der
darauf folgenden vielen Tausenden von Stunden gemeckert und mir Gründe
aus den Fingern gezogen, warum ausgerechnet dies nun schlecht sein soll.
Wo habe ich (in diesem Thread) geschrieben, dass ich die Sprache grundsätzlich schlecht finde?
Ich finde sie gewöhnungsbedürftig, weil sie Sachen für notwendig erachtet, die bei anderen Sprachen nicht so relevant sind.
Ja, man kann sich an vieles gewöhnen:
Rahul D. schrieb im Beitrag #8023371:
Auch, wenn ich mit python so langsam zurecht komme, bis ich die mag,
wird es noch dauern.
Warum wollt ihr Äpfel mit Birnen vergleichen; Python ist eine Scriptsprache und keine klassische Programmiersprache. Der Vorteil liegt ja gerade darin dass nichts für eine Zielplattform kompiliert werden muss. Bevor man anfängt Shellskripte und Batchdateien parallel zu pflegen dann lieber ein Python.py
Den Interpreter namens "python" braucht man aber.
Der ist zwar häufig vorinstalliert, aber das muss nicht immer der Fall sein.
Und dann ist der Kunde aufgeschmissen, wenn er die Software selber installieren soll / will / muss.
In der Tat unter Windows eine Fehlerquelle. Microsoft hat sich erdreistet eine dummy Python.exe in den Path mit aufzunehmen. Diese soll dann den Appstore öffnen. Funktioniert aber nicht wenn man den Appstore deinstalliert hat. Scripte laufen dann mit Returncode 0 ins Leere.
Den Interpreter namens "python" braucht man aber.
Der ist zwar häufig vorinstalliert, aber das muss nicht immer der Fall
sein.
Und dann ist der Kunde aufgeschmissen, wenn er die Software selber
installieren soll / will / muss.
Deine Aussage ist doch ein glatter Strohmann. Nichts ist einfacher wie eine Pythoninstallation. Das ist einfacher wie Office zu installieren.
Deine Aussage ist doch ein glatter Strohmann. Nichts ist einfacher wie
eine Pythoninstallation. Das ist einfacher wie Office zu installieren.
oder den Unterschied bei der Anwendung von "als" und "wie" zu kennen?
Was ist wohl einfacher: Erst einen Interpreter zu installieren, oder gleich eine .exe (bezogen auf MS Windows) zu starten?
Welche Funktionen werden dort denn mit python realisiert?
Es gibt auch andere Programme (z.B. Inkscape), die sich mit python automatisieren lassen - ist halt eine betriebssystemübergreifende Scriptsprache.
Den Interpreter namens "python" braucht man aber.
Der ist zwar häufig vorinstalliert, aber das muss nicht immer der Fall
sein.
Und dann ist der Kunde aufgeschmissen
Für den Fall kannst du ihm über PyInstaller dann eine Exe machen 😁
Dann ist die alleine lauffähig.
Aber was hat das alles noch mit dem Thema dieses Threads zu tun?
Denn ich habe das ursprüngliche Problem nicht erkannt/gesehen/erfasst.
So gesehen, ist das richtig.
Manche beenden Gespräche, indem sie nur sagen, dass Sie den Fehler gefunden und behoben haben; aber nicht woran es lag (häufig sitzt das Problem ja zwischen Stuhllehne und Monitor...)
Also erstens bin ich ich nicht der TE, zweitens das Problem und die 'Lösung' (Workaround; deutsch 'umschifft') stehen sehr wohl im OP. Es steht sogar haarklein die Begründung im Text.
Ich wette ich kann es sogar reproduzieren. Damit habe ich Nichtwisser euch zwei Experten schon mal was voraus.
Das muss ich gar nicht, da ich schon vor (meinen) KI-Zeiten ein ähnliches Problem hatte und mir die Begründung des TE bzgl. Eigenheiten der Arduino IDE sehr wohl vertraut ist.
Aber gute Idee, ich wette selbst eine KI kann das nachvollziehen, befrag sie doch direkt mal!
Schlicht deshalb, weil Arduino automatisch Funktionsprototypen vor der
Kompilierung generiert. Bei Funktionen mit Struct-Parametern kennt der
Compiler den Typ noch nicht und deshalb muss ein Prototyp explizit
angegeben werden
Dann lass Dir gleich noch im Arduino Quelltext zeigen wie die Reihenfolge genau ist. Dann ist hier ein für alle mal Ruhe.
Aber gute Idee, ich wette selbst eine KI kann das nachvollziehen, befrag
sie doch direkt mal!
Ralph S. schrieb:
Schlicht deshalb, weil Arduino automatisch Funktionsprototypen vor der
Kompilierung generiert. Bei Funktionen mit Struct-Parametern kennt der
Compiler den Typ noch nicht und deshalb muss ein Prototyp explizit
angegeben werden
Dann lass Dir gleich noch im Arduino Quelltext zeigen wie die
Reihenfolge genau ist. Dann ist hier ein für alle mal Ruhe.
Nur mal so: es ist hier schon elendig lange "Ruhe" und das Thema hatte sich auch schon erledigt, gehabt, aber garantiert nicht wegen Dir, sondern schon eher von Arduino F. wegen.
Es ist unglaublich, wie sich hier immer und immer und immer wieder manche auf Kosten anderer profilieren wollen (oder glauben dieses tun zu müssen).
Warum auch immer habe ich mich in der letzten Zeit etwas mehr mit Arduino beschäftigt, als mir das lieb war und das alles nur, weil ich beschreiben will, wie mein Hardwareboard (mit CH32V003 und seriellem Bootloader) mit Arduino zusammenarbeiten kann (aber nicht muß)... und wie man mit bestimmten Gegebenheiten umgehen muß.
Wie gesagt, der Titel dieses Threads hier ist schon lange obsolet und, obwohl ich nicht so wirklich viel mit Arduino gemacht habe, glaube ich dennoch, dass ich darüber schon deutlich mehr weiß, als der Standardanwender.
Also, alle, die sich angesprochen fühlen: klopft euch mal selbst auf die Schulter und redet euch ein, wie toll und wie klasse ihr seid (jemand anderes wird das nicht tun). Die, die wirklich klasse und gut sind, werden sicherlich oft genug gelobt!
So, zum eigentlichen Thema will ich nicht wirklich zurück, aber das was ich hier jetzt präsentieren möchte ist genau wegen dieses Threads hier entstanden.
Mittlweile habe ich mich auch durch einen Teil des Dateien-Geflechts von Arduino gekämpft und weiß, wo ich bei bestimmten Dingen ansetzen müßte, wenn ich das denn umsetzen wollte.
erschließt sich mir nicht. "unkommentiert" man den ADC, funktioniert auch analogRead in Arduino (zuvor eben nicht).
Ich wüßte mittlerweile auch, wo ich ansetzen müßte um HardwareSerial die Read-Funktionen zu implementieren, laß das aber, weil ich hier dann lieber ein eigenes Serial als Library habe (und einem Anfänger nicht zumuten möchte, den Core zu patchen).
Wie dem auch sei, waren die Diskussionen hier sehr hilfreich, wie ein Arduino-User bestimmte Dinge vorfinden mag (bspw. einen geerbten Stream), oder eben auch, wie hier gerne die funktion loop gesehen wird. Einiges respektriere ich so und übernehme das auch so, bei anderen Dingen bin ich dann halt manchmal anderer Meinung.
Und weil in einem anderen Thread sogar moniert wurde, dass ein \n\r nicht richtig sei (obwohl das von mir sogar ganz bewußt so eingesetzt wird.... mit allen Mikrocontrollern die ich verwende), nur weil die User scheinbar noch nie eine Terminalemulation wie PuTTY, minicom oder TeraTerm verwendet haben.
Weil ich gerne bestimmte Dinge (und nein, ich kann auch mit OpenOCD umgehen) dann einfach nur auf die Schnelle auf einem Terminal ausgeben mag um korrekte Funktionsweise zu überprüfen, ist es mitunter hochangenehm, wenn man im Terminal Farben verwenden und den Textcursor positionieren kann.
Hierfür ist dann der "serielle Monitor" von Arduino (man möge es mir verzeihen, das soll kein Bashing sein) dann wirklich allerübelster Schrott und es hätte der Arduino-IDE gut zu Gesicht gestanden, hier ein halbwegs vernünftiges Terminal zu integrieren.
Hier ist also mal das Ergebnis (und smile, ich schreibe das von meinem Urlaub aus in einem südlichen Land) für solche Ausgaben, die mit unterschiedlichen Controllern, namentliche Arduino-nano, STM32F411 Nucleo und Eigenbau CH32V003 getestet sind und doch tatsächlich auf allen gleich funktionieren.
Es dreht sich hier um eine Ausgabemöglichkeit mittels ESC-Sequenzen auf einem Terminal (meistens eine Terminalemulation), die weit weniger aufwändig (aber auch weniger leistungsfähig) ist als ein mcurses von Frank M.(ukw) https://www.mikrocontroller.net/articles/MCURSES und zudem auch eben noch aus Arduino heraus funktioniert.
Es würde mich sehr freuen, wenn ihr konstruktive Kritik an meinen Dateien üben würdet, insbesondere von Arduino F. / Veit / Kirnbichler würds mich sehr freuen. Allerdings kann ich natürlich nicht erwarten, dass ihr euch diese Menge auch ansehen werdet.
Für alle anderen: es kann durch aus richtig Spaß machen, mit den Ansi-Sequenzen auf Arduino zu spielen.
nein, habe ich nicht. Dort hätte es zwar auch gepasst, aber die Library hier jetzt funktioniert mit jedem Controller für den es einen Arduino-Core und ein HardwareSerial gibt (und ist von daher genau eines nicht: CH32V003 spezifisch!).
Hier hätte ich jetzt eher eine Aussage erwartet wie: Warum hast du die msgbox und die txtbox nicht als eigenständige Klassen gemacht und die entsprechenden Methoden vererbt: Einzig, weil es dann irgendwann "unübersichtlich" wird und es einen Overhead produziert, der für kleine bis sehr kleine Controller garantiert kontraproduktiv ist.
Ähem Alexander, hast du in irgendeinem Thread auch irgendetwas konstruktives beizutragen ?
Das war eine Anmerkung von dir, die MIR zeigt, dass es manche Leute hier gibt, die xzy (zensiert) und dann abc (genauso zensiert) ... und überhaupt zensiert ist.
Kurz: du hast schlicht überhaupt keine Ahnung und weißt nicht, dass es außerhalb des Tellerrandes weitergeht, denn es gibt noch etwas anderes als schlicht nur den seriellen Monitor von Arduino ... und du hast auch mit keiner Faser verstanden, für was das ist und warum bspw. PuTTY standardmäßig es trennt, dieses LF und CR (oder eben auch \n \r) ... und es überhaupt keine Rolle spielt, ob es zuerst eine neue Zeile gibt und dann an den Anfang der Zeile gesprungen wird, oder ob zuerst an den Anfang einer Zeile gesprungen wird und dann eine neue Zeile.
Dort hatte ich auch dargelegt, dass es absolut ABSICHT ist ... also ist dein Minieinwand, dass etwas von dir konstruktiv ist absolut daneben. Erst nix verstehen, dann sich selbst als Experten darstellen und überhaupt noch nichts gezeigt haben. Ich bitte dich: verschone mich mit deinen Expertenaussagen.
@Arduino F. ich muß etwas schmunzeln, weil ich angenommen habe, dass du gefühlt 100 Vorschläge machen könntest. Wäre nett, wenn du mal den größten nennen würdest.
Beim Schreiben habe ich mir vieles überlegt, wie man etwas machen könnte. Wie gesagt könnte man bspw. aus den Elementen aus AnsiOut eigene Klassen herstellen. Das hätte dann den Vorteil, dass es kein struct benötigen würde, weil das dann schlichtweg Variable der Klasse wären.
Außerdem ist es etwas "gefährlich", die Farbnamen so zu beschreiben wie ich das gemacht hab (obwohl du dann schon zugeben mußt, dass ich wenigstens constexpr gemacht habe).
Und ich gebe zu, dass es wohl doch ein "arger" Mix aus C und C++ ist (und ich bin immer noch kein Freund von C++ auf kleinen Mikrocontrollern).
Im Übrigen funktioniert dein Vorschlag im Verlauf dieses Threads zum Belegen der Instanz einer struct nur mit einem Compiler, der C++20 unterstützt. Der AVR-GCC Compiler Version 7.3 der der Arduino-IDE 1.8 hinterlegt ist, kann das nicht. Der benutzte RISC-V Compiler für CH32V003 kann es.
Im Demo hätte man anstelle einen 12-Bit ADC auf 10 zu reduzieren, eine 10-Bit Auflösung pseudomäßig mittes wert << 2 auf einen 12-Bit Wert skalieren können, so dass bei einem 12-Bit ADC keine Auflösung verschenkt wird.
Man kann die Instanzen von progbar_t und tbox_t bereits im Konstruktor mit Werten belegen.
Ich habe mir viele Sachen überlegt wie man ein printf und ein AnsiOut realisieren kann, so dass es für Arduino-User "okay" ist.
Aber ohne Käse, mach einfach mal ein paar Vorschläge... und dann auch mal eine Einschätzung darüber wie sinnvoll diese Library ist....
Uuuuuund: ist es legitim, wenn ich "Treiber" für bspw. DHT11 / 22 oder DS18B20 , BM280 mache, dass die Beispiele für diese "Treiber" dieses extendedSerial verwenden dürfen oder ist es hier besser doch nur HardwareSerial von Arduino zu verwenden.
Und: für ein vollwertiges Serial für einen CH32V003 lieber den Core patchen oder eine eigenständige Library für Serial.
Es geht mir nicht darum, dass man mir zeigt wie man etwas programmiert, sondern es geht mir daraum, was denn für den geneigten Anwender das pragmatischtes und durchschaubarste ist?
Also bleib ruhig in deinem Film, aber um den seriellen Monitor ging es nie. Genau dort ist es nämlich irrelevant. Auch ich hab schon Progressbars und per ANSI-Escapesequenzen steuerbare ASCII Menüs gebastelt.
Am sinnvollsten Düfte Core patchen sein, die Frage welches serial für die Treiber erübrigt sich dadurch, die Nutzer kennen das Benennungsschema, kommen so in "gewohnter Umgebung" besser zurecht
Ralph, wenn du magst, dann schau dir auch mal das DEC TCS an. Macht die
Ausgaben noch etwas hübscher.
Grüß dich Norbert,
:-) na ja, gibt die Ascii-Tabelle mittels Programm in Python auf der Linux-Konsole aus. Mir ging es ja hier eigentlich um Arduino und Mikrocontroller.
Natürlich kann man das auch mit MicroPython auf einem Controller machen (sagen wir ab sSTM32F411), aber das war nicht das Ziel hier.
Zudem :-) nichts für ungut, dein Pythonprogramm ist so schön "unfarbig". Vllt. bis du auch nur der Meinung, ich sollte die Ascii-Tabelle mit Arduino machen ?
@Arduino F. ich muß etwas schmunzeln, weil ich angenommen habe, dass du
gefühlt 100 Vorschläge machen könntest. Wäre nett, wenn du mal den
größten nennen würdest.
Naja...
Hauptsächlich kleinere.
Stil Dinge.
Wie immer: "Das Prinzip der geringsten Verwunderung"
Eine Programm- bzw. Libsammlung ist verständlicher, wenn überall der gleiche Stil verwendet wird. Und da hat sich ein quasi Standard herausgebildet.
Das fängt an bei den selbstgewählten Bezeichnern für alle möglichen Dinge.
Keine Unterstriche in Bezeichnern. (also kein xyz_t)
Datentypen beginnen mit einem Großbuchstaben (also kein xyz_t)
Andere, mit Kleinbuchstaben ( DatenType variable = 23;)
KamelHöckerSchreiweise
Kein typedef für Strukturen, eigentlich gar kein typedef mehr. "typedef" ist eine Sammlung unnützer Buchstaben.
C Stil:
typedef uint16_t meintype_t;
Ab C++11/Arduino Stil:
using MeinType = uint16_t;
using kann sogar etwas mehr, als typedef, Templates!
Natürlich ist der alte C Stil in Arduino nutzbar, aber eher ungewohnt für geübte Arduin User.
Die Aufteilung in *.h und *.cpp vermeiden.
Warum?
Methoden in *.h only sind per default inline.
Man hat nur eine Datei zu pflegen und nicht zwei.
Die Verlängerung der Kompilezeit spielt meist keine Rolle. Bei großen Desktop Anwendungen schon eher.
Da zwecks Portabilität sowieso der Quellcode mit in der Lib sein muss, macht das Ausliefern von proprietären *.a Dateien wenig Sinn. Das geheimhalten/verbergen von Quellcode ist eher nicht Ziel in der Arduino Welt.
Das sind alles nur persönliche Ansichten.
Keine Religion, kein Muss.
Natürlich kann man das auch mit MicroPython auf einem Controller machen
(sagen wir ab sSTM32F411), aber das war nicht das Ziel hier.
Zudem :-) nichts für ungut, dein Pythonprogramm ist so schön "unfarbig".
Ach um die Programmiersprache geht's doch gar nicht. Auch nicht um die Farbe. ;-) Py war nur gerade zur Hand, bequem und schnell.
Es geht um die zusätzliche TCS Funktionalität mit ESC(0 und ESC(B (für Grafikzeichen), welche alle VT100 oder besser haben. Eben auch die richtigen Hardware-Dinger, falls man da mal dran möchte. Die können nämlich mit UTF-8 nicht wirklich etwas anfangen und der Bildschirm sieht dann aus wie ausgekotze Buchstabensuppe.
Für eine (ausschließliche) Emulation braucht man das natürlich nicht. Die halten sich sowieso kaum an Standards.