Meinen Arduino Code verstehen. Was ist was?

/**
 * 8 Taster, gegen GND geschaltet
 * also invers funktionierend
 * 
 * 8 Relais auf einer der China üblichen Relaiskarte
 * ebenfalls invers schaltend
 * 
 * Die Entprellzeit von 20ms ist in CombieTimer als default 
 * vorgegeben. 
 * 
 * Funktion:
 * Jeder Tastendruck toggelt den Schaltzustand des zugehörigen Relais.
 */

#include <CombiePin.h>
#include <CombieTimer.h>
#include <CombieTools.h>



class TasterDingen
{
  public:
  virtual void init() = 0;
  virtual void run()  = 0;
};

template<byte inPin,byte outPin>
class Taster2Relais: public TasterDingen
{
  private:
  Combie::Pin::TasterGND<inPin>    taster;
  Combie::Pin::RelaisINV<outPin>   relais;
  Combie::Timer::EntprellTimer     entpreller;
  Combie::Tools::FlankenErkennung  flankenerkennung;
  byte state; // hier drin werden die Tastendruecke gezaehlt

  public:
  Taster2Relais():state(0){}

  virtual void init()
  {
    taster.initPullup();
    relais.init();
  }

  virtual void run()
  {
    if(flankenerkennung = entpreller = taster)
      relais = ++state & 1; // Niederwertigstes Bit wird Relaiszustand
  }
};


TasterDingen * dinger[] = { 
                            new Taster2Relais<2,10>(), 
                            new Taster2Relais<3,11>(), 
                            new Taster2Relais<4,12>(), 
                            new Taster2Relais<5,13>(), 
                            new Taster2Relais<6,A2>(), 
                            new Taster2Relais<7,A3>(), 
                            new Taster2Relais<8,A4>(), 
                            new Taster2Relais<9,A5>(), 
                          };
void setup() 
{
  // ForEach TasterDingen, in dinger, tue init()
  for(TasterDingen * ding:dinger) ding->init();
}

void loop() 
{ 
  // ForEach TasterDingen, in dinger, tue run()
  for(TasterDingen * ding:dinger) ding->run();
}

Diesen Code hat mir hier vor längerer Zeit al jemand geschrieben.

Jetzt will ich mal verstehen, was das alles ist.

bei include werden ja die ganzen Libs. eingebunden.

Aber was genau macht jetzt zB. die class "TasterDingen"

Oder was soll eine template sein?

Könnte mir jemand das mal netterweise erklären?

Hi!

Ich empfehle dir ein modernes dickes C++ Buch!
z.B. dieses Der C++ Pogrammierer
Oder, "Die C++-Programmiersprache" vom Erfinder Bjarne Stroustrup

Oder was soll eine template sein?

Ein Template ist eine Erzeugungsschablone für Code.

Aber was genau macht jetzt zB. die class "TasterDingen"

Tasterdingen ist eine "pure abstrakte Klasse".
Im Grunde hier nur vereinfacht...
In meiner (kleinen OOP) Welt ist sie die Mutter aller Tasks.
Dann heißt sie allerdings nicht "TasterDingen", sondern einfach nur Task.

combie:
Hi!

Ich empfehle dir ein modernes dickes C++ Buch!
z.B. dieses Der C++ Pogrammierer
Oder, "Die C++-Programmiersprache" vom Erfinder Bjarne Stroustrup
Ein Template ist eine Erzeugungsschablone für Code.

Tasterdingen ist eine "pure abstrakte Klasse".
Im Grunde hier nur vereinfacht...
In meiner Welt ist sie die Mutter aller Tasks.
Dann heißt sie allerdings nicht "TasterDingen", sondern einfach nur Task.

Ja, ich glaube, ich werde mir mal so eins beschaffen, weil ich demnächst mehr damit machen will.

Als Fahranfänger versuchst Du gerade, ein F1-Auto zu besteigen. Anders als beim Auto kannst Du mit dem Arduino wenig zerstören, dennoch ginge es auch anfängerfreundlicher.

Daher mein Tipp: Fange einfach an und nimm Dir die CombieTools als Ziel.

Das gibt für mich nur mehr Fragen als Antworten.

Was ist using?

Was ist taster.initPullup();?

Was wird hier gemacht:

EingabeTaster taster;
EntprellTimer entprellen(20);
FlankenErkennung flankenerkennung;
Counter counter;

