Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

7-segment arrayklok

Componenten en benodigdheden

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
Real Time Clock (RTC)
Koop een "DS1302 Real Time Clock Module for Arduino" en soldeer de ic-socket en het kristal los.
× 1
CR1220 batterij en houder
Zoeken naar "5 stuks, zwarte behuizing CR1220 CR1225 houder voor knoopcelbatterij BS-1220-1"
× 1
Condensator 0.1uf 1206 SMD
× 1
Condensator 10uF 1206 SMD Keramiek
× 1
Tactiele schakelaar, bovenkant bediend
12 mm variant met knopen
× 4
3A mini DC-DC step-down convertermodule
× 1
0,28 inch gemeenschappelijke kathode 4-cijferig 7-segments display
× 36
MAX7219 DIP-IC
× 18
Zoemer
× 1
Machinekop
Je hebt zowel mannelijke als vrouwelijke headers nodig - komen meestal in stroken van 40, dus je krijgt 8 stroken mannelijke machinaal bewerkte pinnen en 8 stroken vrouwelijke machinaal bewerkte sockets
× 1
DC-stopcontact
Zoeken naar "12V DC Voeding Jack Socket Vrouwelijk Paneelmontage Connector 5,5 x 2.ODZ2"
× 1

Benodigde gereedschappen en machines

Soldeerbout (algemeen)
3D-printer (algemeen)

Apps en online services

Arduino IDE

Over dit project

Tijdens het browsen op Hackaday.io kwam ik een prachtige klok tegen die gemaakt is met een reeks 7-segments displays door Frugha. Ik wilde dit heel graag bouwen, maar de versie van Frugha is vrij groot omdat hij 0,56" 7-segments displays gebruikt. Mijn ontwerp gebruikt 0,28" 7-segments displays, waardoor het maar een kwart van de grootte is.

De software is herschreven met een wekker en een configuratiescherm om de tijd, datum en alarm in te stellen.

Video

Configuratiescherm

De klok wordt bediend door vier knoppen. De SELECT-knop (bovenaan) toont het configuratiescherm. De huidige selectie knippert. Door nogmaals op de SELECT-knop te drukken, bladert u door de verschillende configuratiesecties (dat wil zeggen Tijd, Datum, Alarm, Afstemmen, Helderheid, Datumformaat en Klok).

Door op de ENTER-knop (2e van bovenaf) te drukken terwijl een van de menu-items is geselecteerd, kunt u de instellingen wijzigen. Als er meer dan één instelling is voor een menu-item, zal de ENTER-knop ertussen schakelen. De actieve instelling knippert.

Wanneer een instelling knippert, zullen de OMHOOG- en OMLAAG-knoppen (onderste twee knoppen) de instelling wijzigen.

Datumscherm

Als u op de ENTER-knop drukt (2e van boven naar beneden) terwijl de klok wordt weergegeven, wordt het datumscherm vijf seconden lang weergegeven.

In het gedeelte Datumformaat op het configuratiescherm kunt u het datumformaat (DD-MM of MM-DD) en het gebruikte lettertype instellen.

Ontwerpoverwegingen

Om het bordontwerp eenvoudig te houden, gebruikt mijn versie 4-cijferige displays in plaats van de eencijferige displays die in de originele versie werden gebruikt. Omdat 0,28"-schermen klein zijn, moest ik de MAX7219-chips op een apart bord plaatsen. Om de bedrading eenvoudig te maken, worden machinaal bewerkte mannelijke en vrouwelijke pin-headers gebruikt om de borden aan te sluiten,

De Eagle-bestanden zijn bijgevoegd als u de borden commercieel wilt laten maken of wilt doen zoals ik deed en ze zelf zou maken. Ik heb de Toner-methode gebruikt om de mijne te maken.

De kolomborden

Er moeten zes kolomborden worden gemaakt waarop alle displays kunnen worden geplaatst. Begin bij het solderen van de mannelijke machinekoppen met de middelste set en werk naar de buitenrand toe. Gebruik een lucifer of iets dergelijks om de socket voldoende op te tillen, zodat u de pinnen gemakkelijk kunt solderen. Gebruik een kleine soldeerbout met een fijne punt en 0,5 mm soldeer.

