Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Mini-LED-Matrixuhr

Komponenten und Verbrauchsmaterialien

Arduino Nano R3
× 1
Maxim Integrated DS3231M - ±5 ppm, I2C-Echtzeituhr
× 1
Druckschalter, kurzzeitig
× 2
LED-Matrix-Modul 32x8
× 1

Notwendige Werkzeuge und Maschinen

Lötkolben (generisch)

Apps und Onlinedienste

Arduino-IDE

Über dieses Projekt

Auf der Seite "Nicks LED-Projekte" habe ich ein Uhrenprojekt gefunden, das die Zeit auf 4 Matrizen mit 8x8 LEDs anzeigt. Er baute die Uhr mit Matrizen aus dem Laden "ICStation", der Matrixmodul-Panel-Bausätze verkauft.

Mit einer minimalen Änderung des Codes habe ich meine Uhr mit MAX7219 Dot-Matrix-Modul Mikrocontroller 4-in-One-Display gemacht, das komplett gefaltet ist und viel billiger ist. Ich habe es bei AliExpress gekauft.

Die Uhr hat viele Funktionen:

- Basismodus mit großen Ziffern

- Slide-Modus, in dem Ziffern auf und aus dem Bildschirm rollen

- Kleine Ziffern mit Sekundenmodus

- Zeit in Worten geschrieben, z.B. „zehn nach zwölf“

- Datumsanzeige

- 12/24-Stunden-Option

- Helligkeitsoption

- Zufällige Uhrmodusoption, die den Anzeigemodus alle paar Stunden ändert.

- Drucktastengesteuerte Menüs für Setup und Anzeigeauswahl.

Wie Sie auf der Schaltung sehen können, benötigen wir außer Matrizen eine Arduino-Platine, ein Echtzeituhrmodul und zwei Drucktasten für die Einstellungen. Sie können Bibliotheken und modifizierten Code unter den folgenden Links herunterladen.

Code

  • Code
  • Bibliotheken