?

ich versteh davon gar nichts.

Was ist using?

Die using Direktive
Und den dortigen Links folgen.
Alle drei Varianten setze ich ein.

Was ist taster.initPullup();?

Die Tasterinstanz wird angewiesen sich zu initialisieren und dabei den internen Pullup zu aktivieren.

Was wird hier gemacht:

EingabeTaster taster;
EntprellTimer entprellen(20);
FlankenErkennung flankenerkennung;
Counter counter;

Es werden Instanzen der betreffenden Klassen erzeugt.

Das gibt für mich nur mehr Fragen als Antworten.

Das ist ganz normal....
C++ lernen ist ein Prozess!
Bin mittlerweile ca 3 Jahre dabei, und noch lange nicht fertig.

Da ich selber das ganze im Arduino Typischen C schreiben wollte (C++ ist mir zu schwer),
habe ich das Problem mit dem Entprellen und Relais umschalten.

Ich kann jedem Taster ein Relais zuweisen und beim Drücken auch umschalten.
Wenn ich loslasse, geht es aber wieder aus.

Und in einem anderen Code, den ich noch hier habe, schaltet der Taster nicht immer sauber um.

Da schaltet das Relais teilweise nur hin und her.

Wie könnte denn so etwas in C aussehen?

Da ich selber das ganze im Arduino Typischen C schreiben wollte (C++ ist mir zu schwer),

Arduino ist C++, und nicht C.

An anderer Stelle wurde dir schon gezeigt, wie man das mit Arrays abhandelt.
Das sieht dann etwas C artiger aus.

Du solltest dir C++ aneignen, damit wird der Arduino in erster Linie programmiert.
Also besorge dir ein C++ Buch und ein Arduino-Buch für Anfänger, damit kannst du sicher starten.

HotSystems:
Du solltest dir C++ aneignen, damit wird der Arduino in erster Linie programmiert.
Also besorge dir ein C++ Buch und ein Arduino-Buch für Anfänger, damit kannst du sicher starten.

Davon gibt es ja so viele wie Sand am Meer.

Welches soll man sich denn da holen?

Marino_needing_help:
Davon gibt es ja so viele wie Sand am Meer.

Welches soll man sich denn da holen?

Da ich deine bisherigen Kenntnisse nicht einschätzen kann, solltest du eines nehmen, was du auch verstehst.
Sieh die die Beispiele Online an.

Diese ganzen simplen Sachen verstehe ich ja ganz gut, nur sobald es eben an so Sachen wie Taster Auswertung geht, wird es schwierig.

bis if Schleife verstehe ich das eigentlich.

Marino_needing_help:
Diese ganzen simplen Sachen verstehe ich ja ganz gut, nur sobald es eben an so Sachen wie Taster Auswertung geht, wird es schwierig.

bis if Schleife verstehe ich das eigentlich.

Wie.....Tasterauswertung ist ja nun wirklich einfach.

Dann übe doch mal mit den Beispielen in der IDE. Und ein Arduino Anfängerbuch sollte dann reichen.

Und das du mit einer if-Abfrage klar kommst, kann ich nicht erkennen.
Das ist keine Schleife.

Und somit fehlen dir noch sehr viele Grundlagen, die du erstmal lernen musst.

nur sobald es eben an so Sachen wie Taster Auswertung geht, wird es schwierig

Von der Initialisierung der Taste, bis zur Betätigung des Relais, wollen viele kleine Schritte gegangen werden.

Die OOP, zumindest so wie ich es versuche, bietet den Weg das in klar abgegrenzte kleine Bereiche aufzuteilen. Diese einzelnen Teile werden dann wie hier zu einem Ganzen zusammen gebunden.

In der OOP versucht man/ich Daten und Programm, welches zusammen gehört, in einer Klasse/Objekt zu kapseln. In der prozeduralen Programmierung, z.B. in C, liegen diese Dinge weit verteilt vor.
Diese Verteilung macht die Dinge unübersichtlich und fehlerträchtig!
Im Allgemeinen: Je größer das Projekt, desto problematischer.

Ein Ziel der OOP ist die Wiederverwendung von Code.
Unter weitgehender Vermeidung von Copy&Paste.


Mein Tipp:
Lese OOP Tutorials.
Experimentiere mit Klassen und deren Instanzen.