Nadat u de kolommodules hebt gemaakt, raad ik u aan de weergaverand te schilderen met matzwarte verf. Hierdoor worden de witte randen niet meer zichtbaar als een scherm niet perfect is uitgelijnd met zijn buur. Gebruik ook een markeerstift om elke kolommodule te nummeren. Dit helpt wanneer ze in het MAX7219-moederbord worden geplaatst.

Het MAX7219-moederbord

Bij het ontwerpen van het moederbord en de kolomborden heb ik niet de juiste MAX7219-segmenten of cijfers toegewezen aan hun overeenkomstige display-pinnen. Ik wilde de lay-out van de print zo eenvoudig mogelijk houden en aanpassen voor eventuele verschillen in software.

Ik raad aan als het gaat om de vrouwelijke machinaal bewerkte sockets dat je ze eerst op de mannelijke pinnen van de kolomborden plaatst en vervolgens het geheel op zijn plaats soldeert terwijl ze zijn aangesloten. Dit betekent dat de kolompinnen precies uitgelijnd zijn met hun corresponderende sockets. Als u ze moet verwijderen, zorgt het nummeren van de kolommodules ervoor dat ze teruggaan naar dezelfde positie.

Het MPU-bord

De microprocessorkaart bevat alle andere componenten. De vier knoppen en twee SMD-condensatoren zijn aan de achterkant van het bord gemonteerd en alle andere componenten zijn aan de voorkant van het bord gemonteerd. Om een ​​laag profiel te houden, wordt de FTDI-pinheader die gewoonlijk op de Arduino Pro Mini wordt gesoldeerd, nu rechtstreeks op de PCB gesoldeerd. Twee draden gaan van de DTR- en VCC-pinnen rechtstreeks naar de PCB.

De zaak maken

De STL-bestanden voor de voor- en achterkant zijn bijgevoegd. Beide zijn bedrukt met een hoogte van 0,2 laag en een rand. Op de voorkant zijn ook steunen ingeschakeld die alleen de bouwplaat raken.

Het MAX7219-moederbord met zijn kolommodules schuift vanaf de voorkant naar binnen. Als je het een beetje los vindt, gebruik dan een laag of twee plakband als verpakking.

Het MPU-bord is aan de achterkant vastgelijmd.

Software

De software vereist dat de MD_MAX72XX-bibliotheek in uw Arduino IDE is geïnstalleerd. Ik heb mijn Hardware_Test_V1-schets verstrekt om te testen. Het zal elk segment oplichten, zodat u kunt controleren op kortsluiting of gebroken bedrading. Zodra het scherm werkt, uploadt u een Clock_V4-schets.

Code

  • Clock_V4.ino
  • Cijfers.h
  • Tunes.h
  • Knop.h
  • Knop.cpp
  • Hardware_Test_V1.zip