codeArduino
/************************************************ ************************Mini Clock v1.0, Juli 2014 von Nick HallVerteilt unter den Bedingungen der GPL.Für Hilfe beim Bau der Uhr siehe mein Blog:http://123led.wordpress.com/Tested on IDE v1.6.5 ***************************** ***************************************** ///Bibliotheken einschließen:#include "LedControl.h"#include // Schriftbibliothek#include // DS1307 Uhr#include "RTClib.h" // DS1307 Uhr#include // Schaltflächenbibliothek von Alexander Brevig// Setup LED Matrix// Pin 12 ist mit DataIn am Display verbunden // Pin 11 ist mit CLK am Display verbunden // Pin 10 ist mit LOAD am Display verbunden LedControl lc =LedControl(12, 11, 10, 4); // setzt die 3 Pins als 12, 11 &10 und setzt dann 4 Displays (maximal 8 Displays) // globale Variablenbyte Intensität =7; // Standardintensität/Helligkeit (0-15)byte clock_mode =0; // Standarduhrmodus. Standard =0 (basic_mode)bool random_mode =0; // Zufallsmodus definieren - ändert den Anzeigetyp alle paar Stunden. Standard =0 (aus)byte old_mode =clock_mode; // Speichert den vorherigen Uhrmodus. Wenn wir also zum Datum oder was auch immer gehen, wissen wir, zu welchem ​​Modus wir zurückkehren müssen after.bool ampm =0; // Definiere 12 oder 24 Stunden Zeit. 0 =24 Stunden. 1 =12 Stundenbyte change_mode_time =0; // Hält die Stunde, wenn sich der Uhrmodus das nächste Mal ändert, wenn im Zufallsmodus.unsigned lange Verzögerungszeit =500; // Wir warten immer ein bisschen zwischen den Aktualisierungen von displayint rtc[7]; // Hält die Ausgabezeichen der Echtzeituhr Tage[7][4] ={ "Sun", "Mo", "Di", "Mi", "Do", "Fr", "Sa"}; //day Array - wird in den Modi Slide, Basic_mode und Jumble verwendet (Der DS1307 gibt 1-7 Werte für den Wochentag aus)char daysfull[7][9] ={ "Sunday", "Monday", "Tuesday", "Wed ", "Donnerstag", "Freitag", "Samstag"};char suffix[4][3] ={ "st", "nd", "rd", "th"}; //Datumssuffix-Array, wird in den Modi slide, basic_mode und jumble verwendet. zB 1st 2nd ...//define constants#define NUM_DISPLAY_MODES 3 // Zahlenanzeigemodi (mit Null als erster Modus)#define NUM_SETTINGS_MODES 4 // Zahleneinstellungsmodi =6 (mit Null als erster Modus)# define SLIDE_DELAY 20 // Die Zeit in Millisekunden für den Slide-Effekt pro Zeichen im Slide-Modus. Stellen Sie dies höher für einen langsameren Effekt#define cls clear_display // Clear displayRTC_DS1307 ds1307; // RTC-Objekt erstellenButton buttonA =Button(2, BUTTON_PULLUP); // Schaltfläche A einrichten (mit Schaltflächenbibliothek)Button buttonB =Button(3, BUTTON_PULLUP); // Schaltfläche B einrichten (mit Schaltflächenbibliothek)void setup () { DigitalWrite (2, HIGH); // Pullup-Widerstand für Taste an Pin 2 einschalten DigitalWrite (3, HIGH); // Pullup-Widerstand für Taste an Pin 3 einschalten DigitalWrite (4, HIGH); // Pullup-Widerstand für Taste an Pin 4 einschalten Serial.begin (9600); // Seriell starten // Die 4 Matrix-Panels initialisieren // Wir haben die Anzahl der Geräte bereits eingestellt, als wir die LedControl erstellt haben int devices =lc.getDeviceCount(); //wir müssen alle Geräte in einer Schleife für (int address =0; address =0 &&x <=7) { Adresse =3; } if (x>=8 &&x <=15) { Adresse =2; x =x – 8; } if (x>=16 &&x <=23) { Adresse =1; x =x - 16; } if (x>=24 &&x <=31) { Adresse =0; x =x - 24; aufrechtzuerhalten. Wenn (val ==1) {lc.setLed (Adresse, y, x, wahr); aufrechtzuerhalten. Sonst { lc.setLed (Adresse, y, x, falsch); }} // clear screenvoid clear_display () { for (Byte-Adresse =0; Adresse <4; Adresse ++) { lc.clearDisplay (Adresse); }} // Bildschirm ausblenden downvoid fade_down () { // von globaler Intensität auf 1 überblenden für (Byte i =Intensität; i> 0; i--) { für (Byte-Adresse =0; Adresse <4; Adresse ++) { lc .setIntensity(Adresse, i); } Verzögerung (30); // ändern Sie dies, um die Geschwindigkeit des Abblendens zu ändern} clear_display (); // Anzeige komplett löschen (aus) // Intensität auf globalen Wert zurücksetzen für (Byte-Adresse =0; Adresse <4; Adresse ++) {lc.setIntensity (Adresse, Intensität); }} // LED-Test einschalten und Softwareversionsnummer anzeigenvoid printver () { Byte i =0; char ver_a[9] ="Vers 1.0"; char ver_b[9] ="Hallo!"; // Alle LEDs testen. for (Byte x =0; x <=31; x++) { for (Byte y =0; y <=7; y++) { Plot(x, y, 1); } } Verzögerung (500); fade_down(); while (ver_a[i]) { puttinychar((i * 4), 1, ver_a[i]); Verzögerung (35); i++; } Verzögerung (700); fade_down(); ich =0; while (ver_b[i]) { puttinychar((i * 4), 1, ver_b[i]); Verzögerung (35); i++; } Verzögerung (700); fade_down();}// puttinychar// Kopiere eine 3x5-Zeichen-Glyphe aus der myfont-Datenstruktur, um den Speicher anzuzeigen, mit der linken oberen Ecke an der angegebenen Koordinate // Dies ist nicht optimiert und verwendet einfach plot(), um jeden Punkt zu zeichnen.void puttinychar (Byte x, Byte y, Zeichen c) { Byte Punkte; if (c>='A' &&c <='Z' || (c>='a' &&c <='z') ) { c &=0x1F; // A-Z wird 1-26 zugeordnet} else if (c>='0' &&c <='9') { c =(c - '0') + 32; aufrechtzuerhalten. Sonst wenn (c =='') {c =0; // Leerzeichen} else if (c =='.') {c =27; // Punkt} else if (c ==':') {c =28; // Doppelpunkt} else if (c =='\'') { c =29; // einfaches Anführungszeichen} else if (c =='!') { c =30; // einfaches Anführungszeichen} else if (c =='?') { c =31; // einfaches Anführungszeichen } for (byte col =0; col <3; col++) {dots =pgm_read_byte_near(&mytinyfont[c][col]); for (char row =0; row <5; row++) { if (dots &(16>> row)) plot(x + col, y + row, 1); else plot(x + Spalte, y + Zeile, 0); } }}void putnormalchar(byte x, byte y, char c){ Bytepunkte; // if (c>='A' &&c <='Z' || (c>='a' &&c <='z') ) { // c &=0x1F; // A-Z wird auf 1-26 abgebildet //} if (c>='A' &&c <='Z' ) { c &=0x1F; // A-Z wird auf 1-26 abgebildet } else if (c>='a' &&c <='z') { c =(c - 'a') + 41; // A-Z wird 41-67 zugeordnet} else if (c>='0' &&c <='9') { c =(c - '0') + 31; aufrechtzuerhalten. Sonst wenn (c =='') {c =0; // Leerzeichen} else if (c =='.') {c =27; // Punkt} else if (c =='\'') {c =28; // einfaches Anführungszeichen} else if (c ==':') { c =29; // clock_mode selector arrow} else if (c =='>') {c =30; // clock_mode selector arrow} else if (c>=-80 &&c <=-67) {c *=-1; } for (char col =0; col <5; col++) {dots =pgm_read_byte_near(&myfont[c][col]); for (char row =0; row <7; row++) { //überprüfe, ob die Koordinaten auf dem Bildschirm sind, bevor du versuchst zu zeichnen //if ((x>=0) &&(x <=31) &&(y>=0) &&(y <=7)) { if (dots &(64>> row)) { // nur 7 Zeilen. Plot(x + Spalte, y + Zeile, 1); aufrechtzuerhalten. Sonst { Plot (x + Spalte, y + Zeile, 0); } //} } }}//small_mode//zeigt die Zeit in kleinen 3x5 Zeichen mit Sekunden an displayvoid small_mode() { char textchar[8]; // die 16 Zeichen auf dem Display Byte mins =100; //mins byte secs =rtc[0]; //Sekunden Byte old_secs =secs; // hält den alten Sekundenwert - seit der letzten Aktualisierung der Sekunden oder Anzeige - wird verwendet, um zu überprüfen, ob sich die Sekunden geändert haben cls (); // Hauptschleife der Uhr ausführen, solange run_mode true zurückgibt während (run_mode ()) { get_time (); // auf Tastendruck prüfen if (buttonA.uniquePress()) {switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); Rückkehr; } // Wenn sich die Sekunden geändert haben, aktualisieren Sie sie auf dem Display secs =rtc [0]; if (secs !=old_secs) { //secs char buffer [3]; itoa (Sek., Puffer, 10); //fix - wie sonst wenn num führende Null hat, z.B. "03" Sek., itoa wandelt dies in Zeichen mit Leerzeichen "3" um. if (Sek <10) { Puffer[1] =Puffer[0]; Puffer[0] ='0'; } puttinychar( 20, 1, ':'); //Sekunden Doppelpunkt puttinychar( 24, 1, Puffer[0]); // Sekunden puttinychar( 28, 1, Puffer[1]); //Sekunden old_secs =secs; } //Wenn sich die Minute ändert, ändern Sie die Zeit if (mins!=rtc[1]) { //setze diese für den nächsten Vergleich zurück mins =rtc[1]; Byte-Stunden =rtc[2]; if (Stunden> 12) { Stunden =Stunden - Ampm * 12; } if (Stunden <1) { Stunden =Stunden + Ampere * 12; } //Byte nach unten =rtc[3]; // der DS1307 gibt 0 - 6 aus, wobei 0 =Sonntag 0 - 6 wobei 0 =Sonntag. //Byte-Datum =rtc[4]; // Zeichenpuffer setzen [3]; itoa (Stunden, Puffer, 10); //fix - wie sonst wenn num führende Null hat, z.B. "03" Stunden, itoa wandelt dies in Zeichen mit Leerzeichen "3" um. if (Stunden <10) { Puffer[1] =Puffer[0]; // Wenn wir uns im 12-Stunden-Modus befinden, löschen Sie die führende Null. if (ampm) { Puffer[0] =' '; } else { Puffer[0] ='0'; } } //Stundenzeichen setzen textchar[0] =buffer[0]; textchar[1] =Puffer[1]; textchar[2] =':'; itoa (Minuten, Puffer, 10); if (mins <10) { Puffer[1] =Puffer[0]; Puffer[0] ='0'; } //Mindestens Zeichen setzen textchar[3] =buffer[0]; textchar[4] =Puffer[1]; // Sekunden tun textchar[5] =':'; Puffer[3]; Sekunden =rtc[0]; itoa (Sek., Puffer, 10); //fix - wie sonst wenn num führende Null hat, z.B. "03" Sek., itoa wandelt dies in Zeichen mit Leerzeichen "3" um. if (Sek <10) { Puffer[1] =Puffer[0]; Puffer[0] ='0'; } //Sekunden setzen textchar[6] =buffer[0]; textchar[7] =Puffer[1]; Byte x =0; Byte y =0; // jedes Zeichen ausgeben für (Byte x =0; x <6; x++) { puttinychar( x * 4, 1, textchar[x]); } } Verzögerung (50); } fade_down();}// basic_mode()// Zeit in 5x7 Zeichen anzeigenvoid basic_mode(){ cls(); Zeichenpuffer [3]; // für die Umwandlung von Int in Char, um RTC-Werte in Chars umzuwandeln, können wir auf dem Bildschirm drucken Byte-Offset =0; // Wird verwendet, um die x-Position der Ziffern zu verschieben und die Anzeige zu zentrieren, wenn wir uns im 12-Stunden-Modus befinden und die Uhr nur 3 Ziffern anzeigt. z.B. 3:21 Byte x, y; // Wird verwendet, um ein klares Feld über der linken "1" des Displays zu zeichnen, wenn wir von 12:59 -> 1:00 Uhr im 12-Stunden-Modus rollen. // 12/24-Stunden-Konvertierung durchführen, wenn Ampm auf 1 Byte Stunden gesetzt ist =rtc [2]; if (Stunden> 12) { Stunden =Stunden - Ampm * 12; } if (Stunden <1) { Stunden =Stunden + Ampere * 12; } // Offset-Konvertierung durchführen, wenn (ampm &&Stunden <10) { Offset =2; } //setze die nächste Minute, wir zeigen das Datum bei //set_next_date(); // setze mins anfänglich auf den Wert 100 - so wird es in der ersten Schleife der Uhr nie gleich rtc[1] sein, was bedeutet, dass wir die Uhranzeige zeichnen, wenn wir die Funktion eingeben byte secs =100; Byte-Minuten =100; int-Zählung =0; // Hauptschleife der Uhr ausführen, solange run_mode true zurückgibt, während (run_mode ()) { // die Zeit vom Uhrenchip abrufen get_time (); // auf Tastendruck prüfen if (buttonA.uniquePress()) {switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); Rückkehr; } //prüfen, ob das Datum automatisch angezeigt wird //check_show_date(); // Zeichnen Sie das Blinken:als ob sich die Sekunden geändert haben. if (secs !=rtc[0]) {//update secs mit neuem Wert secs =rtc[0]; //zeichnen:Plot (15 - Offset, 2, 1); // oberstes Punktdiagramm (15 - Offset, 5, 1); // untere Punktzahl =400; } // Wenn die Anzahl abgelaufen ist, schalten Sie die aus:if (count ==0) { Plot (15 - Offset, 2, 0); // oberstes Punktdiagramm (15 - Offset, 5, 0); // unterer Punkt} else { count--; } // die Anzeige neu zeichnen, wenn die Taste gedrückt wurde oder wenn mins !=rtc[1] dh wenn sich die Zeit von der in mins gespeicherten geändert hat (wird auch bei der ersten Eingabe der Funktion ausgelöst, wenn mins 100 ist) if (mins !=rtc[1]) { //Minuten und Stunden mit den neuen Werten aktualisieren mins =rtc[1]; Stunden =rtc[2]; // Stunden von Ampere auf 12-Stunden-Modus einstellen if (hours> 12) {hours =hours - Ampm * 12; } if (Stunden <1) { Stunden =Stunden + Ampere * 12; } itoa (Stunden, Puffer, 10); //wenn Stunden <10 die Zahl z.B. "3" Stunden, itoa wandelt dies in Zeichen mit Leerzeichen "3" um, die wir nicht wollen if (hours <10) { buffer[1] =buffer[0]; Puffer[0] ='0'; } // Stunden drucken // Wenn wir im 12-Stunden-Modus und Stunden <10 sind, drucken Sie die führende Null nicht und stellen Sie den Offset so ein, dass wir die Anzeige mit 3 Stellen zentrieren. if (ampm &&Stunden <10) {Offset =2; // Wenn die Zeit 1:00 Uhr ist, löschen Sie die gesamte Anzeige, da sich der Offset zu diesem Zeitpunkt ändert und wir das alte 12:59 Uhr ausblenden müssen if ((Stunden ==1 &&Mins ==0) ) {cls(); aufrechtzuerhalten.} Else {// Sonst kein Offset und Druckstunden-Zehner-Offset =0; // Wenn die Zeit 10:00 Uhr ist, löschen Sie die gesamte Anzeige, da sich der Offset zu diesem Zeitpunkt ändert und wir die alten 9:59 ausblenden müssen if (hours ==10 &&mins ==0) {cls(); } putnormalchar(1, 0, Puffer[0]); aufrechtzuerhalten. // Drucke Stunden Einerstelle putnormalchar(7 - Offset, 0, Puffer[1]); // Minuten drucken // führende Null hinzufügen, wenn Minuten <10 itoa (Minuten, Puffer, 10); if (mins <10) { Puffer[1] =Puffer[0]; Puffer[0] ='0'; } // Mins-Zehner und Einer-Ziffer drucken putnormalchar(19 - offset, 0, buffer[0]); putnormalchar(25 - Offset, 0, Puffer[1]); }} fade_down();} // wie basic_mode, aber mit Slide-Effektvoid slide() { byte digits_old[4] ={99, 99, 99, 99}; //alte Werte, in denen wir die Zeit speichern. Stellen Sie auf etwas ein, das anfangs nie mit der Zeit übereinstimmt, damit alle Ziffern gezeichnet werden, wenn der Modus beginnt byte digits_new[4]; // Die Zeit der neuen Ziffern wird verschoben, um das Byte digits_x_pos[4] ={25, 19, 7, 1} anzuzeigen; //x pos, für die jede Ziffer bei char gezeichnet werden soll old_char[2]; //wird verwendet, wenn wir itoa verwenden, um die aktuelle Ziffer (type byte) in ein char zu transponieren, um es an die Animationsfunktion zu übergeben char new_char[2]; //wird verwendet, wenn wir itoa verwenden, um die neue Ziffer (type byte) in ein Zeichen zu transponieren, um es an die Animationsfunktion zu übergeben //old_chars - speichert die 5 Tag- und Datumssuffixzeichen auf dem Display. z.B. "mon" und "st". Wir füttern diese als aktuelles Zeichen in die Folienanimation, wenn diese Zeichen aktualisiert werden. //Wir haben sie anfänglich als A gesendet, die verwendet werden, wenn die Clocl in den Modus wechselt und keine letzten Zeichen gespeichert werden. //char old_chars[6] ="AAAAAA"; // Zeichnen Sie den Doppelpunkt der Uhr auf dem Display cls (); putnormalchar( 13, 0, ':'); Byte old_secs =rtc[0]; // Sekunden in old_secs speichern. Wir vergleichen secs und alte secs. Wenn sie unterschiedlich sind, zeichnen wir die Anzeige neu // Laufen Sie die Hauptschleife der Uhr aus, solange run_mode true zurückgibt während (run_mode ()) { get_time (); // auf Tastendruck prüfen if (buttonA.uniquePress()) {switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); Rückkehr; } // Wenn sich die Sekunden geändert haben, aktualisieren Sie die Anzeige if (rtc[0] !=old_secs) { old_secs =rtc[0]; // 12/24-Stunden-Konvertierung durchführen, wenn Ampm auf 1 Byte Stunden gesetzt ist =rtc [2]; if (Stunden> 12) { Stunden =Stunden - Ampm * 12; } if (Stunden <1) { Stunden =Stunden + Ampere * 12; } //alle Datum und Uhrzeit in einzelne Ziffern aufteilen - in digits_new Array einkleben //rtc[0] =secs //Array Pos und Ziffer gespeichert //digits_new[0] =(rtc[0]%10); //0 - Sekunden Einsen //digits_new[1] =((rtc[0]/10)%10); ///1 - Zehner Sekunden //rtc[1] =Minuten digits_new[0] =(rtc[1] % 10); //2 - Mins Einer digits_new[1] =((rtc[1] / 10) % 10); //3 - Minuten Zehner //rtc[2] =Stunden digits_new[2] =(Stunden % 10); // - Stunde Einer digits_new[3] =((Stunden / 10) % 10); //5 - Zehner Stunden //rtc[4] =Datum //digits_new[6] =(rtc[4]%10); ///6 - Datumseiner //digits_new[7] =((rtc[4]/10)%10); //7 - Datum Zehner //Zeichne den Anfangsbildschirm aller Zeichen. Danach zeichnen wir nur noch die Änderungen. //vergleiche die Ziffern 0 bis 3 (Minuten und Stunden) für (byte i =0; i <=3; i++) { //prüfe, ob sich die Ziffer geändert hat... if (digits_old[i] !=digits_new[i]) { // 9-stufige Animationssequenz für jede der Reihe nach ausführen für (byte seq =0; seq <=8; seq++) { // Ziffer in String umwandeln itoa (digits_old[i], old_char, 10); itoa(digits_new[i], new_char, 10); // Wenn der 12-Stunden-Modus eingestellt ist und wir bei Ziffer 2 (Stunden-Zehner-Modus) sind, überprüfen Sie, ob dies eine Null ist. Wenn ja, löschen Sie es stattdessen, damit wir 14.00 Uhr und nicht 14.00 Uhr erhalten if (ampm &&i ==3) { if (digits_new[3] ==0) { new_char[0] =' '; } if (digits_old[3] ==0) { old_char[0] =' '; } } // den Animationsrahmen für jede Ziffer zeichnen slideanim(digits_x_pos[i], 0, seq, old_char[0], new_char[0]); Verzögerung (SLIDE_DELAY); } } } /* // Datumsziffer 6 (Einer) und (7) Zehner vergleichen - wenn sich einer dieser Werte ändert, müssen wir die Datumszeile aktualisieren. Wir vergleichen das Datum Zehner wie zB vom 31. Januar -> 01. Februar dann ändert sich die Einerziffer nicht if ((digits_old[6] !=digits_new[6]) || (digits_old[7] !=digits_new[7])) { // Ändere den angezeigten Tag. Schleife unten geht der Reihe nach durch jeden der 3 Zeichen, z.B. "MON" für (byte day_char =0; day_char <=2; day_char++) {// die Animationssequenz für jedes Zeichen ausführen für (byte seq =0; seq <=8; seq++) {//den Tag (0 - 6 .) ) Lesen Sie diese Zahl in das Tage-Char-Array ein. die Sekundenzahl im Array 0-2 erhält die 3 Zeichen des Tagesnamens, z.B. m o n slideanim(6*day_char,8,seq,old_chars[day_char],days[rtc[3]][day_char]); // x day_char gibt uns die x-Position für die Zeichenverzögerung (SLIDE_DELAY); } //speichere die alten Zeichen im Array old_chars in Array Pos 0-2. Wir verwenden dies das nächste Mal, wenn wir den Tag ändern und füttern es als aktuelles Zeichen in die Animation. Das aktualisierte Zeichen wird als neues Zeichen eingegeben. old_chars[day_char] =days[rtc[3]][day_char]; } // Ändere die Zehnerstelle des Datums (falls erforderlich) und die Einerstelle. (Die Ziffer des Datums wird sich immer ändern, aber das Einfügen in die 'if'-Schleife macht es ein bisschen sauberer.) for (byte i =7; i>=6; i--){ if (digits_old[i] !=digits_new[i]) { for (byte seq =0; seq <=8; seq++){ itoa(digits_old[i],old_char,10); itoa(digits_new[i],new_char,10); slideanim(digits_x_pos[i],8,seq,old_char[0],new_char[0]); Verzögerung (SLIDE_DELAY); } } } // Ausgabe des Tagsuffix "nd" "rd" "th" usw. Zuerst Datum 2 Buchstabensuffix berechnen - zB st, nd, rd, th Byte s =3; //die Position, aus der unser Suffix-Array gelesen werden soll. Byte-Datum =rtc[4]; if(Datum ==1 || Datum ==21 || Datum ==31) { s =0; aufrechtzuerhalten. Sonst if (Datum ==2 || Datum ==22) { s =1; aufrechtzuerhalten. Sonst if (Datum ==3 || Datum ==23) { s =2; } for (byte suffix_char =0; suffix_char <=1; suffix_char++){ for (byte seq =0; seq <=8; seq++){ slideanim((suffix_char*6)+36,8,seq,old_chars[suffix_char+3 ],Suffix[s][Suffix_char]); // wir übergeben das old_char-Array char als aktuelles Zeichen und das Suffix-Array als neues Zeichen delay(SLIDE_DELAY); } //Speichern Sie das Suffic-Zeichen im alten chars-Array bei Array-Pos 3 und 5. Wir verwenden diese Zeichen das nächste Mal, wenn wir das Suffix ändern und füttern es als aktuelles Zeichen in die Animation. Das aktualisierte Zeichen wird als neues Zeichen eingegeben. old_chars[suffix_char+3] =Suffix[s][suffix_char]; } } // Ende do Datumszeile */ // Digita Array speichern tol zum Vergleich nächste Schleife for (byte i =0; i <=3; i++) { digits_old[i] =digits_new[i]; } }//secs/oldsecs }//while loop fade_down();}//aufgerufen von slide// dies zeichnet die Animation eines ein- und eines weggleitenden Zeichens. Es gibt 8 Schritte in der Animation, wir rufen die Funktion auf, um einen der Schritte von 0-7 zu zeichnen // Eingaben sind Zeichen x und y, Animationsbildsequenz (0-7) und die aktuellen und neuen Zeichen, die gezeichnet werden.void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) { // Um ​​ein Zeichen aus- und wieder einzuschalten benötigen wir 9 Schritte oder Frames in Folge... // seq# 0123456 <-Zeilen des Displays // | ||||||| // seq0 0123456 START - alle Zeilen des Displays 0-6 zeigen die aktuellen Zeichen Zeilen 0-6 // seq1 012345 aktuelles Zeichen bewegt sich eine Zeile nach unten auf dem Display. Wir sehen nur die Zeilen 0-5. Es gibt an den Anzeigepositionen 1-6 Oben wird eine leere Zeile eingefügt // seq2 6 01234 Das aktuelle Zeichen bewegt sich um 2 Zeilen nach unten. wir sehen jetzt nur die Zeilen 0-4 bei den Anzeigezeilen 2-6 auf dem Display. Zeile 1 der Anzeige ist leer. Zeile 0 zeigt Zeile 6 des neuen Zeichens // seq3 56 0123 // seq4 456 012 halb altes / halb neues Zeichen // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456 END - alle Zeilen zeigen das neue char //von oben sehen wir... //currentchar läuft 0-6, dann 0-5, dann 0-4 bis 0. Die Y-Startposition erhöht sich jedes Mal um 1 Zeile. // neues Zeichen läuft 6, dann 5-6, dann 4-6, dann 3-6. Die Y-Startposition erhöht sich jedes Mal um 1 Reihe. // Wenn die Sequenznummer kleiner als 7 ist, müssen wir das aktuelle Zeichen zeichnen if (sequence <7) { byte dots; // if (current_c>='A' &&|| (current_c>='a' &¤t_c <='z') ) { // current_c &=0x1F; // A-Z wird 1-26 zugeordnet // } if (current_c>='A' &¤t_c <='Z' ) { current_c &=0x1F; // A-Z wird auf 1-26 abgebildet } else if (current_c>='a' &¤t_c <='z') { current_c =(current_c - 'a') + 41; // A-Z entspricht 41-67 } else if (current_c>='0' &¤t_c <='9') { current_c =(current_c - '0') + 31; aufrechtzuerhalten. Sonst if (current_c =='') { current_c =0; // Leerzeichen} else if (current_c =='.') { current_c =27; // Punkt} else if (current_c =='\'') { current_c =28; // einfaches Anführungszeichen} else if (current_c ==':') { current_c =29; //Doppelpunkt} else if (current_c =='>') {current_c =30; // clock_mode selector arrow } byte curr_char_row_max =7 - Sequenz; // Die maximale Anzahl der zu zeichnenden Zeilen beträgt 6 - Sequenznummer Byte start_y =Sequenz; // y-Position zum Beginnen - ist identisch mit der Sequenznummer. Wir inc diese jede Schleife // Plotten jede Zeile bis zum Zeilenmaximum (berechnet aus der Sequenznummer) for (byte curr_char_row =0; curr_char_row <=curr_char_row_max; curr_char_row++) { for (byte col =0; col <5; col++) { dots =pgm_read_byte_near(&myfont[current_c][col]); if (dots &(64>> curr_char_row)) plot(x + col, y + start_y, 1); // Plot auf Else Plot (x + col, y + start_y, 0); //sonse plot led off } start_y++; // füge eins zu y hinzu, damit wir die nächste Zeile eins nach unten zeichnen } } //Zeichne eine Leerzeile zwischen den Zeichen, wenn die Sequenz zwischen 1 und 7 liegt. Wenn wir dies nicht tun, erhalten wir die Reste der aktuellen Zeichen letzte Position links auf dem Display if (sequence>=1 &&sequence <=8) { for (byte col =0; col <5; col++) { plot(x + col, y + (sequence - 1), 0); //die y-Position zum Zeichnen der Linie entspricht der Sequenznummer - 1 } } //Wenn die Sequenz größer als 2 ist, müssen wir auch mit dem Zeichnen des neuen Zeichens beginnen if (sequence>=2) { //char Byte berechnen Punkte; //if (new_c>='A' &&new_c <='Z' || (new_c>='a' &&new_c <='z') ) { // new_c &=0x1F; // A-Z entspricht 1-26 //} if (new_c>='A' &&new_c <='Z' ) { new_c &=0x1F; // A-Z wird auf 1-26 abgebildet } else if (new_c>='a' &&new_c <='z') { new_c =(new_c - 'a') + 41; // A-Z entspricht 41-67 } else if (new_c>='0' &&new_c <='9') { new_c =(new_c - '0') + 31; aufrechtzuerhalten. Sonst if (new_c =='') {new_c =0; // Leerzeichen} else if (new_c =='.') {new_c =27; // Punkt} else if (new_c =='\'') {new_c =28; // einfaches Anführungszeichen} else if (new_c ==':') { new_c =29; // clock_mode selector arrow} else if (new_c =='>') {new_c =30; // Clock_mode-Selektorpfeil} Byte newcharrowmin =6 - (Sequenz - 2); //minimale Zeilennummer zum Zeichnen für neues Zeichen - dies erzeugt eine Ausgabe von 6 bis 0, wenn die Sequenznummern 2-8 zugeführt werden. Dies ist die minimal zu zeichnende Zeile für das neue Zeichenbyte start_y =0; // y-Position zum Beginnen - ist identisch mit der Sequenznummer. wir inc es jede Zeile // Zeichnen Sie jede Zeile vom Zeilenminimum (berechnet durch die Sequenznummer) bis zu 6 für (byte newcharrow =newcharrowmin; newcharrow <=6; newcharrow++) { for (byte col =0; col <5; col++ .) ) { Punkte =pgm_read_byte_near(&myfont[new_c][col]); if (dots &(64>> newcharrow)) plot(x + col, y + start_y, 1); // Plot auf Else Plot (x + col, y + start_y, 0); //sonse Plot führte aus } start_y++; // füge eins zu y hinzu, damit wir die nächste Zeile eins nach unten zeichnen } }} // eine Uhr mit Worten statt mit Zahlen druckenvoid word_clock() { cls(); Zeichenzahlen[19][10] ={ "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn" }; char numberstens[5][7] ={ "zehn", "zwanzig", "dreißig", "vierzig", "fünfzig" }; //potenziell 3 Zeilen zum Anzeigen von char str_a[8]; char str_b[8]; char str_c[8]; //Byte Stunden_y, Mins_y; //Stunden und Minuten und Positionen für Stunden- und Minutenzeilen byte hours =rtc[2]; if (Stunden> 12) { Stunden =Stunden - Ampm * 12; } if (Stunden <1) { Stunden =Stunden + Ampere * 12; } Zeit kriegen(); // Holen Sie sich die Zeit vom Uhrenchip-Byte old_mins =100; //mins in old_mins speichern. Wir vergleichen Minuten und alte Minuten und wenn sie sich unterscheiden, zeichnen wir die Anzeige neu. Stellen Sie dies anfänglich auf 100 ein, damit die Anzeige beim Start des Modus gezeichnet wird. Byte-Minuten; // Hauptschleife der Uhr ausführen, solange run_mode true zurückgibt while (run_mode ()) { // auf Tastendruck prüfen if (buttonA.uniquePress ()) { switch_mode (); Rückkehr; } if (buttonB.uniquePress()) { display_date(); } Zeit kriegen(); // die Zeit vom Uhrenchip abrufen mins =rtc[1]; //mins abrufen //wenn mins sich von old_mins unterscheiden - Anzeige neu zeichnen if (mins !=old_mins) { //old_mins mit aktuellem mins-Wert aktualisieren old_mins =mins; // diese für den nächsten Vergleich zurücksetzen mins =rtc[1]; Stunden =rtc[2]; // Stunden in das 12-Stunden-Format umwandeln if (Stunden> 12) { Stunden =Stunden - 12; } if (Stunden ==0) { Stunden =12; } // Mins-Wert in zwei separate Ziffern aufteilen Int Minsdigit =rtc[1] % 10; Byte Minsziffern =(rtc[1] / 10) % 10; // wenn Minuten <=10, dann muss die obere Zeile "minsdigti past" lesen und die untere Zeile lautet Stunden if (mins <10) { strcpy (str_a, numbers[minsdigit - 1]); strcpy (str_b, "VERGANGEN"); strcpy (str_c, Zahlen[Stunden - 1]); } //Wenn Mins =10, kann Minsdigit wie oben nicht verwendet werden, also sozialer Fall, um 10 nach /n Stunde zu drucken. if (mins ==10) { strcpy (str_a, numbers[9]); strcpy (str_b, " PAST"); strcpy (str_c, Zahlen[Stunden - 1]); } //Wenn die Zeit nicht auf der Stunde steht - d.h. beide Minutenziffern sind nicht Null, //dann lassen Sie die erste Zeile "Stunden" und die zweite und dritte Zeile "Minstens" "Minuten" lesen, z.B. "drei /n zwanzig /n eins" else if (minsdigitten !=0 &&minsdigit !=0 ) { strcpy (str_a, numbers[hours - 1]); // wenn mins im Teenager ist, verwenden Sie teens aus dem Zahlen-Array für die 2. Zeile, z. "fünfzehn" //if (mins>=11 &&mins <=19) { if (mins <=19) { strcpy (str_b, numbers[mins - 1]); } else { strcpy (str_b, numberstens[minsdigitten - 1]); strcpy (str_c, Zahlen[minsdigit - 1]); } } // wenn die Mins-Ziffer null ist, drucke es nicht. lesen lesen "Stunden" "minstens" z.B. "drei /n zwanzig" else if (minsdigitten !=0 &&minsdigit ==0 ) { strcpy (str_a, numbers[hours - 1]); strcpy (str_b, numberstens[minsdigitten - 1]); strcpy (str_c, ""); } // wenn beide Minuten null sind, dh es steht zur Stunde, lautet die obere Zeile "hours" und die untere Zeile "o'clock" else if (minsdigitten ==0 &&minsdigit ==0 ) { strcpy (str_a, Zahlen [Stunden - 1]); strcpy (str_b, "O'CLOCK"); strcpy (str_c, ""); } } // Trainingszeit beenden // in einer Schleife laufen // Zeile drucken ein "zwölf" Byte len =0; while (str_a[len]) { len++; }; // Länge des Nachrichtenbytes abrufen offset_top =(31 - ((len - 1) * 4)) / 2; // // Stundenzeilenbyte zeichnen i =0; while (str_a[i]) { puttinychar((i * 4) + offset_top, 1, str_a[i]); i++; } // Anzeige halten, aber prüfen, ob Tastendrücke gedrückt werden Int counter =1000; Während (Zähler> 0) {// auf Tastendruck prüfen if (buttonA.uniquePress()) {switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); } Verzögerung(1); Zähler--; } fade_down(); // Zeile drucken b len =0; while (str_b[len]) { len++; }; // Länge der Nachricht abrufen offset_top =(31 - ((len - 1) * 4)) / 2; ich =0; while (str_b[i]) { puttinychar((i * 4) + offset_top, 1, str_b[i]); i++; } // Display halten, aber auf Tastendrücke prüfen Counter =1000; while (Zähler> 0) { if (buttonA.uniquePress()) { switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); } Verzögerung(1); Zähler--; } fade_down(); // drucke Zeile c, falls vorhanden. len =0; while (str_c[len]) { len++; }; // Länge der Nachricht abrufen offset_top =(31 - ((len - 1) * 4)) / 2; ich =0; while (str_c[i]) { puttinychar((i * 4) + offset_top, 1, str_c[i]); i++; } Zähler =1000; Während (Zähler> 0) {// auf Tastendruck prüfen if (buttonA.uniquePress()) {switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); } Verzögerung(1); Zähler--; } fade_down(); // Display leer halten, aber auf Tastendrücke prüfen, bevor erneut gestartet wird. Zähler =1000; Während (Zähler> 0) {// auf Tastendruck prüfen if (buttonA.uniquePress()) {switch_mode(); Rückkehr; } if (buttonB.uniquePress()) { display_date(); } Verzögerung(1); Zähler--; } } fade_down();} /// scroll message - wird derzeit nicht verwendet - zu langsam.void scroll() { char message[] ={"Hello There"}; cls(); Byte p =6; //aktuelle Position im String-Byte chara[] ={0, 1, 2, 3, 4, 5}; //Zeichen aus String int x[] ={0, 6, 12, 18, 24, 30}; //xpos für jedes Zeichenbyte y =0; //y pos // clear_buffer(); while (message[p] !='\0') { //alle 6 Zeichen zeichnen für (byte c =0; c <6; c++) { putnormalchar(x[c],y,message[ chara[c] ] ); // Zeichne eine Linie von Pixeln, die nach jedem Zeichen ausgeschaltet sind, andernfalls haben die Lücken zwischen den Zeichen noch Pixel vom vorherigen Zeichen für (byte yy =0; yy <8; yy ++) { plot(x[c] + 5, jj, 0); } // von jeder Zeichenposition einen nehmen x[c] =x[c] - 1; } //ein Zeichen zurücksetzen, wenn es für (byte i =0; i <=5; i++) { if (x[i] <-5 ) { x[i] =31; chara[i] =p; p++; } } }} //display_date - Wochentag, Datum und Monat mit einem blinkenden Cursor ausgeben effectvoid display_date(){ cls(); // Lesen Sie das Datum aus dem DS1307-Byte dow =rtc[3]; // Wochentag 0 =Sonntag byte date =rtc[4]; Byte Monat =rtc[5] - 1; //Array von Monatsnamen, die auf dem Display gedruckt werden sollen. Einige sind gekürzt, da wir nur 8 Zeichen haben, um mit den Zeichenmonatsnamen zu spielen[12][9] ={ "Januar", "Februar", "März", "April", "May", "June", "Juli" , "August", "Sept", "Oktober", "November", "Dezember" }; //print the day name //get length of text in pixels, that way we can centre it on the display by divindin the remaining pixels b2 and using that as an offset byte len =0; while(daysfull[dow][len]) { len++; }; byte offset =(31 - ((len-1)*4)) / 2; //our offset to centre up the text //print the name int i =0; while(daysfull[dow][i]) { puttinychar((i*4) + offset , 1, daysfull[dow][i]); i++; } Verzögerung (1000); fade_down(); cls(); // print date numerals char buffer[3]; itoa(date,buffer,10); offset =10; //offset to centre text if 3 chars - e.g. 3rd // first work out date 2 letter suffix - eg st, nd, rd, th etc // char suffix[4][3]={"st", "nd", "rd", "th" }; is defined at top of code byte s =3; if(date ==1 || date ==21 || date ==31) { s =0; } else if (date ==2 || date ==22) { s =1; } else if (date ==3 || date ==23) { s =2; } //print the 1st date number puttinychar(0+offset, 1, buffer[0]); //if date is under 10 - then we only have 1 digit so set positions of sufix etc one character nearer byte suffixposx =4; //if date over 9 then print second number and set xpos of suffix to be 1 char further away if (date> 9){ suffixposx =8; puttinychar(4+offset, 1, buffer[1]); offset =8; //offset to centre text if 4 chars } //print the 2 suffix characters puttinychar(suffixposx+offset, 1, suffix[s][0]); puttinychar(suffixposx+4+offset, 1, suffix[s][1]); Verzögerung (1000); fade_down(); //print the month name //get length of text in pixels, that way we can centre it on the display by divindin the remaining pixels b2 and using that as an offset len =0; while(monthnames[month][len]) { len++; }; offset =(31 - ((len-1)*4)) / 2; //our offset to centre up the text i =0; while(monthnames[month][i]) { puttinychar((i*4) +offset, 1, monthnames[month][i]); i++; } Verzögerung (1000); fade_down();}//dislpay menu to change the clock modevoid switch_mode() { //remember mode we are in. We use this value if we go into settings mode, so we can change back from settings mode (6) to whatever mode we were in. old_mode =clock_mode; char* modes[] ={ "Basic", "Small", "Slide", "Words", "Setup" }; byte next_clock_mode; byte firstrun =1; //loop waiting for button (timeout after 35 loops to return to mode X) for (int count =0; count <35; count++) { //if user hits button, change the clock_mode if (buttonA.uniquePress() || firstrun ==1) { count =0; cls(); if (firstrun ==0) { clock_mode++; } if (clock_mode> NUM_DISPLAY_MODES + 1 ) { clock_mode =0; } //print arrown and current clock_mode name on line one and print next clock_mode name on line two char str_top[9]; //strcpy (str_top, "-"); strcpy (str_top, modes[clock_mode]); next_clock_mode =clock_mode + 1; if (next_clock_mode> NUM_DISPLAY_MODES + 1 ) { next_clock_mode =0; } byte i =0; while (str_top[i]) { putnormalchar(i * 6, 0, str_top[i]); i++; } firstrun =0; } Verzögerung (50); }}//run clock main loop as long as run_mode returns truebyte run_mode() { //if random mode is on... check the hour when we change mode. if (random_mode) { //if hour value in change mode time =hours. then reurn false =i.e. exit mode. if (change_mode_time ==rtc[2]) { //set the next random clock mode and time to change it set_next_random(); //exit the current mode. 0 zurückgeben; } } //else return 1 - keep running in this mode return 1;}//set the next hour the clock will change mode when random mode is onvoid set_next_random() { //set the next hour the clock mode will change - current time plus 1 - 4 hours get_time(); change_mode_time =rtc[2] + random (1, 5); //if change_mode_time now happens to be over 23, then set it to between 1 and 3am if (change_mode_time> 23) { change_mode_time =random (1, 4); } //set the new clock mode clock_mode =random(0, NUM_DISPLAY_MODES + 1); //pick new random clock mode}//dislpay menu to change the clock settingsvoid setup_menu() { char* set_modes[] ={ "Rndom", "24 Hr","Set", "Brght", "Exit"}; if (ampm ==0) { set_modes[1] =("12 Hr"); } byte setting_mode =0; byte next_setting_mode; byte firstrun =1; //loop waiting for button (timeout after 35 loops to return to mode X) for(int count=0; count <35; count++) { //if user hits button, change the clock_mode if(buttonA.uniquePress() || firstrun ==1){ count =0; cls(); if (firstrun ==0) { setting_mode++; } if (setting_mode> NUM_SETTINGS_MODES) { setting_mode =0; } //print arrown and current clock_mode name on line one and print next clock_mode name on line two char str_top[9]; strcpy (str_top, set_modes[setting_mode]); next_setting_mode =setting_mode + 1; if (next_setting_mode> NUM_SETTINGS_MODES) { next_setting_mode =0; } byte i =0; while(str_top[i]) { putnormalchar(i*6, 0, str_top[i]); i++; } firstrun =0; } Verzögerung (50); } //pick the mode switch(setting_mode){ case 0:set_random(); brechen; case 1:set_ampm(); brechen; case 2:set_time(); brechen; case 3:set_intensity(); brechen; case 4://exit menu break; } //change the clock from mode 6 (settings) back to the one it was in before clock_mode=old_mode;}//toggle random mode - pick a different clock mode every few hoursvoid set_random(){ cls(); char text_a[9] ="Off"; char text_b[9] ="On"; byte i =0; //if random mode is on, turn it off if (random_mode){ //turn random mode off random_mode =0; //print a message on the display while(text_a[i]) { putnormalchar((i*6), 0, text_a[i]); i++; } } else { //turn randome mode on. random_mode =1; //set hour mode will change set_next_random(); //print a message on the display while(text_b[i]) { putnormalchar((i*6), 0, text_b[i]); i++; } } delay(1500); //leave the message up for a second or so}//set 12 or 24 hour clockvoid set_ampm() { // AM/PM or 24 hour clock mode - flip the bit (makes 0 into 1, or 1 into 0 for ampm mode) ampm =(ampm ^ 1); cls();}//change screen intensityintensityvoid set_intensity() { cls(); byte i =0; char text[7] ="Bright"; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i++; } //wait for button input while (!buttonA.uniquePress()) { levelbar (0,6,(intensity*2)+2,2); //display the intensity level as a bar while (buttonB.isPressed()) { if(intensity ==15) { intensity =0; cls (); } else { intensity++; } //print the new value i =0; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i++; } //display the intensity level as a bar levelbar (0,6,(intensity*2)+2,2); //change the brightness setting on the displays for (byte address =0; address <4; address++) { lc.setIntensity(address, intensity); } delay(150); } }}// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybarvoid levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x =0; x
LibrariesArduino
Keine Vorschau (nur Download).

Schaltpläne


Herstellungsprozess

  1. LED-Sequenzer
  2. Kuckucksuhr
  3. MATLAB - Matrix
  4. Mini-Bosskampf
  5. Hauptuhr
  6. Berliner Uhr
  7. Analoge LED-POV-Uhr
  8. LED-Matrix + Bewegungssensor-Türanzeige [Arduino Holiday]
  9. 8x LED-Beleuchtung mit Ton
  10. Arduino-Vierbeiner