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

7-Segment-Array-Uhr

Komponenten und Verbrauchsmaterialien

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
Echtzeituhr (RTC)
Kaufen Sie ein "DS1302 Real Time Clock Module for Arduino" und löten Sie den IC-Sockel und den Quarz ab.
× 1
CR1220 Batterie und Halter
Suchen Sie nach "5 Stück, schwarzes Gehäuse CR1220 CR1225 Knopfzellenhalter BS-1220-1"
× 1
Kondensator 0.1uf 1206 SMD
× 1
Kondensator 10uF 1206 SMD-Keramik
× 1
Tastschalter, von oben betätigt
12-mm-Variante mit Knopfleiste
× 4
3A Mini-DC-DC-Abwärtswandlermodul
× 1
0,28 Zoll gemeinsame Kathode 4-stellige 7-Segment-Anzeige
× 36
MAX7219 DIP-IC
× 18
Summer
× 1
Maschinen-Header
Sie benötigen sowohl männliche als auch weibliche Header - normalerweise in 40er Streifen, also 8 Streifen männlich bearbeitete Stifte und 8 Streifen bearbeitete Buchsen
× 1
DC-Steckdose
Suche nach "12V DC Netzteilbuchse Buchse für Panelmontage 5,5 x 2.ODZ2"
× 1

Notwendige Werkzeuge und Maschinen

Lötkolben (generisch)
3D-Drucker (generisch)

Apps und Onlinedienste

Arduino-IDE

Über dieses Projekt

Beim Durchstöbern von Hackaday.io stieß ich auf eine schöne Uhr mit einer Reihe von 7-Segment-Anzeigen von Frugha. Ich wollte das wirklich bauen, aber Frughas Version ist ziemlich groß, da sie 0,56" 7-Segment-Displays verwendet. Mein Design verwendet 0,28" 7-Segment-Displays, was es nur ein Viertel der Größe macht.

Die Software wurde neu geschrieben, um einen Wecker und einen Konfigurationsbildschirm zum Einstellen von Uhrzeit, Datum und Wecker zu integrieren.

Video

Konfigurationsbildschirm

Die Uhr wird über vier Tasten gesteuert. Die SELECT-Taste (oberste) zeigt den Konfigurationsbildschirm an. Die aktuelle Auswahl blinkt. Durch erneutes Drücken der SELECT-Taste werden die verschiedenen Konfigurationsabschnitte durchlaufen (d. h. Uhrzeit, Datum, Alarm, Melodie, Helligkeit, Datumsformat und Uhr).

Durch Drücken der ENTER-Taste (2. von oben) während eines der Menüpunkte ausgewählt ist, können Sie dessen Einstellungen ändern. Gibt es mehr als eine Einstellung für ein Menüelement, wechselt die ENTER-Taste zwischen diesen. Die aktive Einstellung blinkt.

Wenn eine Einstellung blinkt, ändern die Tasten UP und DOWN (die beiden unteren Tasten) die Einstellung.

Datumsbildschirm

Wenn Sie die ENTER-Taste (2. von oben nach unten) drücken, während die Uhr angezeigt wird, wird der Datumsbildschirm fünf Sekunden lang angezeigt.

Im Abschnitt Datumsformat auf dem Konfigurationsbildschirm können Sie das Datumsformat (TT-MM oder MM-TT) und die verwendete Schriftart einstellen.

Designüberlegungen

Um das Board-Design zu vereinfachen, verwendet meine Version 4-stellige Anzeigen anstelle der einstelligen Anzeigen, die in der Originalversion verwendet wurden. Da 0,28"-Displays klein sind, musste ich die MAX7219-Chips auf einer separaten Platine platzieren. Zur einfachen Verdrahtung werden bearbeitete Stift- und Buchsenleisten verwendet, um die Platinen zu verbinden.

Die Eagle-Dateien wurden mitgeliefert, falls Sie die Boards kommerziell herstellen lassen möchten oder wie ich es getan habe und sie selbst herstellen möchten. Ich habe die Toner-Methode bei der Herstellung verwendet.

Die Säulentafeln

Es müssen sechs Säulenbretter hergestellt werden, die alle Displays aufnehmen. Beginnen Sie beim Löten der Stiftleisten mit dem mittleren Satz und arbeiten Sie sich bis zur Außenkante vor. Heben Sie die Buchse mit einem Streichholz oder ähnlichem so weit an, dass Sie die Stifte leicht verlöten können. Verwenden Sie einen kleinen Lötkolben mit einer feinen Spitze und 0,5 mm Lötzinn.

Nachdem Sie die Säulenmodule erstellt haben, empfehle ich Ihnen, den Displayrahmen mit mattschwarzer Farbe zu lackieren. Dadurch werden die weißen Ränder nicht mehr angezeigt, wenn ein Display nicht perfekt mit seinem Nachbarn ausgerichtet ist. Nummerieren Sie jedes Säulenmodul ebenfalls mit einem Markierungsstift. Dies hilft beim Einsetzen in das MAX7219-Motherboard.

Das MAX7219-Motherboard

Beim Entwerfen des Motherboards und der Spaltenplatinen habe ich nicht die richtigen MAX7219-Segmente oder -Ziffern den entsprechenden Display-Pins zugeordnet. Ich wollte das PCB-Layout so einfach wie möglich halten und mich an alle Softwareunterschiede anpassen.

Ich empfehle, wenn es um die bearbeiteten Buchsen geht, diese zuerst auf die Stifte der Säulenplatinen zu setzen und dann die Baugruppe zu verlöten, während sie verbunden sind. Dies bedeutet, dass die Säulenstifte genau mit ihren entsprechenden Buchsen ausgerichtet sind. Sollten Sie sie entfernen müssen, stellen Sie durch die Nummerierung der Säulenmodule sicher, dass sie wieder an derselben Position eingesetzt werden.

Das MPU-Board

Die Mikroprozessorplatine enthält alle anderen Komponenten. Die vier Taster und zwei SMD-Kondensatoren sind auf der Rückseite der Platine montiert und alle anderen Komponenten sind auf der Vorderseite der Platine montiert. Um ein niedriges Profil zu halten, wird die FTDI-Stiftleiste, die normalerweise an den Arduino Pro Mini gelötet wird, jetzt direkt an die Platine gelötet. Zwei Drähte gehen von den DTR- und VCC-Pins direkt zur Platine.

