Lektion 10 - Arrays / würfeln von 1-6

  • Zumindest ist mein untenstehendes Beispiel dahingehend schlecht designed, dass die Würfelklasse die Ausgabe über LEDs fest verdrahtet hat. Eigentlich müsste es noch ein Interface geben, welches das Würfeln und die Ausgabe des Würfelergebnisses trennt und eine Schnittstelle zur Ausgabe (LEDs, OLED usw.) darstellt.

  • Kai, es ist mir doch klar, dass es Dir nicht um Spielereien ging, sondern um spezielle Lösungsansätze bei der Programmierung.


    Deshalb auch mein Hinweis, wenn man den Würfel als Spielwürfel nutzen möchte.

    Bei fast allen Programmierbeispielen werden als Hardware LED's und Taster eingesetzt. Ich dachte, bei diesem Beispiel könnte man auch mal abweichen.

    Den funduino Würfel wollte ich mal mit Display und Gehäuse für meine Enkel basteln und habe mich deshalb gefreut, dass hier schon das Thema würfeln behandelt wurde.

  • Zumindest ist der „funduino“ Würfel wesentlich simpler. Und die Programmierung desselben, würde ich mir nicht als Vorbild nehmen


    Es geht hier auch gar nicht um originell oder nicht originell. Es geht um Lösungsansätze und ums lernen.

    Sich mit bestimmten Problematiken beschäftigen und verschiedene Varianten durchspielen. So lerne ich…

    andere ja möglicherweise such.

  • Hallo zusammen,


    ich habe auch mal mit René's Aufgabe herumgespielt und versucht elektronische Würfel zu "bauen" die ohne die delay() Anweisung auskommen. So kann LED animiert, nicht blockierend gewürfelt werden. Der Ansatz ist C++ OOP mäßig.


    Das Programm besteht im Wesentlichen aus drei Klassen. Zuerst einer Buttonklasse, welche das entprellte Abfragen eines Tasters erledigt. Eine Timerklasse die den Umgang mit millis() erleichtert. Diese ist notwendig um ein "nicht blockierndes" Würfeln (ohne delay) zu ermöglichen. Zu Guter Letzt gibt es eine Würfelklasse, welche den Würfelvorgang abbildet.


    Durch das nicht blockierende Würfeln ist es möglich, dass mehrere LED Würfel quasi gleichzeitig animiert dargestellt werden können. In einer For-Schleife mit der delay() Anweisung wäre das unmöglich. Bei einem Würfel ist das egal. Wenn man aber z.B. ein elektronisches Kniffel Spiel erstellen möchte, welches fünf Würfeln benötigt, wäre es doch ziemlich störend, wenn nur ein Würfel nach dem anderen seine Würfelsequenz "abfahren" würde.


    Durch den (notwendigen) Verzicht auf eine For-Schleife mit delay(), ist es bei dieser Implementierung erforderlich, nach jedem Würfelvorgang den/die Würfel mit der Methode <objektname>.rollReset(); zurückzusetzen. Dabei wird ein interner Zähler der für die LED Animation benötigt wird, wieder auf Null zurück gesetzt.


    Das Beispiel ist für zwei Würfel ausgelegt. Die Würfelobjekte sind in einem Array abgelegt. Durch den OOP Ansatz ist das Beispiel im Prinzip (genug Pins vorausgesetzt) mit wenig Programmieraufwand um Würfel erweiterbar. Im Prinzip muss nur das Array um weitere Würfelobjekte erweitert werden.


    Es ist auch gut vorstellbar, das Ganze mit Portexpandern zu betreiben. Dafür ist aber etwas Umbau notwendig.


    Für Vorschläge, wie man das Würfelobjekt optimaler aufbauen kann bin ich offen und würde mich darüber freuen... :)


    Hier gibt es auch eine WokWi Simulation der zwei Würfel: https://wokwi.com/projects/359113191790579713


    Nicht wundern, das "random" funktioniert in der Simulation nicht wirklich. Bei einem echten Aufbau sollten die gewürfelten Werte wesentlich zufälliger sein als in der Simulation (dort sind sie es überhaupt nicht bzw. allenfalls der erste Wert). Das Programm startet mit einer Würfelanimation. Die Leds werden aber wieder gelöscht wenn sie beendet ist. Im Anschluss löst ein Tasterdruck einen Würfelvorgang aus und die Augenzahl wird am Ende durch die LEDs angezeigt.

  • Ok, unter Zuhilfenahme von Arrays ist das Programm um einiges kürzer.

    Was mich etwas gestört hat, war die sehr langsame Ausgabe der Würfelaugen, über die "zeige-Funktion", beim würfeln. Das war gefühlt 1 Sekunde und man hätte das Ergebnis beeinflussen können. Die Stelle am Code hab ich etwas angepasst. Es gibt jetzt eine eigene "wuerfeln-Funktion". Dort lasse ich die LEDs wahllos blinken und der "random-delay" greift auch wieder.




    Video:

    https://www.dropbox.com/s/mbfyjfl14m08jgi/IMG_2503.mov?dl=0

  • for each Konstrukte gibt es in C nicht. Man müsste das etwas mühsam nachbilden.


    In deinem einfachen Fall wäre das kein Problem. Ich verwende hier der Bequemlichkeit halber das String - Objekt. Reine C - Programmierer würden hier eher mit CHAR - Arrays arbeiten. Dann ist aber die kombinierte Ausgabe innerhalb der Schleife wesentlich komplizierter.



    Gruss

    René

  • Danke für eure Antworten. Das hab ich mir soweit auch schon gedacht.

    Wenn ich auf Arbeit mit der Powershell, von Windows,

    Scripte programmiere, gibt es die Möglichkeit Variablen in einer Schleife zu kombinieren.


    pasted-from-clipboard.png


    Gibt es sowas auf dem Arduino auch?


    Grüße


    Rayko

  • Zitat

    Beim initialisieren der Eingänge „pinMode(LED1, OUTPUT);“ gibt es da eine Möglichkeit mit einer Schleife zu arbeiten und die Ziffer hinter LED durch eine Variable zu ersetzen (auch in der Start-Funktion). Sodass beim durchlaufen der Schleife die Ports LED1, LED2, LED3... angesprochen werden? Oder könnte man das über ein Array lösen? Wie verbinde ich dann aber die Variable mit dem entsprechenden Port?


    LED1..LED7 sind Variablennamen bzw. Konstanten, die letztendlich auch nur Zahlen enthalten. Von daher kann pinMode ohne weiteres per Schleife aufgerufen werden. LED1..LED7 sind dazu nicht notwendig, sondern es wird der Zählerwert einer Schleife verwendet, der bei jedem Schleifendurchlauf, eine um eins erhöhte Pinnummer repräsentiert. Es ist nicht notwendig die Ziffer hinter LED durch eine Variable zu ersetzen. Es geht ja nicht darum einen Textstring zu bearbeiten. Die Konstanten LEDx werden u.a. der besseren Lesbarkeit des Quellcodes wegen angelegt.


    Code
    1. // pinmode auf die Pins 2 bis 8
    2. for (byte i=2;i<9;++i) {
    3. pinMode(i, OUTPUT);
    4. }


    Natürlich kann man die Pinnummern auch in einem Array abspeichern und damit die Pins schalten. Der Zählerwert der Schleife ist dann der Index auf die Arrayposition, in der die Pinnummer gespeichert ist. Im Falle eines Arrays können auch Pins berücksichtigt werden, die nicht aufeinanderfolgend sind.


    Code
    1. // pinmode auf die Pins 2 bis 8
    2. byte LED[8] = {2,3,8,7,4,6,5};
    3. for (byte i=0;i<7;++i) {
    4. pinMode(LED[i], OUTPUT);
    5. }

    Gruß Kai

  • Hallo Rayko,


    dein Weg ist korrekt, er erfordert einfach etwas unnötige Tipparbeit.


    Da die LEDs an aufeinanderfolgenen Pins angeschlossen sind, könnte mit einer Schleife gearbeitet werden. Damit liessen sich setup() und start() vereinfachen.


    Sobald die Pins nicht mehr lückenlos nacheinender kommen, geht das mit der Schleife nicht mehr direkt. In diesem Fall muss eine Umsetzung von LED-Nummer zu Pin-Nummer mit Hilfe eines Arrays gemacht werden. Ein einfaches Beispiel mit 5 LEDs findest du im Lösungsvideo. Eine Stufe weiter geht dann Lektion 11.


    Gruss

    René

  • Hallo,


    ein paar kurze Infos zu mir. Mein Name ist Rayko, 46 Jahre alt, gelernter Schlosser und danach Umschulung zum Büroinformationselektroniker. Grundkenntnisse im Programmieren und Elektronik sind vorhanden, müssen aber immer mal wieder aufgefrischt werden, da ich nur selten zum Anwenden komme.

    Meine Hobbys sind 3D-Design, 3D-Druck, Fotografieren, digitale Bildbearbeitung und etwas programmieren. Im Bereich 3D-Druck verwende ich Arduinos um kleine Projekte umzusetzen.

    Für die Projekte werde ich jetzt öfters mal hier vorbeischauen. Der Youtube-Kanal und das Forum vom Hobbyelektroniker find ich super. Beide haben mir schon sehr geholfen. Danke dafür!


    Ich habe mich heute mal an die Aufgabe mit dem elektronischen Würfel gesetzt. Da die Aufgabe am Ende der Array-Lektion kam, denke ich mal, es sollten Arrays verwendet werden. Bei mir hab ich aber keine verwendet.


    Soweit bin ich mit der Funktion der Schaltung und meinem Code zufrieden. Die vorherigen Lektionen haben mir dabei auf jeden Fall geholfen. Ich würde euch trotzdem bitten, mal über den Code zu schauen. Ihr werdet bestimmt noch ein paar Verbesserungsvorschläge haben.


    Ein paar Fragen habe ich auch.


    Beim initialisieren der Eingänge „pinMode(LED1, OUTPUT);“ gibt es da eine Möglichkeit mit einer Schleife zu arbeiten und die Ziffer hinter LED durch eine Variable zu ersetzen (auch in der Start-Funktion). Sodass beim durchlaufen der Schleife die Ports LED1, LED2, LED3... angesprochen werden? Oder könnte man das über ein Array lösen? Wie verbinde ich dann aber die Variable mit dem entsprechenden Port?


    Im seriellen Fenster lasse ich die Zufallswerte beim würfeln ausgeben. Dort habe ich auch bemerkt, dass „randomseed()“ zwingend notwendig ist. ;-)


    2020-07-18 20.35.34-1.jpg2020-07-18 20.35.39-1.jpg


    Video der Schaltung:

    http://www.dropbox.com/s/s2qdcke4dib39xr/2020-07-18%2019.35.16.mov?dl=0


    Video der seriellen Ausgabe:

    http://www.dropbox.com/s/f7mzi…07-18%2019.39.01.mov?dl=0