Clock_V4.inoC/C++
/*--------------------------------------------- ------ * 7 Segment array-klok * * Gebaseerd op klok van Frugha (https://hackaday.io/project/169632-7-segment-display-array-clock) * * Wijzigingen door John Bradnam (jbrad2089@ gmail.com) * - Gewijzigde hardware om 0,28" 7 segment displays te gebruiken. * - MAX7219 apparaat, cijfers en segmenten volgorde is veranderd in een anders * complexe printplaat routing. * - Hardware gebruikt Arduino Mini Pro, DS1302 RTC en 4 drukknoppen * - Alarmfunctie toegevoegd met selecteerbare alarmfunctie * - Helderheidsinstelling toegevoegd * - Instelscherm toegevoegd om tijd, datum, alarm, muziek en helderheid in te stellen * - Datumscherm toegevoegd (wordt twee seconden weergegeven wanneer de ENTER-knop wordt ingedrukt * Update 2020 -06-16 * - Datumnotatie-optie toegevoegd op configuratiescherm * - Time-out van datumscherm verhoogd van 2 naar 5 seconden * - Een configureerbare keuze van lettertype toegevoegd voor datumweergave *-------------- ------------------------------------*/ #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 / / of SCK (WHI)#define LED_DATA 11 // of MOSI (BRN)#define LED_CS 10 // of 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);// Willekeurige pinnen/xarbitraire pinnen/x MD_MAX_DW72XX m,/MD_MAX_DW72XX m LED_CLK, LED_CS, MAX_DEVICES);//EEPROM-verwerking#define EEPROM_ADDRESS 0#define EEPROM_MAGIC 0x0BAD0DADtypedef struct {uint32_t magic; bool-alarm; uint8_t minuten; uint8_t uur; bool-formaat12 uur; uint8_t helderheid; uint8_t tune; bool-formaatDmy; bool squareFont;} EEPROM_DATA;EEPROM_DATA EepromData; //Huidige EEPROM-instellingenvoid clockButtonPressed(void);void enterButtonPressed(void);void downButtonPressed(void);void upButtonPressed(void);Button* clockButton;Button* enterButton;Button* downButton;Button* upButton;//Bedrijfsmodibool 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 klokMode =CLOCK; timeSetMode =TIME_HOUR; enum DateSetMenuEnum {DATE_YEAR, DATE_MONTH, DATE_DAY}; DateSetMenuEnum dateSetMode =DATE_YEAR; enum AlarmSetMenuEnum {ALARM_HOUR, ALARM_MIN, ALARM_STATE}; AlarmSetMenuEnum alarmSetMode =ALARM_HOUR; enum FormatSetMenuEnum {DAY_MONTH, FONT_STYLE}; FormatSetMenuEnum formatSetMode =DAY_MONTH; int lastSeconds =-1;bool alarmRinging =false; //true wanneer alarm is ingeschakeld alarmCancelled =false; // alarm geannuleerd door userbool musicPlaying =false; //true als een songbool-klok wordt afgespeeldColon =false; //show/hide colonint8_t dom[] ={31,28,31,30,31,30,31,31,30,31,30,31};tmElements_t newTime; // Gebruikt om nieuwe timevoid setup () {Serial.begin (115200) op te slaan; //Eprom leesEepromData(); // Initialiseer knoppen clockButton =nieuwe knop (SW_SELECT); enterButton =nieuwe knop (SW_ENTER); downButton =nieuwe knop (SW_DOWN); downButton->Herhalen (downButtonPressed); upButton =nieuwe knop (SW_UP); upButton->Herhaal (upButtonPressed); // Initialiseer geluid pinMode (LUIDSPREKER, OUTPUT); mx.begin(); mx.control(MD_MAX72XX::INTENSITEIT, EepromData.brightness); //0..MAX_INTENSITEIT mx.update (MD_MAX72XX::UIT); // Geen automatische updates setSyncProvider (rtc.get); // de functie om de tijd van de RTC te krijgen if(timeStatus() !=timeSet) {Serial.println("RTC Sync Bad"); newTime.Year =CalendarYrToTm(2020); nieuweTijd.Maand =5; nieuweTijd.Dag =30; newTime.Hour =14; nieuweTijd.Minuut =53; newTime.Second =0; time_t t =makeTime(newTime); setTime(t); rtc.set(t); if (rtc.set(t) !=0) { Serial.println("Tijd instellen mislukt"); } } newTime.Year =CalendarYrToTm(year()); newTime.Month =maand(); newTime.Day =dag(); newTime.Hour =uur(); newTime.Minuut =minuut(); newTime.Second =tweede(); Serial.println("Time:" + String(newTime.Hour) + ":" + String(newTime.Minute) + ":" + String(newTime.Second)); Serial.println("Datum:" + String(newTime.Day) + "/" + String(newTime.Month) + "/" + String(tmYearToCalendar(newTime.Year))); clockMode =KLOK; showTime(true);}void loop(){ testButtons(); if (clockMode ==KLOK) { showTime(false); if (EepromData.alarm &&EepromData.hours ==hour() &&EepromData.minutes ==minuut()) { if (!alarmCancelled) { alarmRinging =true; playSong (melodieën [EepromData.tune]); } } else { alarmCancelled =false; alarmRinging =vals; } } else { showSetup(false); } vertraging(100);}//----------------------------------------- ----------------------//Test of er knoppen zijn ingedrukt ongeldig testButtons(){ //Knoppen één keer indrukken als (clockButton->Pressed()) { clockButtonPressed(); } if (enterButton->Pressed()) { enterButtonPressed(); } //Het is niet nodig om het resultaat van het indrukken te controleren, aangezien de knop-handler zijn herhaalfunctie zal aanroepen upButton->Pressed(); downButton->Ingedrukt();}//---------------------------------------- -----------------------//Greep KLOK bttonvoid clockButtonPressed(){ if (cancelAlarm()) return; inSubMenu =onwaar; clockMode =(clockMode ==FORMAT_SET) ? KLOK :(ClockButtonModesEnum)((int)clockMode + 1); if (clockMode ==CLOCK) { Serial.println("Tijd besparen:" + String(newTime.Hour) + ":" + String(newTime.Minute)); Serial.println(" Van:" + String(uur()) + ":" + String(minuut())); if (newTime.Year !=CalendarYrToTm(year()) || newTime.Month !=month() || newTime.Day !=day() || newTime.Hour !=hour() || newTime.Minute !=minuut ()) { // Tijd bijwerken Serial.println ("RTC bijwerken"); newTime.Second =tweede(); time_t t =makeTime(newTime); setTime(t); rtc.set(t); if (rtc.set(t) !=0) { Serial.println("Tijd instellen mislukt"); } } writeEepromData(); showTime (waar); } else { if (clockMode ==TIME_SET) { newTime.Year =CalendarYrToTm(year()); newTime.Month =maand(); newTime.Day =dag(); newTime.Hour =uur(); newTime.Minuut =minuut(); newTime.Second =tweede(); Serial.println("Laadtijd:" + String(uur()) + ":" + String(minuut())); } showSetup(true); }}//---------------------------------------------- -----------------//Handvat ENTER bttonvoid enterButtonPressed(){ if (cancelAlarm()) return; if (clockMode !=CLOCK) { if (!inSubMenu) { timeSetMode =TIME_HOUR; dateSetMode =DATE_YEAR; alarmSetMode =ALARM_HOUR; formatSetMode =DAY_MONTH; inSubMenu =waar; } else { switch (clockMode) { case TIME_SET:timeSetMode =(timeSetMode ==TIME_FORMAT) ? TIME_HOUR :(TimeSetMenuEnum)((int)timeSetMode + 1); pauze; geval DATE_SET:dateSetMode =(dateSetMode ==DATE_DAY) ? DATE_YEAR :(DateSetMenuEnum)((int)dateSetMode + 1); pauze; geval ALARM_SET:alarmSetMode =(alarmSetMode ==ALARM_STATE) ? ALARM_HOUR :(AlarmSetMenuEnum)((int)alarmSetMode + 1); pauze; geval FORMAT_SET:formatSetMode =(formatSetMode ==FONT_STYLE) ? DAY_MONTH :(FormatSetMenuEnum)((int)formatSetMode + 1); pauze; } } showSetup(true); } else { showDate(dag(), maand(), jaar()); vertraging (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; pauze; case TIME_MIN:newTime.Minute =(newTime.Minute + 60 - 1) % 60; pauze; geval TIME_FORMAT:EepromData.format12hr =!EepromData.format12hr; pauze; } showSetup(true); } pauze; case DATE_SET:if (inSubMenu) { switch(dateSetMode) { case DATE_YEAR:newTime.Year =((newTime.Year - 30 + 100) - 1) % 100 + 30; pauze; case DATE_MONTH:newTime.Month =((newTime.Month - 1 + 12) - 1) % 12 + 1; pauze; case DATE_DAY:uint8_t md =daysInMonth(newTime.Year, newTime.Month); newTime.Day =((newTime.Day - 1 + md) - 1) % md + 1; pauze; } showSetup(true); } pauze; case ALARM_SET:if (inSubMenu) { switch(alarmSetMode) { case ALARM_HOUR:EepromData.hours =(EepromData.hours + 24 - 1) % 24; pauze; geval ALARM_MIN:EepromData.minuten =(EepromData.minuten + 60 - 1) % 60; pauze; geval ALARM_STATE:EepromData.alarm =!EepromData.alarm; pauze; } showSetup(true); } pauze; geval TUNE_SET:EepromData.tune =(EepromData.tune + NUM_OF_MELODIES - 1) % NUM_OF_MELODIES; showSetup(true); pauze; case BRIGHT_SET:EepromData.brightness =(EepromData.brightness + MAX_INTENSITY - 1) % MAX_INTENSITY; mx.control(MD_MAX72XX::INTENSITEIT, EepromData.brightness); //0..MAX_INTENSITY showSetup (true); pauze; case FORMAT_SET:if (inSubMenu) { switch (formatSetMode) { case DAY_MONTH:EepromData.formatDmy =!EepromData.formatDmy; pauze; geval FONT_STYLE:EepromData.squareFont =!EepromData.squareFont; pauze; } } showSetup(true); pauze; }}//---------------------------------------------- -----------------//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; pauze; case TIME_MIN:newTime.Minute =(newTime.Minute + 1) % 60; pauze; geval TIME_FORMAT:EepromData.format12hr =!EepromData.format12hr; pauze; } showSetup(true); } pauze; case DATE_SET:if (inSubMenu) { switch(dateSetMode) { case DATE_YEAR:newTime.Year =((newTime.Year - 30) + 1) % 100 + 30; pauze; case DATE_MONTH:newTime.Month =((newTime.Month - 1) + 1) % 12 + 1; pauze; case DATE_DAY:uint8_t md =daysInMonth(newTime.Year, newTime.Month); newTime.Day =(newTime.Day % md) + 1; pauze; } showSetup(true); } pauze; case ALARM_SET:if (inSubMenu) { switch(alarmSetMode) { case ALARM_HOUR:EepromData.hours =(EepromData.hours + 1) % 24; pauze; geval ALARM_MIN:EepromData.minuten =(EepromData.minuten + 1) % 60; pauze; geval ALARM_STATE:EepromData.alarm =!EepromData.alarm; pauze; } showSetup(true); } pauze; geval TUNE_SET:EepromData.tune =(EepromData.tune + 1) % NUM_OF_MELODIES; showSetup(true); pauze; case BRIGHT_SET:EepromData.brightness =(EepromData.brightness + 1) % MAX_INTENSITY; mx.control(MD_MAX72XX::INTENSITEIT, EepromData.brightness); //0..MAX_INTENSITY showSetup (true); pauze; case FORMAT_SET:if (inSubMenu) { switch (formatSetMode) { case DAY_MONTH:EepromData.formatDmy =!EepromData.formatDmy; pauze; geval FONT_STYLE:EepromData.squareFont =!EepromData.squareFont; pauze; } } showSetup(true); pauze; }}//---------------------------------------------- -----------------//Schakel het alarm uit als het een tunebool afspeelt cancelAlarm(){ if (musicPlaying) { musicPlaying =false; alarmCancelled =alarmRinging; retourneer waar; } opbrengst(); return false;}//-------------------------------------------- -------------------//Toon het setup-menu en flash het huidige geselecteerde item ongeldig showSetup(bool force){ setupDisplayState =setupDisplayState | kracht; kracht =kracht || (millis()> setupTimeout); if (forceren) { setupTimeout =millis () + SETUP_FLASH_RATE; bool aan =setupDisplayState; setupDisplayState =!setupDisplayState; mx.clear(); if (aan || !(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 (op || !(clockMode ==DATE_SET &&!inSubMenu)) displayString(1,7,"DATE"); if (op || !(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_YEAR)) displayNumber(1,13,tmYearToCalendar(newTime.Year),4,true); if (op || !(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_MONTH)) displayNumber(1,18,newTime.Month,2,true); if (op || !(clockMode ==DATE_SET &&inSubMenu &&dateSetMode ==DATE_DAY)) displayNumber(1,21,newTime.Day,2,true); if (aan || !(clockMode ==ALARM_SET &&!inSubMenu)) displayString(2,6,"ALARN"); if (aan || !(clockMode ==ALARM_SET &&inSubMenu &&alarmSetMode ==ALARM_HOUR)) displayNumber(2,13,EepromData.hours,2,true); if (aan || !(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 (aan || !(clockMode ==TUNE_SET &&!inSubMenu)) displayString(3,7,"TUNE"); if (on || !(clockMode ==TUNE_SET &&inSubMenu)) { switch(EepromData.tune) { case 0:displayString(3,13,"ELISE"); pauze; geval 1:displayString(3,13,"RANGE"); pauze; geval 2:displayString (3,13,"SUNSHINE"); pauze; } } if (aan || !(clockMode ==BRIGHT_SET &&!inSubMenu)) displayString(4,1,"BRIGHTNESS"); if (aan || !(clockMode ==BRIGHT_SET &&inSubMenu)) displayNumber(4,13,EepromData.brightness,0,false); if (op || !(clockMode ==FORMAT_SET &&!inSubMenu)) displayString(5,0,"DATE ​​FORNAT"); if (op || !(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(); }}//---------------------------------------------- -----------------//Geef de huidige tijd weer op het display indien gewijzigd// forceer - toon altijd de tijd, zelfs als deze niet is gewijzigdvoid showTime(bool force){ force =force || (lastSeconds !=seconde()); if (force) { lastSeconds =second(); showTime(hour(), minute(), true, true, (second() &0x01), (clockMode !=CLOCK || !EepromData.format12hr)); }}//---------------------------------------------- -----------------//Toon de tijd op het display// h - uur// m - minuut// he - uur inschakelen // me - minuten inschakelen // ce - dubbele punt inschakelen void showTime(int h, int m, bool he, bool me, bool ce, bool f24){ mx.clear(); if (hij) { if (!f24 &&h> 12) { h =h - 12; } if (h> 9 || f24) { displayLargeDigit(0, h/10); } displayLargeDigit(5, uur % 10); } if (me) { displayLargeDigit(13, m/10); displayLargeDigit (18, m % 10); } if (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); datumcijfer weergeven(XOFS+4, d % 10); datumcijfer weergeven(XOFS+8, 10); // dubbele punt displayDateDigit (XOFS+12, m/10); datumcijfer weergeven(XOFS+16, m % 10); } else { displayDateDigit(XOFS+0, m/10); datumcijfer weergeven(XOFS+4, m % 10); datumcijfer weergeven(XOFS+8, 10); // dubbele punt displayDateDigit (XOFS+12, d/10); datumcijfer weergeven(XOFS+16, d % 10); } displayNumber (5, 10, y, 0, onwaar); mx.update();}//----------------------------------------- ----------------------// Schrijf een vierkant of klein cijfer op basis van de configuratie-instelling// x =0 tot 23// v =groot of vierkant cijfer voor display (0..10) ongeldig displayDateDigit(uint8_t x, uint8_t v){ if (EepromData.squareFont) { displaySquareDigit(x, v); } else { displaySmallDigit(x, v); }}//---------------------------------------------- -----------------// Schrijf een segmentbitmasker// x =0 tot 23// v =groot cijfer om weer te geven (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(rij, col + x, pgm_read_byte(&largeDigits[v][row][col]), false); } } }}//-------------------------------------------- -------------------// Schrijf een segmentbitmasker// x =0 tot 23// v =groot cijfer om weer te geven (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(rij, col + x, pgm_read_byte(&smallDigits[v][row][col]), false); } } }}//-------------------------------------------- -------------------// Schrijf een segmentbitmasker// x =0 tot 23// v =groot cijfer om weer te geven (0..10)void displaySquareDigit( uint8_t col, uint8_t v) { // Segmentvolgorde defbca _ g uint8_t mask =ascii [v]; if (masker ==B00000000) {// Koppeltekenmasker =B00000001; } if (masker &B00000100) {//seg A writePhysicalDigit (0, col + 0, 0xff, false); writePhysicalDigit(0, col + 1, 0xff, false); writePhysicalDigit(0, col + 2, 0xff, false); } if (masker &B00010000) { // seg B writePhysicalDigit (0, col + 2, 0xff, false); writePhysicalDigit (1, col + 2, 0xff, false); writePhysicalDigit(2, col + 2, 0xff, false); } if (masker &B00001000) {//seg C writePhysicalDigit (2, col + 2, 0xff, false); writePhysicalDigit (3, col + 2, 0xff, false); writePhysicalDigit (4, col + 2, 0xff, false); } if (masker &B10000000) { // seg D writePhysicalDigit (4, col + 0, 0xff, false); writePhysicalDigit(4, col + 1, 0xff, false); writePhysicalDigit (4, col + 2, 0xff, false); } if (masker &B01000000) {//seg C writePhysicalDigit (2, col, 0xff, false); writePhysicalDigit (3, col, 0xff, false); writePhysicalDigit(4, col, 0xff, false); } if (masker &B00100000) { // seg E writePhysicalDigit (0, col, 0xff, false); writePhysicalDigit (1, col, 0xff, false); writePhysicalDigit(2, col, 0xff, false); } if (masker &B00000001) {//seg D writePhysicalDigit (2, col + 0, 0xff, false); writePhysicalDigit(2, col + 1, 0xff, false); writePhysicalDigit(2, col + 2, 0xff, false); }}//---------------------------------------------- -----------------// Schrijf tekenreeksuint8_t displayString(uint8_t rij, uint8_t col, String s){ voor (int i =0; i  0x5F) { c =0x3F; // Gebruikt als spatieteken } c =c - 0x30; writePhysicalDigit (rij, col, ascii [c], waar); col =col + 1; }}//---------------------------------------------- -----------------// Schrijf een nummeruint8_t displayNumber(uint8_t row, uint8_t col, int number, int padding, bool leadingZeros){ if (padding ==0) { padding =(getal> 0) ? verdieping(log10(getal)) + 1 :1; } col =col + opvulling; bool eerst =waar; for (int i =0; i > 2) * 3 + (rij>> 1); uint16_t c =((uint16_t)dev <<3) | cijferkaart[dig]; if (!erase) { v =v | mx.getColumn(c); } mx.setColumn(c, v); }}//---------------------------------------------- -----------------//Retourneer de dagen in een bepaald jaar en maand//Feb heeft 28 tenzij schrikkeljaar of de eeuwwisselinguint8_t daysInMonth(int y, int m) { return dom[m - 1] + ((m ==2 &&(y % 4) ==0 &&(y % 100) !=0) ? 1 :0);}//------- -------------------------------------------------- ------//Schrijf de EepromData-structuur naar EEPROMvoid writeEepromData(){ //Deze functie gebruikt EEPROM.update() om het schrijven uit te voeren, dus herschrijft de waarde niet als deze niet is gewijzigd. EEPROM.put(EEPROM_ADDRESS,EepromData);}//-------------------------------------- -------------------------//Lees de EepromData structuur van EEPROM, initialiseer indien nodigvoid readEepromData(){ //Eprom EEPROM.get(EEPROM_ADDRESS, EepromData); //Serial.println ("magic:" + String (EepromData.magic, 16) + ", alarm:" + String (EepromData.alarm) + ", tijd:" + String (EepromData.hours) + ":" + String(EepromData.minutes) + ", 12hr:" + String(EepromData.format12hr) + ", helderheid:" + String(EepromData.brightness)); if (EepromData.magic! =EEPROM_MAGIC) { Serial.println ("Initialiseren van EEPROM ..."); EepromData.magic =EEPROM_MAGIC; EepromData.alarm =onwaar; EepromData.minuten =30; EepromData.uren =5; EepromData.format12hr =onwaar; EepromData.brightness =8; EepromData.tune =0; EepromData.formatDmy =false; schrijfEepromData(); } Serial.println("alarm:" + String(EepromData.alarm) + ", tijd:" + String(EepromData.hours) + ":" + String(EepromData.minutes) + ", 12hr:" + String(EepromData .format12hr) + ", helderheid:" + String (EepromData.brightness));}//----------------------------- ----------------------------------//Speel een melodyint playSong (const uint16_t* melodie){ //Speel elke noot in de melodie totdat de END_OF_TUNE noot wordt gevonden musicPlaying =true; int dezeOpmerking =0; uint16_t noteRaw =pgm_read_word(&melody[thisNote++]); while (muziek afspelen &¬eRaw !=END_OF_TUNE) { testButtons(); opbrengst(); playNote(noteRaw); noteRaw =pgm_read_word(&melody[thisNote++]); } //tijdens vertraging (50);}//-------------------------------------- -------------------------//Play a single notevoid playNote(uint16_t noteRaw){ // to calculate the note duration, take one second divided by the note type. // e.g. quarter note =1000 / 4, eighth note =1000/8, etc. uint16_t frequency =noteRaw &0x1FFF; uint16_t duration =(noteRaw &0xE000)>> 13; if (duration ==7) duration =8; uint16_t noteDuration =1800 / duration; if (frequency !=REST) { tone(SPEAKER, frequency, noteDuration); } // to distinguish the notes, set a minimum time between them. // the note's duration + 30% seems to work well:uint16_t pauseBetweenNotes =(noteDuration * 13) / 10; delay(pauseBetweenNotes); if (frequency !=REST) { // stop the tone playing: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 _ a b c d e f g#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_ B00000010#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)uint8_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___, _bcde_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++
No preview (download only).
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).

Aangepaste onderdelen en behuizingen

Schema's

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

Productieproces

  1. Arduino pov vision-klok
  2. Eenvoudige Word Clock (Arduino)
  3. Arduino klok met islamitische gebedstijden
  4. Hoofdklok
  5. Enkele LED Matrix Arduino Flip Clock
  6. Een LED-matrix besturen met Arduino Uno
  7. eDOT - op Arduino gebaseerde precisieklok en weerstation
  8. Mini-radar met Arduino
  9. Arduino OLED-temperatuurweergave met realtime klok
  10. Arduino Shield NCS314 NIXIE buizenklok IN-14
  11. Eenvoudige wekker met DS1302 RTC