Den Fall machen

Die STL-Dateien für Vorder- und Rückseite wurden mitgeliefert. Beide wurden mit einer 0,2-Schichthöhe und einer Krempe gedruckt. Auf der Vorderseite sind auch Stützen aktiviert, die nur die Bauplatte berührt haben.

Das Mainboard MAX7219 mit seinen Säulenmodulen wird von vorne eingeschoben. Wenn Sie es etwas locker finden, verwenden Sie ein oder zwei Lagen Abdeckband als Verpackung.

Die MPU-Platine ist auf der Rückseite heißgeklebt.

Software

Die Software erfordert, dass die MD_MAX72XX-Bibliothek in Ihrer Arduino-IDE installiert wurde. Ich habe meine Hardware_Test_V1-Skizze zum Testen bereitgestellt. Es leuchtet jedes Segment auf, damit Sie auf Kurzschlüsse oder Kabelbrüche überprüfen können. Sobald die Anzeige funktioniert, laden Sie die Clock_V4-Skizze hoch.

Code

  • Clock_V4.ino
  • Ziffern.h
  • Tunes.h
  • Button.h
  • Button.cpp
  • Hardware_Test_V1.zip
Clock_V4.inoC/C++
/*---------------------------------------------------------- ------ * 7 Segment Array Clock * * Basierend auf Clock von Frugha (https://hackaday.io/project/169632-7-segment-display-array-clock) * * Modifikationen von John Bradnam (jbrad2089@ gmail.com) * - Hardware geändert, um 0,28" 7-Segment-Displays zu verwenden. * - Die Reihenfolge von MAX7219-Geräten, Ziffern und Segmenten wurde auf einfaches * ansonsten komplexes PCB-Routing geändert. * - Hardware verwendet Arduino Mini Pro, DS1302 RTC und 4 Drucktasten * - Alarmfunktion mit wählbarer Alarmfunktion hinzugefügt * - Helligkeitseinstellung hinzugefügt * - Setup-Bildschirm zum Einstellen von Uhrzeit, Datum, Alarm, Musik und Helligkeit hinzugefügt * - Datumsbildschirm hinzugefügt (wird zwei Sekunden lang angezeigt, wenn die ENTER-Taste gedrückt wird * Update 2020 -06-16 * - Datumsformatoption auf dem Konfigurationsbildschirm hinzugefügt * - Zeitüberschreitung des Datumsbildschirms von 2 auf 5 Sekunden erhöht * - Konfigurierbare Schriftart für die Datumsanzeige hinzugefügt *---------------- ------------------------------------*/ #include #include #include # include #include #include "button.h"#include "Tunes.h"#include "Digits.h"#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW#define MAX_DEVICES 18#define LED_CLK 13 / / oder SCK (WHI)#define LED_DATA 11 // oder MOSI (BRN)#define LED_CS 10 // oder SS (YEL)#define SPEAKER 2#define SW_UP 3#define SW_DOWN 4#define RTC_CLK 5#define RTC_IO 6#define SW_ENTER 7#define RTC_CE 8#define SW_SELECT 9DS1302RTC rtc(RTC_CE, RTC_IO, RTC_CLK);// SPI Hardware InterfaceMD_MAX72XX mx =MD_MAX72XX(HARDWARE_TYPE, LED_CS, MAX_DEVICES);// Arbitrary Pins//x =_MD_HWARE LEDDATA LED_CLK, LED_CS, MAX_DEVICES); // EEPROM-Behandlung#define EEPROM_ADDRESS 0#define EEPROM_MAGIC 0x0BAD0DADtypedef struct { uint32_t magic; bool-Alarm; uint8_t Minuten; uint8_t Stunden; bool-Format12hr; uint8_t Helligkeit; uint8_t Melodie; bool formatDmy; bool squareFont;} EEPROM_DATA;EEPROM_DATA EepromData; //Aktuelle EEPROM-Einstellungenvoid clockButtonPressed(void);void enterButtonPressed(void);void downButtonPressed(void);void upButtonPressed(void);Button* clockButton;Button* enterButton;Button* downButton;Button* upButton;//Betriebsmodibool inSubMenu =false;#define SETUP_FLASH_RATE 200;unsigned long setupTimeout;bool setupDisplayState =false;enum ClockButtonModesEnum { CLOCK, TIME_SET, DATE_SET, ALARM_SET, TUNE_SET, BRIGHT_SET, FORMAT_SET };ClockButtonModesENUM clockMode =CLOCK;enum {TimeSetMenuEnum clockMode =CLOCK;enum TimeSetMenuEnum timeSetMode =TIME_HOUR;enum DateSetMenuEnum { DATE_YEAR, DATE_MONTH, DATE_DAY };DateSetMenuEnum dateSetMode =DATE_YEAR;enum AlarmSetMenuEnum { ALARM_HOUR, ALARM_MIN, ALARM_STATE };AlarmSetMenuEnum_Day_FORT_FormatTHMenuEnum_AlarmSetMON}FormatTHMenuEnum_FormatTH_Menum_FormatTH_Menum_FormatTH_Menum_FormatTHENUM_SETMODE; -1;bool alarmRinging =false; // wahr, wenn der Alarm onbool ist alarmCancelled =false; // Alarm von userbool abgebrochen musicPlaying =false; //true, wenn ein Songbool gespielt wird clockColon =false; //kolonint8_t dom[] ={31,28,31,30,31,30,31,31,30,31,30,31};tmElements_t newTime; // Wird verwendet, um ein neues Timevoid-Setup zu speichern () { Serial.begin (115200); //Eprom readEepromData(); // Schaltflächen initialisieren clockButton =new Button (SW_SELECT); enterButton =neuer Button (SW_ENTER); downButton =neuer Button (SW_DOWN); downButton->Repeat (downButtonPressed); upButton =neuer Button (SW_UP); upButton->Repeat(upButtonPressed); // Sound initialisieren PinMode (SPEAKER, OUTPUT); mx.begin(); mx.control(MD_MAX72XX::INTENSITY, EepromData.brightness); //0..MAX_INTENSITY mx.update(MD_MAX72XX::OFF); //Keine automatische Aktualisierung setSyncProvider(rtc.get); // die Funktion zum Abrufen der Uhrzeit von der RTC if (timeStatus () ! =timeSet) { Serial.println ( "RTC Sync Bad"); newTime.Year =CalendarYrToTm(2020); neueZeit.Monat =5; newTime.Day =30; neueZeit.Stunde =14; neueZeit.Minute =53; newTime.Second =0; time_t t =makeTime(newTime); setTime(t); rtc.set(t); if (rtc.set (t) !=0) {Serial.println ("Set Time Failed"); } } newTime.Year =CalendarYrToTm(year()); newTime.Month =Monat(); newTime.Day =day(); newTime.Hour =Stunde(); newTime.Minute =minute(); newTime.Second =second(); Serial.println ( "Zeit:" + String (newTime.Hour) + ":" + String (newTime.Minute) + ":" + String (newTime.Second)); Serial.println ( "Datum:" + String (newTime.Day) + "/" + String (newTime.Month) + "/" + String (tmYearToCalendar (newTime.Year))); ClockMode =CLOCK; showTime(true);}void loop(){ testButtons(); if (clockMode ==CLOCK) { showTime (false); if (EepromData.alarm &&EepromData.hours ==Stunde() &&EepromData.minutes ==Minute()) { if (!alarmCancelled) { alarmRinging =true; playSong (Melodien[EepromData.tune]); } } else { alarmCancelled =false; alarmRinging =false; } } else { showSetup (false); } Verzögerung(100);} //----------------------------------------- ---------------------- // Testen, ob irgendwelche Tasten gedrückt wurdenvoid testButtons () { // Tasten einzeln drücken if (clockButton->Pressed ()) { clockButtonPressed(); } if (enterButton->Pressed()) { enterButtonPressed(); } //Sie müssen das Ergebnis von gedrückt nicht überprüfen, da der Button-Handler seine Wiederholungsfunktion aufruft upButton->Pressed(); DownButton->Gedrückt();}//---------------------------------------------------- -----------------------//Handle CLOCK bttonvoid clockButtonPressed(){ if (cancelAlarm()) return; inSubMenu =false; clockMode =(clockMode ==FORMAT_SET) ? CLOCK :(ClockButtonModesEnum)((int)clockMode + 1); if (clockMode ==CLOCK) { Serial.println ("Saving Time:" + String (newTime.Hour) + ":" + String (newTime.Minute)); Serial.println ( " From:" + String (hour ()) + ":" + String (minute ())); if (newTime.Year !=CalendarYrToTm(year()) || newTime.Month !=month() || newTime.Day !=day() || newTime.Hour !=hour() || newTime.Minute !=Minute ()) {// Aktualisierungszeit Serial.println ( "RTC aktualisieren"); newTime.Second =second(); time_t t =makeTime(newTime); setTime(t); rtc.set(t); if (rtc.set (t) !=0) {Serial.println ("Set Time Failed"); } } writeEepromData(); showTime (wahr); aufrechtzuerhalten. Sonst { if (clockMode ==TIME_SET) { newTime.Year =CalendarYrToTm (year()); newTime.Month =Monat(); newTime.Day =day(); newTime.Hour =Stunde(); newTime.Minute =minute(); newTime.Second =second(); Serial.println ( "Ladezeit:" + String (hour ()) + ":" + String (minute ())); } showSetup (wahr); }}//---------------------------------------------------------- ------------------//Handle ENTER bttonvoid enterButtonPressed(){ if (cancelAlarm()) return; if (clockMode !=CLOCK) { if (!inSubMenu) { timeSetMode =TIME_HOUR; dateSetMode =DATE_YEAR; alarmSetMode =ALARM_HOUR; formatSetMode =DAY_MONTH; inSubMenu =true; } else { switch (clockMode) { case TIME_SET:timeSetMode =(timeSetMode ==TIME_FORMAT) ? TIME_HOUR :(TimeSetMenuEnum)((int)timeSetMode + 1); brechen; case DATE_SET:dateSetMode =(dateSetMode ==DATE_DAY) ? DATE_YEAR :(DateSetMenuEnum)((int)dateSetMode + 1); brechen; Fall ALARM_SET:alarmSetMode =(alarmSetMode ==ALARM_STATE) ? ALARM_HOUR :(AlarmSetMenuEnum)((int)alarmSetMode + 1); brechen; case FORMAT_SET:formatSetMode =(formatSetMode ==FONT_STYLE) ? DAY_MONTH :(FormatSetMenuEnum)((int)formatSetMode + 1); brechen; } } showSetup(true); aufrechtzuerhalten. Sonst { showDate (Tag (), Monat (), Jahr (); Verzögerung (5000); }}//---------------------------------------------------------- ------------------//Handle DOWN bttonvoid downButtonPressed() { if (cancelAlarm()) return; switch (clockMode) { case TIME_SET:if (inSubMenu) { switch(timeSetMode) { case TIME_HOUR:newTime.Hour =(newTime.Hour + 24 - 1) % 24; brechen; Fall TIME_MIN:newTime.Minute =(newTime.Minute + 60 - 1) % 60; brechen; Fall TIME_FORMAT:EepromData.format12hr =!EepromData.format12hr; brechen; } showSetup (wahr); } brechen; case DATE_SET:if (inSubMenu) { switch(dateSetMode) { case DATE_YEAR:newTime.Year =((newTime.Year - 30 + 100) - 1) % 100 + 30; brechen; case DATE_MONTH:newTime.Month =((newTime.Month - 1 + 12) - 1) % 12 + 1; brechen; case DATE_DAY:uint8_t md =daysInMonth(newTime.Year, newTime.Month); newTime.Day =((newTime.Day - 1 + md) - 1) % md + 1; brechen; } showSetup (wahr); } brechen; case ALARM_SET:if (inSubMenu) { switch(alarmSetMode) { case ALARM_HOUR:EepromData.hours =(EepromData.hours + 24 - 1) % 24; brechen; Fall ALARM_MIN:EepromData.minutes =(EepromData.minutes + 60 - 1) % 60; brechen; case ALARM_STATE:EepromData.alarm =!EepromData.alarm; brechen; } showSetup (wahr); } brechen; Fall TUNE_SET:EepromData.tune =(EepromData.tune + NUM_OF_MELODIES - 1) % NUM_OF_MELODIES; showSetup(true); brechen; Fall BRIGHT_SET:EepromData.brightness =(EepromData.brightness + MAX_INTENSITY - 1) % MAX_INTENSITY; mx.control(MD_MAX72XX::INTENSITY, EepromData.brightness); //0..MAX_INTENSITY showSetup(true); brechen; case FORMAT_SET:if (inSubMenu) { switch (formatSetMode) { case DAY_MONTH:EepromData.formatDmy =!EepromData.formatDmy; brechen; case FONT_STYLE:EepromData.squareFont =!EepromData.squareFont; brechen; } } showSetup(true); brechen; }}//---------------------------------------------------------- ------------------//Handle UP bttonvoid upButtonPressed() { if (cancelAlarm()) return; switch (clockMode) { case TIME_SET:if (inSubMenu) { switch(timeSetMode) { case TIME_HOUR:newTime.Hour =(newTime.Hour + 1) % 24; brechen; Fall TIME_MIN:newTime.Minute =(newTime.Minute + 1) % 60; brechen; Fall TIME_FORMAT:EepromData.format12hr =!EepromData.format12hr; brechen; } showSetup (wahr); } brechen; case DATE_SET:if (inSubMenu) { switch(dateSetMode) { case DATE_YEAR:newTime.Year =((newTime.Year - 30) + 1) % 100 + 30; brechen; case DATE_MONTH:newTime.Month =((newTime.Month - 1) + 1) % 12 + 1; brechen; case DATE_DAY:uint8_t md =daysInMonth(newTime.Year, newTime.Month); newTime.Day =(newTime.Day % md) + 1; brechen; } showSetup (wahr); } brechen; case ALARM_SET:if (inSubMenu) { switch(alarmSetMode) { case ALARM_HOUR:EepromData.hours =(EepromData.hours + 1) % 24; brechen; Fall ALARM_MIN:EepromData.minutes =(EepromData.minutes + 1) % 60; brechen; case ALARM_STATE:EepromData.alarm =!EepromData.alarm; brechen; } showSetup (wahr); } brechen; Fall TUNE_SET:EepromData.tune =(EepromData.tune + 1) % NUM_OF_MELODIES; showSetup(true); brechen; Fall BRIGHT_SET:EepromData.brightness =(EepromData.brightness + 1) % MAX_INTENSITY; mx.control(MD_MAX72XX::INTENSITY, EepromData.brightness); //0..MAX_INTENSITY showSetup(true); brechen; case FORMAT_SET:if (inSubMenu) { switch (formatSetMode) { case DAY_MONTH:EepromData.formatDmy =!EepromData.formatDmy; brechen; case FONT_STYLE:EepromData.squareFont =!EepromData.squareFont; brechen; } } showSetup(true); brechen; }}//---------------------------------------------------------- ------------------ // Schalten Sie den Alarm aus, wenn ein Tunebool abgespielt wird CancelAlarm () { if (musicPlaying) { musicPlaying =false; alarmCancelled =alarmRinging; true zurückgeben; } Ertrag(); falsch zurückgeben;}//-------------------------------------------- -------------------//Zeige das Setup-Menü und flashe das ausgewählte Elementvoid showSetup(bool force){ setupDisplayState =setupDisplayState | Gewalt; Kraft =Kraft || (millis()> setupTimeout); if (force) { setupTimeout =millis() + SETUP_FLASH_RATE; bool on =setupDisplayState; setupDisplayState =!setupDisplayState; mx.clear(); if (on || !(clockMode ==TIME_SET &&!inSubMenu)) displayString(0,7,"TINE"); if (on || !(clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_HOUR)) displayNumber(0,13,newTime.Hour,2,true); if (on || !(clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_MIN)) displayNumber(0,16,newTime.Minute,2,true); if (on || !(clockMode ==TIME_SET &&inSubMenu &&timeSetMode ==TIME_FORMAT)) displayString(0,19,(EepromData.format12hr) ? "12HR" :"24HR"); if (on || !(clockMode ==DATE_SET &&!inSubMenu)) displayString(1,7,"DATE"); if (on || !(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_YEAR)) displayNumber(1,13,tmYearToCalendar(newTime.Year),4,true); if (on || !(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_MONTH)) displayNumber(1,18,newTime.Month,2,true); if (on || !(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_DAY)) displayNumber(1,21,newTime.Day,2,true); if (on || !(clockMode ==ALARM_SET &&!inSubMenu)) displayString(2,6,"ALARN"); if (on || !(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_HOUR)) displayNumber(2,13,EepromData.hours,2,true); if (on || !(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_MIN)) displayNumber(2,16,EepromData.minutes,2,true); if (on || !(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_STATE)) displayString(2,19,(EepromData.alarm) ? "ON" :"OFF"); if (on || !(clockMode ==TUNE_SET &&!inSubMenu)) displayString(3,7,"TUNE"); if (on || !(clockMode ==TUNE_SET &&inSubMenu)) { switch(EepromData.tune) { case 0:displayString(3,13,"ELISE"); brechen; Fall 1:displayString(3,13,"BEREICH"); brechen; Fall 2:displayString(3,13,"SONNENSCHEIN"); brechen; } } if (on || !(clockMode ==BRIGHT_SET &&!inSubMenu)) displayString(4,1,"BRIGHTNESS"); if (on || !(clockMode ==BRIGHT_SET &&inSubMenu)) displayNumber(4,13,EepromData.brightness,0,false); if (on || !(clockMode ==FORMAT_SET &&!inSubMenu)) displayString(5,0,"DATE ​​FORNAT"); if (on || !(clockMode ==FORMAT_SET &&inSubMenu &&formatSetMode ==DAY_MONTH)) displayString(5,13,(EepromData.formatDmy) ? "DD-NN" :"NN-DD"); if (on || !(clockMode ==FORMAT_SET &&inSubMenu &&formatSetMode ==FONT_STYLE)) displayString(5,19,(EepromData.squareFont) ? "FONT1" :"FONT2"); mx.update(); }}//---------------------------------------------------------- ------------------ // Zeigt die aktuelle Uhrzeit auf dem Display an, wenn sie geändert wurde // force - immer die Uhrzeit anzeigen, auch wenn sie nicht geändert wurdevoid showTime(bool force){ force =force || (lastSeconds !=zweite()); if (force) { lastSeconds =second(); showTime(hour(), minute(), true, true, (second() &0x01), (clockMode !=CLOCK || !EepromData.format12hr)); }}//---------------------------------------------------------- ------------------//Anzeige der Uhrzeit auf dem Display // h - Stunde// m - Minute // he - Stunde aktivieren // me - Minute aktivieren // ce - Doppelpunkt enable void showTime(int h, int m, bool he, bool me, bool ce, bool f24) { mx.clear(); if (er) { if (!f24 &&h> 12) { h =h - 12; } if (h> 9 || f24) { displayLargeDigit (0, h / 10); } displayLargeDigit(5, h % 10); } if (me) { displayLargeDigit (13, m / 10); displayLargeDigit(18, m % 10); aufrechtzuerhalten. Wenn (ce) { DisplayLargeDigit (11, 10); } mx.update();}//---------------------------------------------------- -----------------------void showDate(int d, int m, int y){ #define XOFS 3 mx.clear(); if (EepromData.formatDmy) { displayDateDigit (XOFS + 0, d / 10); displayDateDigit(XOFS+4, d % 10); displayDateDigit(XOFS+8, 10); // Doppelpunkt displayDateDigit (XOFS + 12, m / 10); displayDateDigit(XOFS+16, m % 10); aufrechtzuerhalten. Sonst { displayDateDigit (XOFS + 0, m / 10); displayDateDigit(XOFS+4, m % 10); displayDateDigit(XOFS+8, 10); // Doppelpunkt displayDateDigit (XOFS + 12, d / 10); displayDateDigit(XOFS+16, d % 10); } displayNumber(5, 10, y, 0, false); mx.update();} //----------------------------------------- ----------------------// Schreiben Sie eine quadratische oder kleine Ziffer basierend auf der Konfigurationseinstellung // x =0 bis 23// v =große oder quadratische Ziffer bis display (0..10)void displayDateDigit(uint8_t x, uint8_t v) { if (EepromData.squareFont) { displaySquareDigit(x, v); aufrechtzuerhalten. Sonst { displaySmallDigit (x, v); }}//---------------------------------------------------------- ------------------// Schreiben Sie eine Segmentbitmaske// x =0 bis 23// v =große Ziffer zur Anzeige (0..10)void displayLargeDigit(uint8_t x , uint8_t v) { if (x <24 &&v <11) { for (uint8_t row =0; row <6; row++) { for (uint8_t col =0; col <6; col++) { writePhysicalDigit(row, col + x, pgm_read_byte(&largeDigits[v][row][col]), false); } } }} //-------------------------------------------- -------------------// Schreiben einer Segmentbitmaske // x =0 bis 23// v =große Ziffer zur Anzeige (0..10)void displaySmallDigit( uint8_t x, uint8_t v){ if (x <24 &&v <11) { for (uint8_t row =0; row <5; row++) { for (uint8_t col =0; col <3; col++) { writePhysicalDigit(row, col + x, pgm_read_byte(&smallDigits[v][row][col]), false); } } }} //-------------------------------------------- -------------------// Schreiben Sie eine Segmentbitmaske // x =0 bis 23// v =große Ziffer zur Anzeige (0..10)void displaySquareDigit( uint8_t col, uint8_t v){//Segmentreihenfolge defbca _ g uint8_t mask =ascii[v]; if (Maske ==B00000000) {//Bindestrichmaske =B00000001; } if (Maske &B000000100) {//seg A writePhysicalDigit (0, Spalte + 0, 0xff, false); writePhysicalDigit(0, Spalte + 1, 0xff, falsch); writePhysicalDigit(0, Spalte + 2, 0xff, falsch); aufrechtzuerhalten. Wenn (Maske &B00010000) {//Seg B writePhysicalDigit (0, Spalte + 2, 0xff, false); writePhysicalDigit(1, Spalte + 2, 0xff, falsch); writePhysicalDigit(2, Spalte + 2, 0xff, falsch); aufrechtzuerhalten. Wenn (Maske &B00001000) {//seg C writePhysicalDigit(2, Spalte + 2, 0xff, false); writePhysicalDigit(3, Spalte + 2, 0xff, falsch); writePhysicalDigit(4, Spalte + 2, 0xff, falsch); aufrechtzuerhalten. Wenn (Maske &B10000000) {//seg D writePhysicalDigit (4, Spalte + 0, 0xff, false); writePhysicalDigit(4, Spalte + 1, 0xff, falsch); writePhysicalDigit(4, Spalte + 2, 0xff, falsch); } if (mask &B01000000) {//seg C writePhysicalDigit(2, col, 0xff, false); writePhysicalDigit(3, Spalte, 0xff, falsch); writePhysicalDigit(4, Spalte, 0xff, false); aufrechtzuerhalten. Wenn (Maske &B00100000) {//seg E writePhysicalDigit (0, Spalte, 0xff, false); writePhysicalDigit(1, Spalte, 0xff, false); writePhysicalDigit(2, Spalte, 0xff, false); aufrechtzuerhalten. Wenn (Maske &B00000001) {//seg D writePhysicalDigit(2, Spalte + 0, 0xff, false); writePhysicalDigit(2, Spalte + 1, 0xff, falsch); writePhysicalDigit(2, Spalte + 2, 0xff, falsch); }}//---------------------------------------------------------- ------------------// Zeichenkette schreibenuint8_t displayString(uint8_t row, uint8_t col, String s){ for (int i =0; i  0x5F) {c =0x3F; // Wird als Leerzeichen verwendet} c =c - 0x30; writePhysicalDigit(row, col, ascii[c], true); Spalte =Spalte + 1; }}//---------------------------------------------------------- ------------------// Schreiben Sie eine Zahluint8_t displayNumber(uint8_t row, uint8_t col, int number, int padding, bool führendenZeros){ if (padding ==0) { padding =(Zahl> 0) ? floor(log10(Zahl)) + 1 :1; } Spalte =Spalte + Auffüllung; bool zuerst =wahr; for (int i =0; i > 2) * 3 + (Zeile>> 1); uint16_t c =((uint16_t)dev <<3) | digitMap[dig]; if (!löschen) { v =v | mx.getColumn(c); } mx.setColumn(c, v); }}//---------------------------------------------------------- ------------------ // Gib die Tage in einem bestimmten Jahr und Monat zurück // Februar hat 28, es sei denn, Schaltjahr oder die Jahrhundertwendeuint8_t daysInMonth(int y, int m) { return dom[m - 1] + ((m ==2 &&(y % 4) ==0 &&(y % 100) !=0) ? 1 :0);}//------- -------------------------------------------------- ------//Schreibe die EepromData-Struktur in EEPROMvoid writeEepromData(){ //Diese Funktion verwendet EEPROM.update(), um das Schreiben durchzuführen, schreibt also den Wert nicht neu, wenn er sich nicht geändert hat. EEPROM.put(EEPROM_ADDRESS,EepromData);}//---------------------------------------- -------------------------- // EepromData-Struktur aus EEPROM lesen, ggf. initialisierenvoid readEepromData(){ //Eprom EEPROM.get(EEPROM_ADDRESS, Eeprom-Daten); //Serial.println("magic:" + String(EepromData.magic, 16) +", Alarm:" + String(EepromData.alarm) +", Zeit:" + String(EepromData.hours) + ":" + String(EepromData.minutes) +", 12hr:" + String(EepromData.format12hr) +", Helligkeit:" + String(EepromData.brightness)); if (EepromData.magic!=EEPROM_MAGIC) {Serial.println("Initialisierung des EEPROM ..."); EepromData.magic =EEPROM_MAGIC; EepromData.alarm =false; EepromData.Minuten =30; EepromData.hours =5; EepromData.format12hr =false; EepromData.brightness =8; EepromData.tune =0; EepromData.formatDmy =false; writeEepromData(); } Serial.println("alarm:" + String(EepromData.alarm) +", Zeit:" + String(EepromData.hours) + ":" + String(EepromData.minutes) +", 12hr:" + String(EepromData .format12hr) + ", Helligkeit:" + String(EepromData.brightness));}//---------------------------------------- ---------------------------------- // Spiel eine Melodieint playSong(const uint16_t* Melodie){//Play jede Note in der Melodie, bis die Note END_OF_TUNE angetroffen wird musicPlaying =true; int thisNote =0; uint16_t noteRaw =pgm_read_word(&melody[thisNote++]); while (musicPlaying &¬eRaw !=END_OF_TUNE) { testButtons(); Ertrag(); playNote(noteRaw); noteRaw =pgm_read_word(&melody[thisNote++]); } //während Verzögerung (50);} //-------------------------------------- -------------------------- // Spielen Sie eine einzelne Notevoid playNote(uint16_t noteRaw){ // Um ​​die Notendauer zu berechnen, nehmen Sie eine Sekunde geteilt durch der Notiztyp. // z.B. Viertelnote =1000/4, Achtelnote =1000/8 usw. uint16_t Frequenz =noteRaw &0x1FFF; uint16_t Dauer =(noteRaw &0xE000)>> 13; if (Dauer ==7) Dauer =8; uint16_t noteDuration =1800 / Dauer; if (Frequenz!=REST) ​​{ Ton (LAUTSPRECHER, Frequenz, NoteDuration); } // Um ​​die Noten zu unterscheiden, legen Sie einen Mindestabstand zwischen ihnen fest. // die Dauer der Notiz + 30% scheint gut zu funktionieren:uint16_t pauseBetweenNotes =(noteDuration * 13) / 10; Verzögerung (pauseBetweenNotes); if (Frequenz!=REST) ​​{// stoppen Sie die Tonwiedergabe:noTone (SPEAKER); }}
Digits.hC/C++
/*---------------------------------------------------------- ------ * 7 Segment array clock * define each digit in a 6x6 byte array *----------------------------- ---------------------*/ #pragma once//---------------------- -----------------------------// Standard MAX7219 wiring// Digit order 0,1,2,3,4,5/ *// Segment order _ abcdefg#define _______ B00000000#define __cd___ B00011000#define _bcde_g B00111101#define abcdefg B01111111#define __cdefg B00011111#define __c____ B00010000#define ab__efg B01100111#define abcd_fg B01111011#define abcde_g B01111101#define ab_defg B01101111#define _bc____ B00110000#define a__defg B01001111#define ____ef_ B00000110#define ___defg B00001111#define abc__fg B01110011#define a___ef_ B01000110#define _b_____ B00100000#define ab___f_ B01100010#define _bcd___ B00111000#define a___ef_ B01000110#define ab_____ B01100000#define ____e__ B00000100#define __cde_g B00011101# define a____f_ B01000010#define a_cdefg B01011111#define ___de__ B00001100#define _____f_ B00000 010#define ab___fg B01100011#define a__def_ B01001110#define __cde__ B00011100#define a___efg B01000111#define a__d___ B01001000#define abc____ B01110000#define _bc_ef_ B00110110#define ___def_ B00001110#define abc_ef_ B01110110#define _bcdef_ B00111110#define a__def_ B01001110#define abcd___ B01111000*///Segment order d e f b c a _ g#define _______ B00000000#define __cd___ B10001000#define _bcde_g B11011001#define abcdefg B11111101#define __cdefg B11101001#define __c____ B00001000#define ab__efg B01110101#define abcd_fg B10111101#define abcde_g B11011101#define ab_defg B11110101#define _bc____ B00011000#define a__defg B11100101#define ____ef_ B01100000#define ___defg B11100001#define abc__fg B00111101#define a___ef_ B01100100#define _b_____ B00010000#define ab___f_ B00110100#define _bcd___ B10011000#define a___ef_ B01100100#define ab_____ B00010100#define ____e__ B01000000#define __cde_g B11001001#define a____f_ B00100100#define a_cdefg B11101101#define ___de__ B11000000#define _____f _ B00100000#define ab___fg B00110101#define a__def_ B11100100#define __cde__ B11001000#define a___efg B01100101#define a__d___ B10000100#define abc____ B00011100#define _bc_ef_ B01111000#define ___def_ B11100000#define abc_ef_ B01111100#define _bcdef_ B11111000#define a__def_ B11100100#define abcd___ B10011100//Square Numbers//ASCII Character Set//Numbers 0 - 9//Letters A - Z//Segment order d e f b c a _ guint8_t ascii[] ={ B11111100, B00011000, B11010101, B10011101, B00111001, B10101101, B11101101, B00011100, B11111101, B10111101, B00000000, B00000000, B00000000, B00000001, B00000000, B00000000, B00000000, B01111101, B11101001, B11100100, B11011001, B11100101, B01100101, B10111101, B01111001, B00011000, B11011000, B00000000, B11100000, B00000000, B01001001, B11001001, B01110101, B00000000, B01000001, B10101101, B11100001, B11001000, B00000000, B00000000, B00000000, B10111001, B00000000, B11001100, B01010001, B10011100, B00000000, B10000000};//Digit sequence for each device (MAX7219)u int8_t digitMap[] ={5, 2, 6, 4, 1, 7, 3, 0};//------------------------------------------------------------// Digits using logical coordinates//------------------------------------------------------------const int8_t largeDigits[11][6][6] PROGMEM ={ { //0 { _______, _______, __cd___, _bcde_g, abcdefg, __cdefg }, { _______, __c____, abcdefg, ab__efg, abcd_fg, abcdefg }, { _______, abcde_g, ab_defg, _______, _bc____, a__defg }, { _______, abcdefg, ____ef_, __c____, abcdefg, ____ef_ }, { _______, abcdefg, __cdefg, abcdefg, a___efg, _______ }, { _______, abc__fg, abcdefg, ab__efg, _______, _______ } }, { //1 { _______, _______, _______, __c____, abcdefg, __cdefg }, { _______, _______, _______, abcdefg, abcdefg, ____ef_ }, { _______, _______, _bcde_g, abcdefg, a__defg, _______ }, { _______, _bc____, abcdefg, abcdefg, ____ef_, _______ }, { _______, abcdefg, abcdefg, a___ef_, _______, _______ }, { _b_____, abcdefg, abcdefg, _______, _______, _______ } }, { //2 { _______, _______, __cd___, _b cde_g, abcdefg, __cdefg }, { _______, _bc____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _______, _______, _bcd___, abcdefg, a___ef_ }, { _______, _______, _bcde_g, abcdefg, a___ef_, _______ }, { __c____, abcdefg, abcdefg, a___ef_, _______, _______ }, { _b_____, abc__fg, abcdefg, abcdefg, ab__efg, _______ } }, { //3 { _______, _______, __cd___, abcdefg, abcdefg, __cdefg }, { _______, _b_____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _______, __cd___, _bcde_g, abcdefg, a___ef_ }, { _______, _______, ab_____, abc__fg, abcdefg, ____e__ }, { _______, __cd___, __cde_g, _bcde_g, abcdefg, ____ef_ }, { _b_____, abc__fg, abcdefg, abcdefg, a____f_, _______ } }, { //4 { _______, _______, _bcd___, abcdefg, __c____, abcdefg }, { _______, __c____, abcdefg, a___ef_, abcde_g, a__defg }, { _______, abcde_g, abcdefg, _bcd___, abcdefg, ____ef_ }, { __c____, abcdefg, abcdefg, abcdefg, abcdefg, _______ }, { _______, _______, __c____, abcdefg, ____ef_, _______ }, { _______, _______, abcdefg, ab__efg, _______, _______ } }, { //5 { _______, _______, _bcde_g, abcdefg, abcdefg, abcdefg }, { _______, _bc____, abcdefg, a_cdefg, ___de__, _______ }, { _______, _______, abc__fg, abcdefg, abcdefg, ____ef_ }, { _______, _______, _______, _bc____, abcdefg, ____ef_ }, { _______, __cde_g, __cde_g, _bcde_g, abcdefg, _____f_ }, { _b_____, abcdefg, abcdefg, ab__efg, a____f_, _______ } }, { //6 { _______, _______, _______, __cd___, abcdefg, ____ef_ }, { _______, _______, _bcde_g, abcdefg, a____f_, _______ }, { _______, _bcd___, abcdefg, abcdefg, abcdefg, ____e__ }, { __c____, abcdefg, a___ef_, ab_____, abcdefg, ____ef_ }, { _bc____, abcdefg, __cdefg, _bcde_g, abcdefg, _______ }, { _______, abc__fg, abcdefg, ab__efg, _______, _______ } }, { //7 { _______, _bc____, abcdefg, abcdefg, abcdefg, __cdefg }, { _______, _b_____, ab___fg, ab___fg, abcdefg, abcdefg }, { _______, _______, _______, _bcde_g, abcdefg, a___ef_ }, { _______, _______, _bcde_g, abcdefg, ab__efg, _______ }, { _______, _bcde_g, abcdefg, a___ef_, _______, _______ }, { _b_____, abcdefg, abcdefg, _______, _______, _______ } }, { //8 { _______, _______, __cd___, abcdefg, abcdefg, __cdefg }, { _______, _bc____, abcdefg, ab___f_, abcd_fg, abcdefg }, { _______, _b_____, abcdefg, _bcde_g, abcdefg, a___ef_ }, { _______, _bcde_g, ab__efg, abc__fg, abcdefg, ____e__ }, { _bc____, abcdefg, __cde_g, _bcde_g, abcdefg, ____ef_ }, { _______, abc__fg, abcdefg, abcdefg, a____f_, _______ } }, { //9 { _______, _______, __cde_g, abcdefg, __cdefg, ___de__ }, { _______, _bcd___, abcdefg, ab___fg, abcd_fg, abcdefg }, { _______, abcdefg, a_cdefg, __cde__, abcdefg, a__defg }, { _______, ab_____, abcd_fg, abcdefg, abcdefg, _____f_ }, { _______, __cd___, abcdefg, ab__efg, _______, _______ }, { _b_____, abcdefg, a___ef_, _______, _______, _______ } }, { //Colon { _______, _______, _______, _______, _______, _______ }, { _______, __cde_g, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ }, { ___ ____, _______, _______, _______, _______, _______ }, { __cde_g, _______, _______, _______, _______, _______ }, { _______, _______, _______, _______, _______, _______ } }};const int8_t smallDigits[11][5][3] PROGMEM ={ { //0 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //1 { _______, abc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bcdef_, _______ } }, { //2 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { a___ef_, a__d___, _bcd___ }, { _bc_ef_, _______, _______ }, { ___def_, a__d___, abcd___ } }, { //3 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { _______, a__def_, _bc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //4 { abc_ef_, _______, abc_ef_ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bc____ }, { _______, _______, _bc_ef_ }, { _______, _______, _bcdef_ } }, { //5 { a___ef_, a__d___, abcd___ }, { _bc_ef_, _______, _______ }, { ___def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //6 { a___ef_, a__d___, abcd___ }, { _bc_ef_, _______, _______ }, { ____ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //7 { a__def_, a__d___, abc____ }, { _______, _______, _bc_ef_ }, { _______, _bc_ef_, _______ }, { _______, _bc_ef_, _______ }, { _______, _bcdef_, _______ }, }, { //8 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ____ef_, a__d___, _bc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bcd___ } }, { //9 { a___ef_, a__d___, abc____ }, { _bc_ef_, _______, _bc_ef_ }, { ___def_, a__d___, _bc____ }, { _______, _______, _bc_ef_ }, { a__def_, a__d___, _bcd___ } }, { //Hyphen { _______, _______, _______ }, { _______, _______, _______ }, { a__def_, a__d___, abcd___ }, { _______, _______, _______ }, { _______, _____ __, _______ } }};
Tunes.hC/C++
Keine Vorschau (nur Download).
Button.hC/C++
/*Class:ButtonAuthor:John Bradnam ([email protected])Purpose:Arduino library to handle buttons*/#pragma once#include "Arduino.h"#define DEBOUNCE_DELAY 10//Repeat speed#define REPEAT_START_SPEED 500#define REPEAT_INCREASE_SPEED 50#define REPEAT_MAX_SPEED 50class Button{ public://Simple constructor Button(int pin); Button(int name, int pin); Button(int name, int pin, int analogLow, int analogHigh, bool activeLow =true); //Background function called when in a wait or repeat loop void Background(void (*pBackgroundFunction)()); //Repeat function called when button is pressed void Repeat(void (*pRepeatFunction)()); //Test if button is pressed bool IsDown(void); //Test whether button is pressed and released //Will call repeat function if one is provided bool Pressed(); //Return button state (HIGH or LOW) - LOW =Pressed int State(); //Return button name int Name(); private:int _name; int _pin; bool _range; int _low; int _high; bool _activeLow; void (*_repeatCallback)(void); void (*_backgroundCallback)(void);};
Button.cppC/C++
/*Class:ButtonAuthor:John Bradnam ([email protected])Purpose:Arduino library to handle buttons*/#include "Button.h"Button::Button(int pin){ _name =pin; _pin =pin; _range =false; _low =0; _high =0; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT_PULLUP);}Button::Button(int name, int pin){ _name =name; _pin =pin; _range =false; _low =0; _high =0; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT_PULLUP);}Button::Button(int name, int pin, int analogLow, int analogHigh, bool activeLow){ _name =name; _pin =pin; _range =true; _low =analogLow; _high =analogHigh; _activeLow =activeLow; _backgroundCallback =NULL; _repeatCallback =NULL; pinMode(_pin, INPUT);}//Set function to invoke in a delay or repeat loopvoid Button::Background(void (*pBackgroundFunction)()){ _backgroundCallback =pBackgroundFunction;}//Set function to invoke if repeat system requiredvoid Button::Repeat(void (*pRepeatFunction)()){ _repeatCallback =pRepeatFunction;} bool Button::IsDown(){ if (_range) { int value =analogRead(_pin); return (value>=_low &&value <_high); } else { return (digitalRead(_pin) ==LOW); }}//Tests if a button is pressed and released// returns true if the button was pressed and released// if repeat callback supplied, the callback is called while the key is pressedbool Button::Pressed(){ bool pressed =false; if (IsDown()) { unsigned long wait =millis() + DEBOUNCE_DELAY; while (millis() =time) { _repeatCallback(); unsigned long faster =speed - REPEAT_INCREASE_SPEED; if (faster>=REPEAT_MAX_SPEED) { speed =faster; } time =millis() + speed; } } pressed =true; } } return pressed;}//Return current button stateint Button::State(){ if (_range) { int value =analogRead(_pin); if (_activeLow) { return (value>=_low &&value <_high) ? LOW :HIGH; } else { return (value>=_low &&value <_high) ? HIGH :LOW; } } else { return digitalRead(_pin); }}//Return current button nameint Button::Name(){ return _name;}
Hardware_Test_V1.zipC/C++
Hardware test sketch - Turns on all segments and tests speaker
No preview (download only).

Kundenspezifische Teile und Gehäuse

Schaltpläne

Schematic for each MAX7219 (repeated 18 times) Holds six 7 segment 4 digit displays (6 boards required) PCB files in Eagle format eagle_files_KPhUOj6Ezv.zip

Herstellungsprozess

  1. Arduino-Pov-Vision-Uhr
  2. Einfache Wordclock (Arduino)
  3. Arduino-Uhr mit islamischen Gebetszeiten
  4. Hauptuhr
  5. Einzelne LED-Matrix-Arduino Flip Clock
  6. Steuerung einer LED-Matrix mit Arduino Uno
  7. eDOT - Arduino-basierte Präzisionsuhr und Wetterstation
  8. Mini-Radar mit Arduino
  9. Arduino OLED-Temperaturanzeige mit Echtzeituhr
  10. Einfacher Wecker mit DS1302 RTC