Did you recognize which parts are used as a display?
Correct. He has cut the with his Dremel into the individual modules decomposed to set two individual 8x8 modules "to the top".
Of course you can also use two Max7219 8x8 1 dot matrix MCU LED display modules . Circuit and Sketch are identical because both displays are based on the display driver MAX7219. But then the size is slightly larger and that would not have fit into the case he wanted to use.Before we view the code, we want to briefly introduce the power supply and the construction manual. Only a 9V block and a small DC-DC converter, e.g. the . This step-down regulator favors Mr. Süster, because the current account is better than the higher tension in Nano to spare, which can basically be supplied directly with 9V.
In addition, he has planned two switches. Switch 1 is the power switch. And with switch 2 can be selected between 3 times, 5 minutes, 5 minutes 30 seconds and 6 minutes. When switching on, different signals, depending on the time you have chosen. In addition, at selected 5.5 minutes, a signal is additionally output at 5 minutes at 5 and 5.5 minutes at selected 6 minutes.
These times can be changed software side in subsequent line:
int pause_5 = 136; int pause_5_5 = 149; int pause_6 = 162;
The times for the intermediate signals in the line:
byte Beep_1 = 50; byte Beep_2 = 44; byte Beep_3 = 50;
Both lines are located in the declaration part of the sketch.
Here again the components used:- 1
- Alternatively
- 1
- 1
- Power supply, e.g. 9V block
- 2 switches, of which one with three positions
- 1 NPN transistor
- 1 capacitor 100μF
- 1 Resistance 1 Kohm
- Optional speaker
- Housing and craft material
As a transistor, every 1 watt NPN transistor is suitable from the craft box.
When mounting the displays is important that the lower LED line 0 and row is 0.The openings for the ads should be as suitable as possible and the ads are glued again.
// Anzahl Segmente
// or SCK
// or MOSI
// or SS
MD_MAX72XX su = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Adressen für die Koerner
byte zeile1 = 0; byte reihe1 = 0;
byte zeile2 = 0; byte reihe2 = 0;
int pause_5 = 136; int pause_5_5 = 149; int pause_6 = 162; // Zeiten Ablauf
int pause_1 = pause_5_5;
byte beep_1 = 50; byte beep_2 = 44; byte beep_3 = 50; // Zwischenzeiten 5 bei 5:30, 5 bei 6, 5:30 bei 6
byte ton_ausgang = 9;
byte schalter1 = 8; byte schalter2 = 7; // Schalter fuer Zeiteinstellung
int zw_unten = 0; // Zaelwert unten, Position unten
int zw_oben = 0; // Zaelwert oben, Zaelwert Hauptschleife und Position oben
byte zw_laenge = 0; // Waeglaenge des Korn
byte zw_anzahl = 0; // Anzahl der Koerner
byte zw_laenge_1 = 0; // Weglaenge des Korn in der Schleife
byte zw_anzahl_1 = 0; // Anzahl der Koerner in der Schleife
byte zw_position = 7; // Position Korn
// Unterer Rhombus, 9 -> Stererelement, X -> Fallhöhe, Y -> Anzahl Wiederholungen, Z... -> Positionen
// X und Y gelten immer bis zum naechste Steuerelement.
byte unten [] = {9, 8, 01, 00, //1 Zeile 01
9, 07, 02, 01, 10, //2 Zeile 02
9, 07, 01, 11, 9, 06, 02, 20, 02, //1+2 Zeile 03
9, 06, 04, 12, 21, 30, 03, //4 Zeile 04
9, 06, 01, 22, 9, 05, 04, 13, 31, 40, 04, //1+4 Zeile 05
9, 05, 06, 23, 32, 14, 41, 05, 50, //6 Zeile 06
9, 05, 01, 33, 9, 04, 06, 24, 42, 15, 51, 06, 60, //1+6 Zeile 07
9, 04, 06, 34, 43, 25, 52, 16, 61, 07, 70, //6 Zeile 08
9, 04, 01, 44, 9, 03, 04, 35, 53, 26, 62, 17, 71, //1+4 Zeile 09
9, 03, 04, 45, 54, 36, 63, 27, 72, //4 Zeile 10
9, 03, 01, 55, 9, 02, 03, 46, 64, 37, 73, //1+3 Zeile 11
9, 02, 03, 56, 65, 74, 47, //3 Zeile 12
9, 02, 01, 66, 9, 01, 01, 75, 57, //1+1 Zeile 13
9, 01, 01, 67, 76, //1 Zeile 14
9, 0, 0, 77 //0 Zeile 14
};
// Oberer Rhombus, Positionen
byte oben [] = {77, // Zeile 01
67, 76, // Zeile 02
66, 75, 57, // Zeile 03
56, 65, 74, 47, // Zeile 04
55, 46, 64, 37, 73, // Zeile 05
45, 54, 36, 63, 27, 72, // Zeile 06
44, 35, 53, 26, 62, 17, 71, // Zeile 07
34, 43, 25, 52, 16, 61, 07, 70, // Zeile 08
33, 24, 42, 15, 51, 06, 60, // Zeile 09
23, 32, 14, 41, 05, 50, // Zeile 10
22, 13, 31, 40, 04, // Zeile 11
12, 21, 30, 03, // Zeile 12
11, 20, 02, // Zeile 13
01, 10, // Zeile 14
00 // Zeile 15
};
void setup() {
su.begin(); su.control(MD_MAX72XX::INTENSITY, 0); // Start MD_MAX72xx.h; Helligkeit Minimum
// Benoetigte Ports
pinMode (ton_ausgang, OUTPUT);
pinMode (schalter1, INPUT); digitalWrite (schalter1, HIGH);
pinMode (schalter2, INPUT); digitalWrite (schalter2, HIGH);
}
void loop() {
su.clear(); delay (100); su.clear(); // Loeschen Anzeige
// Zuordnung der Verzoegerungszeiten
if (digitalRead (schalter1 ) == 0) {
pause_1 = pause_5;
};
if (digitalRead (schalter2) == 0) {
pause_1 = pause_6;
}
// Tonsignal / Lichtsignal für eingestellte Zeit
if (pause_1 == pause_5 ) {
su.setPoint (4, 12, 1); // Mitte
tone(ton_ausgang, 500); delay (1000); noTone(ton_ausgang);
delay (2000);
};
if (pause_1 == pause_5_5) {
su.setPoint (6, 10, 1); // Links
su.setPoint (2, 14, 1); // Rechts
tone(ton_ausgang, 500); delay (1000); noTone(ton_ausgang); delay (1000);
tone(ton_ausgang, 500); delay (1000); noTone(ton_ausgang);
delay (1000);
};
if (pause_1 == pause_6) {
su.setPoint (4, 12, 1); // Mitte
su.setPoint (6, 10, 1); // Links
su.setPoint (2, 14, 1); // Rechts
tone(ton_ausgang, 500); delay (1000); noTone(ton_ausgang); delay (1000);
tone(ton_ausgang, 500); delay (1000); noTone(ton_ausgang); delay (1000);
tone(ton_ausgang, 500); delay (1000); noTone(ton_ausgang);
};
//Fuellen oberer Rhombus
zw_oben = 0;
do {
zeile2 = oben [zw_oben] / 10; reihe2 = (oben [zw_oben] % 10) + 8;
su.setPoint(zeile2, reihe2, 1);
zw_oben++;
}
while (zw_oben != 64);
// Lesen Steuerzeichen und Ausgabe der Koerner
zw_unten = 0; zw_oben = 0;
do {
if (unten [zw_unten] == 9) {
zw_unten++; zw_laenge = unten [zw_unten]; zw_unten++; zw_anzahl = unten [zw_unten]; zw_unten++;
};
zw_anzahl_1 = zw_anzahl;// Uebernahme der Daten fuer aeußeren Zyklus (Anzahl der Ketten)
do {
zw_laenge_1 = zw_laenge; zw_position = 7; // Uebernahme der Daten fuer inneren Zyklus (Anzahl Koerner der Kette und Ausgabe)
do {
if (zw_laenge_1 != 0) {
su.setPoint (zw_position, zw_position, 1); delay (pause_1);
su.setPoint (zw_position, zw_position, 0); zw_position--;
zw_laenge_1--;
}
}
while (zw_laenge_1 != 0);
if (zw_anzahl_1 != 0) {
zw_anzahl_1--;
};
delay (pause_1 * 5);
}
while (zw_anzahl_1 != 0);
// Ausgabe der gefallenen Koerner
zeile1 = unten [zw_unten] / 10; reihe1 = unten [zw_unten] % 10;
su.setPoint(zeile1, reihe1, 1);
zw_unten++;
zeile2 = oben [zw_oben] / 10; reihe2 = (oben [zw_oben] % 10) + 8;
su.setPoint(zeile2, reihe2, 0);
zw_oben++;
// Ausgabe Signal Zwischenzeiten
if (zw_oben == beep_1 && pause_1 == pause_5_5) {
tone(ton_ausgang, 500);
delay (1000);
noTone(ton_ausgang);
}
if (zw_oben == beep_2 && pause_1 == pause_6) {
tone(ton_ausgang, 500);
delay (1000);
noTone(ton_ausgang);
}
if (zw_oben == beep_3 && pause_1 == pause_6) {
tone(ton_ausgang, 500);
delay (1000);
noTone(ton_ausgang);
}
}
while (zw_oben != 64);
// Ausgabe Endsignal
tone(ton_ausgang, 500); delay (1000);
noTone(ton_ausgang); delay (500);
tone(ton_ausgang, 800); delay (1000);
noTone(ton_ausgang); delay (500);
tone(ton_ausgang, 500); delay (1000);
noTone(ton_ausgang); delay (500);
su.clear();
// "Bildschirm und Batterieschoner" do while wird nicht verlassen.
do {
zeile1 = random(8); reihe1 = random (16);
su.setPoint(zeile1, reihe1, 1); delay (100);
su.setPoint(zeile1, reihe1, 0);
}
while (zw_oben != 0);
}
// HUK Sanduhr V2-2-1 09.04.2021
3 comments
Bernd Albrecht
Hier die Antwort von Herrn Küster:
Zuerst die Frage zur Zeitsteuerung: In dem Programm gibt es keine Uhr. Die Zeit ergibt sich aus dem zeitlichen Abstand zwischen den fallenden Körnern und ihrer Fallgeschwindigkeit. Dieses wird durch nachfolgende Zeile im Deklarationsteil gesteuert.
int pause_5 = 136; int pause_5_5 = 149; int pause_6 = 162; // Zeiten Ablauf
Der Wert von pause_5 bestimmt die 5 Minuten, pause__5_5 die Zeit von 5 Minuten 30 Sekunden und pause__6 letztendlich von 6 Minuten. Dieses drei Werte sind eine Angabe in Millisekunden und werden im Programm direkt oder als ein Vielfaches davon benutzt.
Jetzt könnte man natürlich diese Werte mit einer Menüführung durch zwei Taster verändern. Angefangen, dass man Ziffern für die auf der Spitze stehenden Anzeigen konfigurieren müsste, stellt sich die Menüführung durch die Umrechnung der Werte der Anzeige in die entsprechenden Werte in Millisekunden auch nicht einfach da. Im Prinzip würde ein vollkommen neues Programm entstehen. Das sind einige Stunden Arbeit. Das lohnt den Aufwand nicht.
Das mit dem Poti ist sicherlich etwas einfacher. Dazu müsste man die Zeitauswahl rausschmeißen. Am Anfang des Programms den Wert des Potis mit einem analogen Eingang messen, danach mit einem festen Umrechnungsfaktor die Zeit definieren. Wenn man dann am Poti eine Skala anbringt umgeht man die Anzeige der eingestellten Zeit, was alles vereinfachen würde. Zwischenzeiten fallen dann auch raus. Da könnte man mal drüber nachdenken. Das kann aber frühestens im Herbst passieren (Rentner haben niemals Zeit).
Die Lautstärke lässt sich einfach mit einem Poti regeln. Dieses muss dann aber zwischen Kollektor und Lautsprecher liegen.
Die Adressierung der Pixel erfolgt über Zeile und Reihe. Zeile 0 bis 7 und Reihe 0 bis 7. Im Array “Byte oben []” sind die Adressen hinterlegt. Die zweistellige Ziffer besteht aus Zeilennummer und Reihennummer. Die niedrigste ist 00 und die höchste 77. Diese Ziffern werden dann im Programm wieder in ihre Einzelteile zerlegt.
R. Gerlinger
Hallo H.U. Küster,
kann ich die zeiten auch mit poti einstellen
super projekt, aber es gibt immer welche die mehr wollen…
…ich zum beispiel
Schymczyk Georg
Hallo Hr Küster, für mich als Anfänger finde euren Projekt sehr interessant und auch sofort nach Anleitung alles Aufgebaut, mag sein das durch mangelhafte Kenntnisse die ich habe, habe das Teil mit der Zeit Einstellung nicht so richtig verstanden. Möchte mir aber vorstellen eine einfachste Lösung:
1). Schalter S1 – ist ok
2). Schalter S2 – statt diesen möchte einfach drei Taster benutzen
a). T1 – für Minuten
b): T2 – für Sekunden ( T2 ist bei Eier kochen auf die Sekunde nicht so wichtig):
c): T3 – raset der vorher eingestellter Zeit
3). Der Transistor und Wiederstand(1kohm) für den Lautsprecher….?
kennte man nicht mit einem Poti ersetzen…?
Bin Schwerhörig und mit Poti bin in der Lage die Lautstärke regeln.
4). Wie am Anfang angedeutet schon habe, habe sehr geringe Kenntnisse mit dem Arduino, und das Sie
noch die deutsche Sprache im programmieren verwenden, freue mich darüber, weil dadurch kommt
mir leichter einiges zu verstehen.
5). Eine wichtige Frage werde noch stellen:
Jede Pixel muss mir einer Nr angesprochen werden, Segment1 – 8×8=64 ( 0 bis 63)
auch Segment2 – 8×8=64(64 bis 127)
beide Segmente – = 0 bis 127 Pixel
Und diese Nr127 konnte nicht finden?
Über eine Rückmeldung möchte mich freuen.
Lg, GS