Mir ist bei Arduino unangenehm aufgefallen, dass dort viele Variablen
mit einem Großbuchstaben beginnen. Zum Beispiel Serial und Wire.
Ist das allgemeiner Standard? Ich frage, weil ich das im Rahmen
zahlreicher Programmiersprachen anders gelernt habe:
- variablen beginnen immer klein
- typen beginnen immer groß
- Konstanten und Aufzählungen schreibt mal komplett groß
In meinen Programmen führt das zu hässlichen Artefakten. Wenn ich zum
Beispiel zwei I²C Busse an einem ESP8266 habe, dann kommt da so etwas
bei heraus:
Wire.begin(4,5);
TwoWire wire2=Wire();
wire2.begin(12,13);
Sieht für mich verwirrend aus. Habe ich das "falsch" gelernt?
Stefan ⛄ F. schrieb:> Habe ich das "falsch" gelernt?
Offensichtlich ja.
Es gibt nur genau eine richtige Code-Konvention, und das ist meine. Alle
anderen sind grundfalsch ;)
Oliver
Probleme gibt's ;)
Arduino ist ja eher im Hobby Bereich zuhause. Ich glaube nicht, dass
sich Hobbiesten, welche Arduino mittel zum Zweck sehen, sich gross
Gedanken über klein/gross Schreibung machen.
Aber ich habs auch mal so gelernt wie du. Arbeite nun aber in einer
Firma die wollen zum Beispiel auch noch ein Prefix "c_" für Konstanten
oder "E_" für Enums.
Sollen Sie dass doch wollen. Meine Privaten Projekte schreibe ich
bestimmt nicht so. Und zum Glück bin ich nicht auf Arduino angewiesen...
und ich gehe schwer davon aus du auch nicht.
Also wenn es dir nicht gefällt, gibt es noch viele Alternativen.
Wire und TwoWire sind Klassen, keine Variablen.
Die Variable ist wire2.
Ah, ok falsch Wire ist eine Instanz von TwoWire. Na ja dann versteh ichs
auch nicht.
Stefan ⛄ F. schrieb:> TwoWire wire2=Wire();
Was macht jetzt diese Zeile genau ?
wire2 vom typ TwoWire wird instanziiert von "Wire()".
Was ist "Wire()" ? Gibts da einen Klammeroperator ?
"Wire" ist ja keine Klasse, oder doch ?
Thomas W. schrieb:> Wire und TwoWire sind Klassen, keine Variablen.> Ah, ok falsch Wire ist eine Instanz von TwoWire.
Genau das meine ich mit Verwirrung.
> TwoWire wire2=Wire();Thomas W. schrieb:> Was macht jetzt diese Zeile genau ?> wire2 vom typ TwoWire wird instanziiert von "Wire()".
Oh sorry, da ist ein Tippfehler drin. Es sollte heißen:
TwoWire wire2=TwoWire();
Je mehr Du Dich mit Sprachen und Programmiersprachen beschäftigst, umso
mehr wirst Du erkennen, wie wichtig es ist, möglichst kompakt,
systematisch, redundant und verständlich zu sein.
Und dann siehst Du, dass Deutsch und Englisch den Satzanfang und Namen
groß schreiben, Hauptwörter aber nur wir. Und es keinen Sinn macht, das
jetzt gleichzuziehen.
Stefan ⛄ F. schrieb:>> TwoWire wire2=Wire();>> Thomas W. schrieb:>> Was macht jetzt diese Zeile genau ?>> wire2 vom typ TwoWire wird instanziiert von "Wire()".>> Oh sorry, da ist ein Tippfehler drin. Es sollte heißen:>> TwoWire wire2=TwoWire();
Besser:
TwoWire wire2;
Stefan ⛄ F. schrieb:> Mir ist bei Arduino unangenehm aufgefallen, dass dort viele Variablen> mit einem Großbuchstaben beginnen. Zum Beispiel Serial und Wire.>> Ist das allgemeiner Standard? Ich frage, weil ich das im Rahmen> zahlreicher Programmiersprachen anders gelernt habe:>> - variablen beginnen immer klein> - typen beginnen immer groß> - Konstanten und Aufzählungen schreibt mal komplett groß>> In meinen Programmen führt das zu hässlichen Artefakten. Wenn ich zum> Beispiel zwei I²C Busse an einem ESP8266 habe, dann kommt da so etwas> bei heraus:>> Wire.begin(4,5);
Hier wäre dann Wire ein Objekt, keine Klasse.
Wilhelm M. schrieb:> Hier wäre dann Wire ein Objekt, keine Klasse.
So habe ich das auch verstanden.
Wire ist eine Objekt-Instanz von TwoWire. Deswegen müsste meiner Meinung
nach Wire klein geschrieben sein.
Stefan ⛄ F. schrieb:> Wilhelm M. schrieb:>> Hier wäre dann Wire ein Objekt, keine Klasse.>> So habe ich das auch verstanden.
Gut, dann habe ich Deinen Post falsch interpretiert.
> Wire ist eine Objekt-Instanz
Schwurbel: Objekt-Instanz.
Man sagt, Instanz (einer Klasse, es gibt ja auch
Template-Instanziierung), Objekt oder Exemplar.
> von TwoWire. Deswegen müsste meiner Meinung> nach Wire klein geschrieben sein.
Es muss gar nichts.
Thomas W. schrieb:> Dann am besten das (in wire.h vorgefinierte) Wire-Objekt garnicht> verwenden:>> TwoWire wire;> TwoWire wire2;> wire.begin(4,5);> wire2.begin(12,23);
Aber dann existieren insgesamt drei Objekte. Das Problem hierbei ist,
dass viele Bilbiotheken zwangsweise das Wire Objekt verwenden.
Stefan ⛄ F. schrieb:> Thomas W. schrieb:>> Dann am besten das (in wire.h vorgefinierte) Wire-Objekt garnicht>> verwenden:>>>> TwoWire wire;>> TwoWire wire2;>> wire.begin(4,5);>> wire2.begin(12,23);>> Aber dann existieren insgesamt drei Objekte. Das Problem hierbei ist,> dass viele Bilbiotheken zwangsweise das Wire Objekt verwenden.
Die ganze Schnittstelle ist doch broken-by-design.
Stefan ⛄ F. schrieb:> Thomas W. schrieb:>> Dann am besten das (in wire.h vorgefinierte) Wire-Objekt garnicht>> verwenden:>>>> TwoWire wire;>> TwoWire wire2;>> wire.begin(4,5);>> wire2.begin(12,23);>> Aber dann existieren insgesamt drei Objekte. Das Problem hierbei ist,> dass viele Bilbiotheken zwangsweise das Wire Objekt verwenden.
Ernsthaft das Wire-Objekt ist statisch global angelegt und andere gehen
davon aus daß es existiert und greifen drauf zu ?? OMG.
Probier mal delete Wire;
Wilhelm M. schrieb:> Stefan ⛄ F. schrieb:>>> TwoWire wire2=Wire();>>>> Thomas W. schrieb:>>> Was macht jetzt diese Zeile genau ?>>> wire2 vom typ TwoWire wird instanziiert von "Wire()".>>>> Oh sorry, da ist ein Tippfehler drin. Es sollte heißen:>>>> TwoWire wire2=TwoWire();>> Besser:>> TwoWire wire2;
Besser:
TwoWire wire2{};
Wilhelm M. schrieb:> Sag mal: Du schreibst doch C++-Bücher ;-)
Nein. Ich kenne von C++ nur die Grundlagen und erlebe immer wieder
Überraschungen. Mit Java kenne ich mich besser aus.
Stefan ⛄ F. schrieb:> Wilhelm M. schrieb:>> Sag mal: Du schreibst doch C++-Bücher ;-)>> Nein. Ich kenne von C++ nur die Grundlagen und erlebe immer wieder> Überraschungen. Mit Java kenne ich mich besser aus.
Dann bitte ich Dich um Entschuldigung: da muss ich Dich mit einem
anderen Stefan F... verwechselt haben.
Wilhelm M. schrieb:> Dann bitte ich Dich um Entschuldigung: da muss ich Dich mit einem> anderen Stefan F... verwechselt haben.
Ja ganz bestimmt (zwinker). So ganz Unrecht hast du ja nicht. Es ist
halt nur kein BUCH.
Zunächst einmal: ja, in C++ gibts die Möglichkeit, den "()" Operator zu
überladen - in den Quellen wire.cpp bzw. wire.h (irgendwo unter
Arduino/Arduino_Boards-master/) ist der Operator aber nicht überladen
worden.
Den "()" Operator zu überladen gilt zu Recht als ungeschickt.
Die Klasse "TwoWire" ist nur von der Klasse "Stream" abgeleitet (s.
Stream.h) - dort gibts auch kein Überladen des () Operators.
"Wire" ist eine globale Instanz (Variable) der Klasse TwoWire. In Wire.h
steht "extern TwoWire Wire;" und in Wire.cpp "TwoWire Wire =
TwoWire();". Dass "Wire" hier groß geschrieben wird, ist ungeschickt,
aber zulässig.
Der Code wäre besser so geschrieben worden:
TwoWire wire2 = Wire;
oder noch einfacher (weil der Konstruktor von "TwoWire" nichts macht und
weil "wire2" wahrscheinlich durch "begin()" sowieso komplett
initialisiert wird:
TwoWire wire2;
Mein Verdacht: in den üblichen Crosscompiler Paketen wird meist eine
alte Version von GNU g++ verwendet, die das mal irgendwann durchgelassen
hat. Die aktuellen Versionen von g++ lassen das nicht durch.
Edgar Huckert
ehuckert schrieb:> Den "()" Operator zu überladen gilt zu Recht als ungeschickt.
Das tut er doch auch gar nicht:
A a();
ist die Deklaration einer Funktion a mit leerer Parameterliste und
Rückgabetyp A.
ehuckert schrieb:> Der Code wäre besser so geschrieben worden:>> TwoWire wire2 = Wire;
Wenn es einen assignment operator gibt und der nicht irgendwie deleted
ist, ist das eine Kopie.
Thomas W. schrieb:> ehuckert schrieb:>> Der Code wäre besser so geschrieben worden:>>>> TwoWire wire2 = Wire;>> Wenn es einen assignment operator gibt und der nicht irgendwie deleted> ist, ist das eine Kopie.
Das hat aber mit copy-assignment gar nichts zu tun!
Stefan ⛄ F. schrieb:> - variablen beginnen immer klein> - typen beginnen immer groß> - Konstanten und Aufzählungen schreibt mal komplett groß
Und Funktionen? Halbgroß oder eher Kursiv?
Camelback oder doch mit Unterstrichen (ich_mag_das_nicht)?
Oder Kontanten eher mit einem 'k' vorneangestellt (kEinesfalls)?
Wilhelm M. schrieb:> Thomas W. schrieb:>> ehuckert schrieb:>>> Der Code wäre besser so geschrieben worden:>>>>>> TwoWire wire2 = Wire;>>>> Wenn es einen assignment operator gibt und der nicht irgendwie deleted>> ist, ist das eine Kopie.>> Das hat aber mit copy-assignment gar nichts zu tun!
Sorry, copy-constructor wäre richtig gewesen.
Thomas W. schrieb:> Wilhelm M. schrieb:>> Thomas W. schrieb:>>> ehuckert schrieb:>>>> Der Code wäre besser so geschrieben worden:>>>>>>>> TwoWire wire2 = Wire;>>>>>> Wenn es einen assignment operator gibt und der nicht irgendwie deleted>>> ist, ist das eine Kopie.>>>> Das hat aber mit copy-assignment gar nichts zu tun!> Sorry, copy-constructor wäre richtig gewesen.
Oder Move-ctor ;-)
Thomas W. schrieb:> Bist du sicher ?
Ja.
> Dann müßte man aber std::move() drum schreiben.> So ist das eine Kopie.
Auf der rechten Seite steht ein RValue. Damit wird der move-ctor
ausgewählt (der dann intern natürlich ein std::move braucht, denn ein
benanntes Objekt ist kein RValue mehr), wenn er existiert. Fallback:
cctor.
Das std::move benötigt man nur, wenn das move-from-object ein lvalue
ist.
Thomas W. schrieb:> Das neue C++ Zeug ist mir immer zu hoch.
Es ist eigentlich gar nicht so schwer, wenn man sich einmal intensiv mit
den Basics beschäftigt hat. Hier z.B. was ist ein RValue und was ist ein
LValue.
Zugegebenermaßen schwer zu behalten ist die Tabelle, welche der
speziellen Elementfunktionen wann automatisch generiert werden. Da
verfahre ich immer nach der Regel: explizit ist besser als implizit, und
default/delete explizit diese Elemente.
ehuckert schrieb:> Mein Verdacht: in den üblichen Crosscompiler Paketen wird meist eine> alte Version von GNU g++ verwendet, die das mal irgendwann durchgelassen> hat. Die aktuellen Versionen von g++ lassen das nicht durch.
Welche Codezeile aus deinem Beitrag genau meinst du damit?
Oliver
Wilhelm M. schrieb:> Thomas W. schrieb:>> Bist du sicher ?>> Ja.>>> Dann müßte man aber std::move() drum schreiben.>> So ist das eine Kopie.>> Auf der rechten Seite steht ein RValue. Damit wird der move-ctor> ausgewählt (der dann intern natürlich ein std::move braucht, denn ein> benanntes Objekt ist kein RValue mehr), wenn er existiert. Fallback:> cctor.>> Das std::move benötigt man nur, wenn das move-from-object ein lvalue> ist.
Mooooment.
Der kann den move-ctor nur dann nehmen, wenn ich das Objekt nachher
nicht mehr verwende.
Entweder ich übernehme die Verantwortung und schreibe std::move drum,
oder
er macht einen copy-ctor, falls ich das Objekt noch verwende, oder er
macht einen move-ctor wenn das Objekt lokal vorhanden ist und nicht mehr
verwendet wird.
Im Fall von Wire geht das nicht, weil das Wire-Objekt global ist.
Thomas W. schrieb:> Wilhelm M. schrieb:>> Thomas W. schrieb:>>> Bist du sicher ?>>>> Ja.>>>>> Dann müßte man aber std::move() drum schreiben.>>> So ist das eine Kopie.>>>> Auf der rechten Seite steht ein RValue. Damit wird der move-ctor>> ausgewählt (der dann intern natürlich ein std::move braucht, denn ein>> benanntes Objekt ist kein RValue mehr), wenn er existiert. Fallback:>> cctor.>>>> Das std::move benötigt man nur, wenn das move-from-object ein lvalue>> ist.>> Mooooment.> Der kann den move-ctor nur dann nehmen, wenn ich das Objekt nachher> nicht mehr verwende.
Das ist Deine Verantwortung!!!
> Entweder ich übernehme die Verantwortung und schreibe std::move drum,> oder> er macht einen copy-ctor, falls ich das Objekt noch verwende, oder er> macht einen move-ctor wenn das Objekt lokal vorhanden ist und nicht mehr> verwendet wird.> Im Fall von Wire geht das nicht, weil das Wire-Objekt global ist.
Blödsinn.
std::move ist nur ein RValue-cast. Und eine Vokalular-Funktion.
Ein move hinterlässt das Objekt in einem beliebigen(!), aber gültigen
Zustand. Insbesondere muss es destruierbar sein.
Thomas W. schrieb:> Nochmal mit Beispiel:>> #include <stdio.h>> #include <iostream>> using namespace std;>> struct A> {> std::string name;> };>> int main(int argc, char *argv[])> {> A a;> a.name = "FRITZ";> A a2 = a; // << copy-ctor> Hier wird nix gemovt, das ist eine Kopie.
Ja klar: a ist ein lvalue! Sagte ich oben bereits.
Wilhelm M. schrieb:> Thomas W. schrieb:>> Wilhelm M. schrieb:>>> Thomas W. schrieb:>>>> ehuckert schrieb:>>>>> Der Code wäre besser so geschrieben worden:>>>>>>>>>> TwoWire wire2 = Wire;>>>>>>>> Wenn es einen assignment operator gibt und der nicht irgendwie deleted>>>> ist, ist das eine Kopie.>>>>>> Das hat aber mit copy-assignment gar nichts zu tun!>> Sorry, copy-constructor wäre richtig gewesen.>> Oder Move-ctor ;-)
Dann verstehe ich nicht, wieso es oben ein move-ctor sein soll...
(weil "Wire" ist ja keine Klasse sondern eine Instanz)
Thomas W. schrieb:> (weil "Wire" ist ja keine Klasse sondern eine Instanz)
Ah ja ... dann hast Du natürlich Recht, und ich schlecht gelesen. Denn
ich hatte noch den Eingangspost im Sinn ;-) Dort stand nämlich
TwoWire wire2=Wire();
und dort ist der Initializer ein RValue.
Klassen werden in der Regel groß geschrieben. Variablen klein.
class Serial{
};
Serial serial;
serial.irgendwas();
Wenn die Klasse eine statische Methode enthält sieht das halt so aus:
Serial.begin(9600);
serial.irgendwas();
Thomas W. schrieb:> oder hab ich was übersehen ?
Ja natürlich, mein Flüchtigskeitsfehler. Wenn es hingegen so aussieht:
Stefan ⛄ F. schrieb:> Wire.begin(4,5);> TwoWire wire2=Wire();> wire2.begin(12,13);
Dann soll uns der Stefan bitte aufklären, was "Wire." ist. Ich meide
Arduino wie die Pest und werde nun nicht nachschlagen, was "Wire" ist.
Wenn das eine normale Variable(/Objekt ist, kann man drüber streiten -
ich würde es nicht groß schreiben.
Nick M. schrieb:> Und Funktionen? Halbgroß oder eher Kursiv?> Camelback oder doch mit Unterstrichen (ich_mag_das_nicht)?> Oder Kontanten eher mit einem 'k' vorneangestellt (kEinesfalls)?
Ich wollte ganz bewusst nicht allzu weit ausholen, sonst diskutieren wir
hier parallel über unterschiedliche Teile (ist leider trotzdem schon
passiert), wodurch es schwierig wird, der Diskussion zu folgen.
Arduino an sich hat den Einstieg in die Programmierwelt der
Mikrocontroller für Noobs wie mich erheblich vereinfacht, aber natürlich
ist es nicht ohne Fehler und Fehlentscheidungen...
Ben S. schrieb:> Dann soll uns der Stefan bitte aufklären, was "Wire." ist.
Wurde bereits geklärt.
Wire ist eine Instanz von TwoWire. Arduino stellt für alle
Schnittstellen (außer einfache I/O Pins) mindestens eine Instanz in
dieser Schreibweise zur Verfügung, so auch: Serial, Ethernet, WiFi,
LiquidCrystal, Servo, Stepper.
Noch ekliger ist es bei SPI und EEPROM, das sieht für mich wie eine
Konstante aus, ist aber ebenfalls eine Objekt-Instanz.
Stefan ⛄ F. schrieb:> TwoWire wire2=Wire();Ben S. schrieb:> Dann soll uns der Stefan bitte aufklären, was "Wire." ist. Ich meide> Arduino wie die Pest und werde nun nicht nachschlagen, was "Wire" ist.
Dann ist jetzt die Frage, was Wire() sein soll.
Oliver
Um völlig bekloppt zu werden: Ich sehe gerade dass es bei Stepper doch
anders ist. Davon stellt Arduino keine Instanz bereit und im Example
steht:
> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)> stepper.setSpeed()> stepper.step()
Da schreiben sie es auf einmal klein. Ich werde kirre!
Stefan ⛄ F. schrieb:> Ich wollte ganz bewusst nicht allzu weit ausholen, sonst diskutieren wir> hier parallel über unterschiedliche Teile ...
Naja, aber ...
Erster Buchstabe klein oder groß ist genau gleich wie:
Ich fang alle Klassen mit 'Cls' an (ClsTwoWire) oder lass sie mit
'Class' enden (TwoWireClass). Alle Funktionen mit ...
Denn das wäre die einzig richtige Methode um mehr als zwei verschiedene
Klassen von Namen auseinander halten zu können.
Klein/groß bietet halt nur zwei Schubläden.
Ich brauch aber Klassen, Variablen, Funktionen, Memberfunctions, ...
Stefan ⛄ F. schrieb:> Da schreiben sie es auf einmal klein. Ich werde kirre!
Wie dein Beispiel im Ausgangsbeitrag kommt der größte Teil der
allgemeinen Verwirrung von deinen falsch zitierten Codebeispielen.
Oliver
Stefan ⛄ F. schrieb:> Um völlig bekloppt zu werden: Ich sehe gerade dass es bei Stepper doch> anders ist. Davon stellt Arduino keine Instanz bereit und im Example> steht:>>> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)>> stepper.setSpeed()>> stepper.step()>> Da schreiben sie es auf einmal klein. Ich werde kirre!
Das macht ja überhaupt keinen Sinn. Wo soll das Beispiel stehen ?
Stefan ⛄ F. schrieb:> Walter T. schrieb:>> Gilt die Regel "einfache Datentypen klein, komplexe Datentypen groß" als>> veraltet?>> Davon habe ich noch nie gehört.
Interessant. Ich finde tatsächlich auch keinen Style Guide für die
C-Sprachenfamilie, der das beinhaltet. Ich glaube, ich muss erst einmal
mein Leben überdenken.
Wilhelm M. schrieb:> Vincent H. schrieb:>> Und inline obwohl die Funktion im Körper der Klasse steht... :D>> Das ist ausnahmsweise mal richtig ;-)
Es ist nicht falsch, aber meines Wissens nach ist die Funktion dann
sowieso implizit inline.
Stefan ⛄ F. schrieb:>> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)>> stepper.setSpeed()>> stepper.step()>> Da schreiben sie es auf einmal klein. Ich werde kirre!
Nicht nur das. Vgl. myStepper vs. stepper.
>> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)>> stepper.setSpeed()>> stepper.step()Thomas W. schrieb:> Das macht ja überhaupt keinen Sinn. Wo soll das Beispiel stehen ?https://www.arduino.cc/en/Tutorial/LibraryExamples/MotorKnob
Ganz unten. Über das myStepper versus stepper würde ich mal hinweg
sehen. Bemerkenswerter finde ich, dass sie hier Kleinbuchstaben für die
Variable (Name der Objektinstanz) empfehlen. Woanders wiederum wird es
groß begonnen (wie bei Wire und Serial).
Und warum heißt es mal
> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)
und mal
> Stepper myStepper(steps, pin1, pin2, pin3, pin4)
Das ist nicht einmal innerhalb der einen Seite konsistent!
Das die untere Variante die bessere ist, darauf hatte der Wilhelm in
Zusammenhang mit Wire bereits hingewiesen. Ich bin ja schon ziemlicher
Anfänger, was C++ angeht. Aber die Arduino Macher scheinen noch weniger
kompetent zu sein, falls ich das mal so sagen darf.
Ben S. schrieb:> Sind halt Italiener 😁
Ich dachte bisher das nur Franzosen "komisch" sind.
Stefan ⛄ F. schrieb:> Und warum heißt es mal>> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)
Kopier-Konstruktion.
> und mal>> Stepper myStepper(steps, pin1, pin2, pin3, pin4)
Direkter ctor-Aufruf.
> Das ist nicht einmal innerhalb der einen Seite konsistent!
Die beiden Beispiele sind schon konsistent.
Oder was meinst Du?
Stefan ⛄ F. schrieb:> Aber die Arduino Macher scheinen noch weniger> kompetent zu sein, falls ich das mal so sagen darf.
Arduino ist dafür gedacht, möglichst schnell etwas ans laufen zu
bekommen. Die Zielgruppe will keinen Sourcecode-Schönheitspreis
gewinnen, und die Macher anscheinend auch nicht.
Stefan ⛄ F. schrieb:>> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)
Das tut letztendlich, was man erwartet. Arduino in Reinstform.
Oliver
Wilhelm M. schrieb:> Die beiden Beispiele sind schon konsistent.> Oder was meinst Du?
Ich meine, dass beide Varianten auf der einen Seite vorkommen. Im
Quelltext (Sketch) die kürzere Version, darunter in der Link-Liste die
längere.
Stefan ⛄ F. schrieb:> Ich meine, dass beide Varianten auf der einen Seite vorkommen. Im> Quelltext (Sketch) die kürzere Version, darunter in der Link-Liste die> längere.
Verstehe ich nicht: beides ist absolut konsistent zueinander. Und wegen
copy-elision ist es auch in der Praxis dasselbe.
Stefan ⛄ F. schrieb:> Um völlig bekloppt zu werden: Ich sehe gerade dass es bei Stepper doch> anders ist. Davon stellt Arduino keine Instanz bereit und im Example> steht:>>> Stepper myStepper = Stepper(steps, pin1, pin2, pin3, pin4)>> stepper.setSpeed()>> stepper.step()>> Da schreiben sie es auf einmal klein. Ich werde kirre!
Da hätteste aber fairerweise dazuschreiben sollen, daß das kein
zusammenhängender Code, sondern die einzelnen Links zu "Siehe auch"
sind.
Mensch und ich hab gedacht das wäre ein Code.
Thomas W. schrieb:> Da hätteste aber fairerweise dazuschreiben sollen, daß das kein> zusammenhängender Code, sondern die einzelnen Links zu "Siehe auch"> sind.
Direkt über den Links ist der zusammenhängende Code. Es geht darum, dass
die Variable klein geschrieben wurde (stepper bzw. myStepper) während
Serial und Wire groß geschrieben werden.
Seltsam finde ich auch, dass die Seriellen Ports über Serial, Serial1,
Serial2, etc. angesprochen werden die bereits vom Arduino Framework
instantiiert wurden. Manche andere Klassen wie Stepper muss man aber
selber instantiieren.
Wobei die Methode, selber zu instantiieren meiner Meinung nach die
Sinnvollere ist, denn dann kann man dem Konstruktor auch gleich die Pin
Nummern übergeben. Bei ATmega sind die Pins fest vorgegeben, bei einigen
anderen Mikrocontrollern jedoch nicht. Und damit schließt sich der Kreis
zu meinem Eröffnungsbeitrag:
> Wire.begin(4,5);> TwoWire wire2=TwoWire(); // Tippfehler korrigiert> wire2.begin(12,13);
Wo ich die eine vordefinierte Wire Instanz mittels Wire.begin(4,5)
konfiguriere, während ich die zweite Instanz selbst anlege. Eigentlich
sollte der Konstruktor für die Zuordnung der Pins zuständig sein, finde
ich.
Nick M. schrieb:> Ist der Arduino eigentlich die Referenz für irgendwas Sinnvolles?
Ich denke schon. Zumindest im Umfeld von Schülern, Bastlern und
Anfängern.
Stefan ⛄ F. schrieb:> Ich denke schon. Zumindest im Umfeld von Schülern, Bastlern und> Anfängern.
Aber wohl nicht wenns um eine style guide für C++ geht. Also ist es
sinnlos das Gekorkse von Aruino anzusehen.
Von Scott Mayers gabs doch auch eine Style Guide, der Grieche wurde
schon genannt. Und dann gabs noch ein Buch das ich schon lang nicht mehr
hab.
Aber sicherlich gibt es weit mehr als ich kenne/kannte.
Nick M. schrieb:> Aber wohl nicht wenns um eine style guide für C++ geht. Also ist es> sinnlos das Gekorkse von Aruino anzusehen.
Ich muss zugeben, dass ich leider zunehmend auch diesen Eindruck
bekomme. Beliebte 3rd Party Bibliotheken sehen teilweise auch schlimm
aus. Wenn ich so auf der Arbeit programmieren würde, hätte man mich
längst zum Junior degradiert.
von Nick M. (muellernick)
>Ist der Arduino eigentlich die Referenz für irgendwas Sinnvolles? Und>wenn nein, warum streitet ihr euch wechen dem?
Über die Programmiersprache des Arduino wird bisweilen heftig
diskutiert.
Ich beobachte die Diskussionen hier schon über ein Jahrzehnt.
Das Arduinosystem ist zu einer Zeit entstanden ( 2003 ), in der im
Mikrocontrollernetz noch nicht einmal Ansatzweise die Verwendung von C++
auf einem Atmega8 8Bit Controller angedacht war. Ich erinnere mich eher
an die langen Diskussionsbeiträge einer Person, die partout die
Verwendung von Assembler progragiert hat ( Leser, die schon länger diese
Forum beobachten, wissen, wen ich meine ).
Wurde Arduino am Anfang heftigst bekämpft, tritt so langsam die Phase
ein, in der man sich genauer mit dem Thema auseinandersetzt.
Wenn man sie aber genauer verstehen will, muss man sich zunächst aber
fragen,welches Designziel mit der Entwicklung des Arduinos verfolgt
wurde.
Man kann es kurz Zusammenfassen: maximale Einfachheit.
Das System bestand aus zwei Componenenten der Mikrocontroller mit C++
programmiert und der PC-Steuerung mit Processing ( Java ) programmiert.
Die Programmierung beider Seiten wurde auf Einfachheit und
Kompatibilität getrimmt. Deshalb finden sich sowohl in Processing als
auch auf der Mikrocontrollerseite die Funktionen setup() und loop().
For C-Programmierer ungewohnt ist die Bezeichung boolean für den
Bitwert. Dieser wurde aber aus Kompatibilitätsgründen zur Java Seite so
umtypisiert.
Dem Unstand der Einfachheit dürfte auch das oben geschilderte Problem
der I2C Klasse geschuldet sein.
Es ist schlichtweg für Anfänger einfacher
wire.begin()
zu schreiben, als zu verstehen, dass man vorher die Wire Klasse noch
instantiieren muss.
Wer sich wirklich für die Zusammenhänge interessiert, sollte den Artikel
auf GitHub "the untold story of wiring" durchlesen:
https://arduinohistory.github.io/
Die Geschichte ist in mehrere Sprachen übersetzt und akademisch präzise
mit Verweisen belegt. Sie ist auf GitHub abgelegt, damit die damals
beteiligten Leute ihre Sichtweise einchecken können und ein
Änderungs-Log existiert.
( Stefan, das möchte ich insbesondere Dir empfehlen, da Du ja Bücher
über diese Themen schreibst und ich denke, da darf diese Grundlage auf
keinen Fall fehlen )
Die jüngeren Entwickler macht die Fragen nach der Sinnhaftigkeit des
Arduino-Systems genauso wenig Sinn, wie die Frage nach der
Sinnhaftigkeit eines Schraubenziehers oder Akkuschraubers aus dem
schlichten Grund, weil an den Unversitäten und Hochschulen die
Verwendung dieses Rapid-Protoytping Werkzeugs zum Standardreperatoir
gehört.
Christoph M. schrieb:> Es ist schlichtweg für Anfänger einfacher>> wire.begin()>> zu schreiben, als zu verstehen, dass man vorher die Wire Klasse noch> instantiieren muss.
Es muss aber Wire.begin() heißen. Und die Klasse heißt TwoWire. Die
Datei heißt aber wire.h und wire.cpp.
Da sind wir wieder bei der Verwirrung die Arduino stiftet. Schön zu
sehen, dass nicht nur ich damit ein Problem habe.
> da Du ja Bücher über diese Themen schreibst
Ich werde niemals ein Buch über Arduino schreiben.
Christoph M. schrieb:> Das Arduinosystem ist zu einer Zeit entstanden ( 2003 ), in der im> Mikrocontrollernetz noch nicht einmal Ansatzweise die Verwendung von C++> auf einem Atmega8 8Bit Controller angedacht war. Ich erinnere mich eher> an die langen Diskussionsbeiträge einer Person, die partout die> Verwendung von Assembler progragiert hat
Gut, so als System wo man irgendwas reinstecken kann und dann mit einer
Art Malen nach Zahlen bunte Schaltpläne kritzeln kann ... gefällt den
Kindern!
Als Erwachsener möchte ich aber dann doch ernstgenommen werden. Ich
schau auch keine Teletubies.
Aber bitte nimm nie wieder den Ausdruck C++ in den Mund. Denn das ist
ein C++ auf Holzrädern die bon einem Russichen (besoffenen) Biber
rausgeknappert wurden und mit Heißkleber zusammengekleckert wurden.
Man hätte es bei C belassen sollen. Das wäre keinen Deut schlechter
geworden.
Denn der Besitz eines C++-Buchs hilft den Arduisti nicht im Geringsten
weiter.
Das mit Assembler ist auch unnötig. Aber der Forderung hängt halt auch
viel Herrschaftswissen dahinter. :-)
>Aber bitte nimm nie wieder den Ausdruck C++ in den Mund. Denn das ist>ein C++ auf Holzrädern die bon einem Russichen (besoffenen) Biber>rausgeknappert wurden und mit Heißkleber zusammengekleckert wurden.
Ich bezweifle, dass du auch nur im Ansatz die Philosophie hinter dem
"Arduino-Prinzip" verstanden hast.
Eine Philosophie immerhin, die zu gefühlt 100 Millionen Anwendern
weltweit geführt hat.
Einem fähigen Programmierer bleibt es unbenommen, saubere C++ Libraries
für das System zu schreiben.
Fähige Programmierer aber, die einen sauberen, klar verständlichen aufs
wesentliche reduzierten Code ohne unnötigen Overhead schreiben können,
gibt es ganz ganz wenige.
>Man hätte es bei C belassen sollen. Das wäre keinen Deut schlechter>geworden.
Na dann zeig mal, wie den zur oben genannten Processing Seite auf dem PC
kompatibel bekommst.
Ich denke eher, dass die Arduino Macher ein System geschaffen haben, mit
dem man möglichst rasch zu ersten Erfolgserlebnissen kommt. Sie wollen
es aber sinnvollerweise aus Standard Komponenten zusammen setzen, die
Ausbaufähig sind - im Gegensatz zu Scratch, um nur ein Beispiel zu
nennen.
Bei Arduino hast du einen fließenden Übergang zu professioneller
Programmierung. Zwischen Scratch und den professionellen Arbeitsmitteln
tut sich hingegen ein breiter Graben auf, den wohl kein Kind alleine
überwinden kann.
Christoph M. schrieb:> Na dann zeig mal, wie den zur oben genannten Processing Seite auf dem PC> kompatibel bekommst.
Du willst also sagen, dass in C nicht die Funktionalität von C++ möglich
ist.
Einmalige Theorie!
Stefan ⛄ F. (stefanus)
>Bei Arduino hast du einen fließenden Übergang zu professioneller>Programmierung.
Ich denke, so ausgedrückt trifft es die Sache recht gut ;-)
Nick M. schrieb:> Du willst also sagen, dass in C nicht die Funktionalität von C++ möglich> ist. Einmalige Theorie!
Manch Leute verwechseln die objektorientierte Programmierung mit der
Syntax. Bei dem Wirrwarr an uneindeutigen Fachbegriffen habe ich dafür
vollstes Verständnis.
Stefan ⛄ F. schrieb:> Bei dem Wirrwarr an uneindeutigen Fachbegriffen habe ich dafür> vollstes Verständnis.
Vermutlich ist der Arduino schuld. Die Leute lesen C++ und glauben, wenn
sie mit dem verkrüppelten Arduino-C++ irnkwas gebacken bekommen haben,
sind sie Meister in OOP-Programmierung.
Eine andere Erklärung hab ich nicht, bin aber offen für bessere
Erkenntnisse.
Nick M. schrieb:> Stefan ⛄ F. schrieb:>> Bei dem Wirrwarr an uneindeutigen Fachbegriffen habe ich dafür>> vollstes Verständnis.>> Vermutlich ist der Arduino schuld. Die Leute lesen C++ und glauben, wenn> sie mit dem verkrüppelten Arduino-C++ irnkwas gebacken bekommen haben,> sind sie Meister in OOP-Programmierung.>> Eine andere Erklärung hab ich nicht, bin aber offen für bessere> Erkenntnisse.
Naja, man kann schon im selbst geschriebenen Code Features von C++17
nutzen, denn der Compiler des "Arduino-C++" ist GCC.
Es spricht auch nichts dagegen, mal keine Lust zu haben den Treiber für
xyz selber zu bauen.
Wenn man auch oft feststellen muß, daß der Schreiber zwar mehr Lust zum
Schreiben hatte, aber nicht unbedingt als Vorbild dienen sollte.
Stefan ⛄ F. schrieb:> Manch Leute verwechseln die objektorientierte Programmierung mit der> Syntax.
Und davon setzen die meisten dann noch OOP = Polymorphie und weiter
Polymorphie = Laufzeitpolymorphie. Und beide Missverständnisse werden
leider vom Arduino-Framework begünstigt.
Und darüber hinaus glauben nicht wenige, mit Arduino das Programmieren
lernen zu können. Das merkt man dann leider überall.
Wilhelm M. schrieb:> Und darüber hinaus glauben nicht wenige, mit Arduino das Programmieren> lernen zu können. Das merkt man dann leider überall.
Wem Programmierung langweilig erscheint, für den kann Arduino durchaus
eine Motivation bieten. Durch die Kombination mit Elektronik kommt man
nämlich in die Lage, ganz individuelle Geräte zu bauen, die man so nicht
kaufen kann.
Allerdings tanzen gerade Anfänger damit auf zwei Hochzeiten
gleichzeitig, was die Sache mitunter erheblich komplizierter macht. Also
genau das Gegenteil, was Arduino eigentlich versucht.
Ich selbst hatte lange Zeit gedacht, dass Programmierung+Elektronik
einer Super Kombination für den Einstieg ist, da spannend. Doch
mittlerweile bin ich nicht mehr so sicher.
In den Kindergruppen wo ich ehrenamtlich Unterstützt habe, war Scratch
und ein bissen Löten (Led Blinker) hoch im Kurs. Doch schon die
Kombination von Scratch mit Touch Sensoren zeigte ganz deutlich, dass
ungefähr dort die Grenze dessen liegt, was die meisten 10 jährigen
nachvollziehen können. Relais-Schaltungen begreifen sie genau so wenig
wie Logikgatter, obwohl man sie buchstäblich begreifen und anschauen
kann.
Alles was darüber hinaus geht, setzt Englisch und Mathe voraus, sowie
die Bereitschaft viel zu lesen. Was bedeutet: Nach ersten Experimenten
ruht das Thema für ein paar Jahre. Wenn es dann mit 18 oder später
weiter geht, ist Scratch auf jeden Fall kein Thema mehr und Arduino ganz
nett aber eigentlich nicht mehr notwendig.
Ich finde trotzdem wichtig, dass man die Kinder ein bisschen mit
Elektronik experimentieren lässt, damit keine Scheu vor dem Thema
aufbauen. Ein paar LEDs zu verkabeln sollte genau selbstverständlich
sein, wie Muffins backen und sich Mayonnaise ins Gesicht zu schmieren.
Stefan ⛄ F. schrieb:> Wem Programmierung langweilig erscheint, für den kann Arduino durchaus> eine Motivation bieten. Durch die Kombination mit Elektronik kommt man> nämlich in die Lage, ganz individuelle Geräte zu bauen, die man so nicht> kaufen kann.
Sehe ich genauso: das ist ja der Reiz des ganzen sod. Maker-Booms
(Basteln).
>> Allerdings tanzen gerade Anfänger damit auf zwei Hochzeiten> gleichzeitig, was die Sache mitunter erheblich komplizierter macht. Also> genau das Gegenteil, was Arduino eigentlich versucht.
Auch das sehe ich so: keine Ahnung von Elektronik und keine Ahnung von
Programmieren/SW ist eine schlechte Kombi. Und eines/beides lernt man
nicht in Kombination mit einem anderen Gebiert, wo man auch keine Ahnung
hat. Das ist didaktisch unklug.
Nick M. schrieb:
> Du willst also sagen, dass in C nicht die Funktionalität von C++ möglich> ist. Einmalige Theorie!
Nein.
Was genau hast du jetzt an dem im Link beschriebenen Designziel, die
Syntax der API auf dem Mikrocontroller mit Hilfe von C++ möglichst nahe
an der Syntax von Processing ( Java ) anzunähern, nicht verstanden?
Scheint ein Henne-Ei-Problem zu sein.
Muss das ähnlich Processing sein um C++ verwenden zu müssen oder
andersrum?
Einfach: Wer oder was zwingt dich dazu?
>Einfach: Wer oder was zwingt dich dazu?
[ ] Du hast dir die Geschichte von Wiring durchgelesen und verstanden
https://arduinohistory.github.io/
[ ] Du kennst das Design Ziel von Arduino
[ ] Du weist, welche Institution Processing entwickelt hat
[x] Du interessierst dich eigentlich für nichts, möchtest aber deine
Meinung kundtun.
>> Sind dann wire1 und wire2 äquivalent verwendbar, oder gibt es da wieder> irgendwelche Haken?
Auch wenn der Thread zwischenzeitig mal wieder ausgeartet ist:
Ich denke, dass das eine gute Lösung für dich sein könnte um deinen
Source optisch sauber zu bekommen.
Dominik S. schrieb:>> TwoWire& wire1 = Wire;>> TwoWire wire2();
wire2 ist nicht das, was man denkt: hier ist wire2 eine freie Funktion
mit leerer Parameterliste und Rückgabetyp TwoWire ;-)
>> wire1.begin(4,5);>> wire2.begin(12,13);
Und was sollen diese magischen Konstanten sein?
Wilhelm M. schrieb:> wire2 ist nicht das, was man denkt: hier ist wire2 eine freie Funktion> mit leerer Parameterliste und Rückgabetyp TwoWire ;-)
Hast du natürlich recht. Mir gings prinzipiell auch um die Referenz
wire1 zur Behebung seines "Optikproblems".
Wilhelm M. schrieb:> Und was sollen diese magischen Konstanten sein?
Die kommen von oben. Pin-Nummern glaube ich.
Wilhelm M. schrieb:> Und was sollen diese magischen Konstanten sein?
Da steht dann für dich ein Makro dahinter.
Eines mit gaaaaaaaaaaaaanz langen Namen damit du horizontal scrollen
musst.
Bei Arduino ist es üblich, Pin Nummer so anzugeben. Normalerweise
definiere ich sie irgendwo mit sprechenden Namen. In diesem kurzen
Beispiel habe ich darauf verzichtet, weil ich nicht vom Thema
ablenken wollte.
Stefan ⛄ F. schrieb:> Bei Arduino ist es üblich, Pin Nummer so anzugeben. Normalerweise> definiere ich sie irgendwo mit sprechenden Namen. In diesem kurzen> Beispiel habe ich darauf verzichtet, weil ich nicht vom Thema> ablenken wollte.
In meinen Augen ist es genau das Thema: kann ich beliebige Pin-Nummern
angeben? Wohl kaum. Was passiert dann? Warum kann ich überhaupt die
Pin-Nummern frei wählen? Das macht doch keinen Sinn, denn die TWI-Pins
sind ja festgelegt - zumindest kann ich sie nicht beliebig mux-en.
Das ist also ein Musterbeispiel, wie man eine Schnittstelle nicht
gestalten sollte. Das ist das Problem von Arduino: es ist ein
Schnittstellenproblem wie das im Eingangspost auch.
Wilhelm M. schrieb:> In meinen Augen ist es genau das Thema: kann ich beliebige Pin-Nummern> angeben? Wohl kaum.
Kann man, beim ESP8266. Weil es dort nämlich soft-I²C ist.
Bei Atmega Controllern hat die begin() Methode keine Pin-Parameter.
> Was passiert denn bei TwoWire().begin(4711, 815);?
Anstatt blöde Fragen abseits des Themas zu stellen, schau besser in den
Quelltext.
Wilhelm M. (wimalopaan)
>In meinen Augen ist es genau das Thema: kann ich beliebige Pin-Nummern>angeben? Wohl kaum. Was passiert dann? Warum kann ich überhaupt die>Pin-Nummern frei wählen? Das macht doch keinen Sinn, denn die TWI-Pins>sind ja festgelegt - zumindest kann ich sie nicht beliebig mux-en.
Das mit den Pin-Nummern ist bisweilen tatsächlich ein Problem und nur
mäßig geglückt.
Die Idee dabei ist, die Anschlusspins vom Mikrocontroller unabhängig zu
machen und zu abstrahieren.
Als Beispiel sei der obige Arduino-Uno gezeigt. Die Idee ist, ein Shield
mit einer bestimmten Pin-Belegung auf jeden Arduinotyp wie z.B. einen
Arduino Uno oder einen Arduino Mega aufstecken zu können, ohne dass die
Software geändert werden muss.
Das funktioniert bei z.b. BitBanging-TWI Treibern.
In den vielen Fällen wird aber die spezielle Hardware des spezifischen
Prozessors verwendet und die kann dann meistens nicht auf die
gewünschten Pins geroutet werden.