Je mehr du übst, desto besser wirst du (nicht nur) meinen Code verstehen lernen.
Nahezu alle Arduino Libraries haben einen OOP Aufbau.

Schaue dir an, wie die Libs aufgebaut sind.

Marino_needing_help:
Wie könnte denn so etwas in C aussehen?

Das wäre die aus meiner Sicht anfängerfreundlichere Alternative.

/**
 * 8 Taster, gegen GND geschaltet also invers funktionierend
 *
 * 8 Relais auf einer der China üblichen Relaiskarte ebenfalls invers schaltend
 *
 * Die Entprellzeit von 20ms ist als default vorgegeben.
 *
 * Funktion:
 * Jeder Tastendruck toggelt den Schaltzustand des zugehörigen Relais.
 */

const byte taster[] = {2, 3, 4, 5, 6, 7, 8, 9};
const byte relais[] = {10, 11, 12, 13, A2, A3, A4, A5};
const byte anzahl = sizeof(taster);
bool altStatus[anzahl];
const uint32_t entprellIntervall = 20;
uint32_t aktMillis, entprellMillis;

void setup()
{
  for (byte pin = 0; pin < anzahl; pin++)
  {
    pinMode(taster[pin], INPUT_PULLUP);
    altStatus[pin] = digitalRead(taster[pin]);
    pinMode(relais[pin], INPUT_PULLUP);
    pinMode(relais[pin], OUTPUT);
  }
}

void loop()
{
  aktMillis = millis();
  if (aktMillis - entprellMillis >= entprellIntervall)
  {
    entprellMillis = aktMillis;
    for (byte pin = 0; pin < anzahl; pin++)
    {
      bool aktStatus = digitalRead(taster[pin]);
      if (altStatus[pin] && !aktStatus)
      {
        digitalWrite(relais[pin], !digitalRead(relais[pin]));
      }
      altStatus[pin] = aktStatus;
    }
  }
}

Was didaktisch sinnvoll ist, was nicht, vermag ich nicht zu beurteilen. Das hängt sicher stark von den Vorkenntnissen ab.

Hallo,

zu den beiden Büchern kann ich etwas sagen. Natürlich alles aus meiner persönlichen Sichtweise, welche sonst.

Nach Lektüre eines C Buches für Anfänger, kaufte ich mir das hier:

Nach 332 Seiten musste ich abbrechen. Es ist nicht für Anfänger geeignet. Es ist auch kein Programmierbuch wie man sich das vorstellt. Es wird eher alles im Detail erklärt und Hinweise gegeben vom C++ Erfinder selbst wie man etwas hier und da noch "richtiger" oder "anders" anwenden oder nutzen sollte. Es ist eine völlig ungewohnte Schreibweise und damit Lesart. Man darf nicht erwarten das da jemand Lösungen für Probleme beschreibt. Es geht eher um den letzten Feinschliff wie man die Sprache und dessen Funktionen nutzen kann mit tieferen Verständnis. Diese Feinheiten brauch man aber als Beginner nicht. Würde sagen selbst als normaler Programmierer benötigt man das noch nicht. Weil man wird auch mit vielen unterschiedlichen Syntax für ein und das selbe förmlich erschlagen. Es ist irre was möglich ist, aber auch irre was die alles möglich machen, der Sinn erschließt sich einem dabei nicht immer, mir zumindestens nicht.

Ich kaufte dann dieses Buch.
https://www.hanser-fachbuch.de/buch/Der+C+Programmierer/9783446448841

Das ist schon besser lesbar. Bin noch am Anfang. Hier werden praktische Hinweise zur Programmierung gegeben für alltägliche Probleme. Allerdings merkt man auch hier, dass man von tausenden Möglichkeiten ebenfalls erschlagen wird. Ist eben ein dicker Wälzer wie das Buch oben der alles behandelt. Nur mehr aus praktischer Sicht.

Allgemein schwanken meine Gedanken beim lesen des Buches immer zwischen "macht das alles überhaupt Sinn" oder "ich werde mich schon durchkämpfen". Ich gebs mal einfach formuliert wieder, kann falsch sein oder auch nicht. Mit OOP gehts nur um das noch mehr verstecken von Code. Im Grunde kann man auch alles in Funktionen packen. Dann wäre C ausreichend. Meine Gedanken tun sich manchmal schwer den ganzen Aufwand von C++ für einen µC zurechtfertigen. Ich meine in C kann man auch Libs erstellen. Ich bin zur Zeit an einem Punkt wo ich mich frage, mache ich mit C++ weiter oder reicht mir C völlig aus. Ich sehe aktuell keinen echten Vorteil von C++ für einen µC. Im Gegenteil, ich habe hin und wieder das Gefühl es wird vieles verkompliziert statt einfacher. Die Gedanken gegen C++ werden immer wieder dann verstärkt, wenn ich solche Syntaxmöglichkeiten lesen muss.

int var = 9;
oder
int var {9};
oder
auto var = 9;

Der automatische Datentyp ist sicherlich auf den ersten Blick bequem, kann aber auch laut Buch zu ungeahnten Problemen führen. Nur wofür zur Hölle führt man einen neuen Syntax mit Klammern zur Initialisierung ein. Die markieren eigentlich eine Gruppierung. Die ganze C Welt initialisiert seit Jahr und Tag mit dem = Zuweisungsoperator. Was ja auch logisch erscheint. Jetzt wird sich das im Laufe der Zeit vermischen je nachdem wer programmiert. Viel Spass beim Code lesen. Sowas finde ich persönlich total irre und total unsinnig.

Ich weiß auch aktuell nicht warum immer nur C++ mit Objektprogrammierung in Verbindung gebracht wird. In C spricht man auch von Objekten.

Ich bin der Typ der sich viel mit Grundlagen befassen und diese dann, wenn verstanden, auch neu kombinieren kann. Nur wenn wie mit C++ die Anzahl der Grundbausteine aus meiner Sicht unendlich wird, dann verliert man den Überblick. Momentan weiß ich nicht wohin das Pendel ausschlägt.

Für sachdienliche Hinweise und vielleicht konkrete praktische Bsp. was mit C++ geht was mit C nicht geht wäre ich dankbar. Nur sollten das keine künstlich kompliziert kontruierten Bsp. sein. Vielleicht finde ich dann den roten Faden zu C++ zurück. Momentan macht das C++ Buch lesen keinen Spass.

Hallo,

Doc_Arduino:
Meine Gedanken tun sich manchmal schwer den ganzen Aufwand von C++ für einen µC zurechtfertigen.

das ist natürlich ein Punkt. Man muss dabei bedenken, dass Mikrocontroller am untersten Rand des Spektrums der Dinge liegen, die mit C++ programmiert werden. Den ganzen Umfang der Sprache kann man da kaum realistisch einsetzen.

Die Leute vom ISO C++ Komitee sind aber eher konservativ und führen Sprachänderungen nur nach jahrelangen Diskussionen durch. Die haben dann in der Regel schon Gründe.

So auch bei der Initialisierung.

Doc_Arduino:
Nur wofür zur Hölle führt man einen neuen Syntax mit Klammern zur Initialisierung ein.

Dafür gab es gleich mehrere Gründe. Einige davon fallen eher in Bereiche, die bei der µC Programmierung eher selten sind.

Einer ist aber leicht verständlich und hat sogar einen eigenen Wikipedia Artikel

Ein anderer Punkt wäre z.B. das {} keine implizite Typumwandlung erlaubt

int x = 5.0;    // geht
int y { 5.0 };  // Compilerfehler

Es ist aber eine gute Empfehlung die neue Initialisierung mit {} nur in solchen Fällen zu verwenden, wo die alte Syntax nicht funktioniert. Damit lenkt man Aufmerksamkeit auf diese Codestellen.

agmue:

const byte taster[] = {2, 3, 4, 5, 6, 7, 8, 9};

const byte relais[] = {10, 11, 12, 13, A2, A3, A4, A5};
const byte anzahl = sizeof(taster);
bool altStatus[anzahl];

Man muss nicht gleich mit Templates, abstrakten Klassen, Vererbung und virtuellen Methoden anfangen. Aber man kann auch einem Anfänger zumuten seine Daten vernünftig zu strukturieren. Sowas gehört einfach in ein struct und nicht in unabhängige Arrays. Dann ist der Sprung auf komplexere Programmieransätze auch nicht so groß

Sowas finde ich persönlich total irre und total unsinnig.

So wie du auch Goto unsinnig findest....
(OK, das war jetzt etwas gemein)

Seit Jahrzehnten programmiere ich Objekt orientiert.
Mein Gehirn funktioniert so viel besser, als prozedural.

Selbst als ich noch nicht wusste, was OOP überhaupt ist, habe ich schon so programmiert.

Damals wurde mir das auch gesagt, ungefähr mit diesen Worten:
"Du arbeitest doch schon OO, dann nimm doch bitte auch eine OOP Sprache!"
Gesagt, und getan.
Es war eine Befreiung!
Wie das ablegen eines viel zu engen Korsetts..

Von dem OOP Pferd gehe ich auch nicht mehr (ohne Not) runter.

Selbst mein Nickname "Combie" beruht/fußt darauf.
ComBie - Computer Bienen
Die Bienen haben mir die OOP nahegebracht, als ich noch nicht wirklich wusste, was OOP ist.
Meine Programme sollten sich verhalten, wie ein Bienenvolk.
Endlos viele einzelnen Teile, klare Schnittstellen, lose gekoppelt, quasi jedes eigenständig, und dann, im Verbund schlagkräftig.

Meine CombieLib ist einer dieser Auswüchse .....
Ein Produkt dieser Philosophie.

Zu C++ ....
Vor Jahren hätte ich gesagt: "Ich hasse C++."
Mittlerweile habe ich mich etwas eingewöhnt.
Und es fängt an Spaß zu machen.

C++ bietet eine interessante Sammlung "Grundwerkstoffe" und da greife ich gerne mit beiden Händen tief rein. Und modelliere mir die Welt so, wie ich sie mag.

Und das, Doc_Arduino, ist auch der Grund warum die beiden Bücher so gut für mich sind. Gerade das vom Erfinder! Denn das zeigt mir ganz klar die Details, die Mittel, die ich zur Verfügung habe. Fertige Lösungen brauche ich nicht in so einem Buch. Die Beschreibungen der Sprachmittel, und winzige Codefragmente, welche zeigen, wie sowas dann aussieht, sind genug.
OK, OK..
Nicht alles ist auf unseren kleinen µC vollumfänglich brauchbar, z.B. die STL.

Es gibt allerdings auch Gehirne, wo die OOP offensichtlich nicht auf die Windungen passt.
Das ist nicht schlimm, ganz im Gegenteil.
Die Träger solcher Hirne haben die Chance viel bessere prozedurale Programmierer zu werden, als ich es je sein könnte.
Zum Glück haben wir verschiedene Talente, Neigungen, oder was auch immer.

Ob prozedural, oder OOP, mit C++ ist beides möglich.

Wer jetzt mit Arduino C artige Programme schreiben lernt, kann später bei der Linux/Windows Kernel/Treiber Programmierung Fuß fassen. (oder ähnliche Bereiche)
Wer mit Arduino streng im C++ Stil arbeitet, wird es dann in Anwendungsprogrammierung, z.B. auf PCs, viel leichter haben.

Das Umlernen, zwischen den beiden Arten, ist recht schwer.
Denn man muss eine andere Art zu Denken erlernen.
(und dabei steht einem das bisher gelernte häufig im Weg rum)

Man muss nicht gleich mit Templates, abstrakten Klassen, Vererbung und virtuellen Methoden anfangen. Aber man kann auch einem Anfänger zumuten seine Daten vernünftig zu strukturieren. Sowas gehört einfach in ein struct und nicht in unabhängige Arrays. Dann ist der Sprung auf komplexere Programmieransätze auch nicht so groß

Da hast du natürlich völlig Wahr!

Hallo,

ihr gebt mir wieder Hoffnung. :slight_smile: Ich lasse eure Antworten so stehen. Recht habt ihr alle.

Wegen den Büchern. Das erste Buch ist eben für Leute die schon programmieren können. Die benötigen keine Bsp. dafür. Die Erklärung dessen reicht denen. Anwenden können die das dann selbst. Ihr gehört zu denen.

Das zweite Buch möchte C++ einem mit praktischen Bsp. näher bringen. Das liegt mir einfach besser, da ich aus der praktischen Ecke komme. Ich gehe vermutlich anders ran wie ihr. Nebenbei lesen gelingt mir jedoch nicht. Ich benötige immer ein Bsp. um den Nutzen dessen zu verstehen und später auch anwenden zu können.

Kurzum, mir gehts wieder besser. Ziel erreicht. Ich danke euch.