Dom, dizajn, renoviranje, uređenje.  Dvorište i vrt.  Vlastitim rukama

Dom, dizajn, renoviranje, uređenje. Dvorište i vrt. Vlastitim rukama

» Takt na AVR mikrokontroleru s DS1307. Uradi sam sat s LED zaslonom Uradi sam veliki elektronski sat

Takt na AVR mikrokontroleru s DS1307. Uradi sam sat s LED zaslonom Uradi sam veliki elektronski sat

U prodaji možete pronaći mnogo različitih modela i opcija elektroničkih digitalnih satova, ali većina njih je namijenjena za unutarnju upotrebu, budući da su brojevi mali. Ipak, ponekad je potrebno postaviti sat na ulicu – na primjer, na zid kuće, ili na stadion, trg, odnosno tamo gdje će ga iz velike udaljenosti vidjeti mnogo ljudi. U tu svrhu razvijen je i uspješno sastavljen ovaj sklop velikog LED sata na koji možete spojiti (putem internih tranzistorskih sklopki) LED indikatore bilo koje veličine. Shematski dijagram možete povećati klikom na njega:

Opis sata

  1. Gledati. U ovom načinu rada postoji standardna vrsta prikaza vremena. Postoji digitalna korekcija točnosti sata.
  2. Termometar. U ovom slučaju uređaj mjeri temperaturu prostorije ili vanjskog zraka s jednog senzora. Raspon od -55 do +125 stupnjeva.
  3. Predviđena je kontrola napajanja.
  4. Prikazuje informacije na indikatoru naizmjenično - sat i termometar.
  5. Za spremanje postavki i postavki kada se izgubi 220V, koristi se trajna memorija.


Osnova uređaja je ATMega8 MK, koji se trepće postavljanjem osigurača prema tablici:

Rad i upravljanje satom

Kada prvi put uključite sat, na ekranu će se pojaviti reklamni pozdravni ekran, nakon čega će se prebaciti na prikaz vremena. Pritiskom na gumb POSTAVI VRIJEME indikator će ići u krug iz glavnog načina:

  • način prikaza minuta i sekundi. Ako u ovom načinu rada istovremeno pritisnete gumb PLUS I MINUS, tada će se sekunde resetirati;
  • postavljanje minuta trenutnog vremena;
  • postavljanje trenutnog sata;
  • simbol t. Podešavanje trajanja prikaza sata;
  • simbol o. Vrijeme prikaza simbola indikacije vanjske temperature (out);
  • iznos dnevne korekcije točnosti sata. Simbol c i vrijednost korekcije. Postavljanje ograničenja od -25 do 25 sekundi. Odabrana vrijednost će se dodavati ili oduzimati od trenutnog vremena svaki dan u 0 sati 0 minuta i 30 sekundi. Za više detalja pročitajte upute koje se nalaze u arhivi s datotekama firmware-a i tiskanih ploča.

Podešavanje sata

Dok držite pritisnute tipke PLUS/MINUS Radimo ubrzano postavljanje vrijednosti. Nakon promjene bilo koje postavke, nakon 10 sekundi nove vrijednosti bit će zapisane u trajnu memoriju i očitat će se odatle kada se napajanje ponovno uključi. Nove postavke stupaju na snagu tijekom instalacije. Mikrokontroler prati prisutnost glavnog napajanja. Kada je isključen, uređaj se napaja iz internog izvora. Dolje je prikazan dijagram redundantnog modula napajanja:


Kako bi se smanjila potrošnja struje, indikator, senzori i gumbi su isključeni, ali sam sat nastavlja brojati vrijeme. Čim se pojavi mrežni napon od 220 V, vraćaju se sve funkcije indikacije.


Budući da je uređaj zamišljen kao veliki LED sat, ima dva zaslona: veliki LED - za ulicu i mali LCD - za jednostavno podešavanje glavnog zaslona. Veliki zaslon nalazi se nekoliko metara od upravljačke jedinice i povezan je s dva kabela od 8 žica. Za upravljanje anodama vanjskog indikatora indikatora koriste se tranzistorski prekidači prema dijagramu danom u arhivi. Autori projekta: Alexandrovich & SOIR.

Postoji mnogo načina za sastavljanje elektroničkog sata vlastitim rukama: dijagrami su široko predstavljeni u literaturi i na Internetu. Većina modernih implementacija temelji se na mikrokontrolerima. Provedba takvih projekata često zahtijeva opsežne praktične vještine i teoretsko znanje u području elektronike: sposobnost korištenja specijaliziranog softvera, izradu tiskanih ploča kod kuće pomoću jetkanja željeznim kloridom i dobro lemljenje. Također morate imati razne alate i zalihe.

Međutim, postoji jednostavan i pristupačan način sastavljanja elektroničkog sata vlastitim rukama kod kuće: koristite Arduino platformu. To je softverski i hardverski kompleks posebno dizajniran za podučavanje osnova programiranja i elektronike. Uz pomoć Arduina, svatko, čak i bez posebne prethodne obuke, može vlastitim rukama izgraditi elektronički sat: nisu potrebni dijagrami strujnog kruga, inženjerski programi, pa čak ni lemilo!

Spajanje svih elektroničkih komponenti provodi se na posebnoj kontaktnoj („bez lemljenja“) matičnoj ploči, što eliminira rizik od opeklina, posjekotina i drugih ozljeda - stoga možete raditi s Arduino dizajnerom zajedno s djecom. Vizualni način prikazivanja dijagrama strujnog kruga pomoći će vam da izbjegnete pogreške prilikom sastavljanja uređaja.

Korak 1. Popis komponenti

Za sastavljanje jednostavnog sata na LED matricama trebat će vam samo nekoliko jeftinih komponenti:

  • Arduino platforma. Najjednostavniji modeli će poslužiti - ili Micro;
  • kontaktna matična ploča;
  • spojne žice za matičnu ploču;
  • Adafruit DS3231 modul sata za realno vrijeme;
  • LED matrični modul 32x8 MAX7219;
  • dva gumba.

Također ćete trebati osobno računalo i USB-mini-USB kabel za učitavanje upravljačkog programa u memoriju. To je sve - nisu potrebni lemilo, alati za skidanje izolacije, noževi za montažu i drugi profesionalni alati: sve se radnje izvode ručno. Možda je u nekim slučajevima prikladnije koristiti pincetu, ali možete i bez nje.


Korak 2. Sastavljanje elektroničkog sklopa

Krug elektroničkog sata s LED zaslonom koji koristi Arduino izgledat će prilično jednostavan čak i za neiskusne radio amatere. Za sastavljanje je potrebno samo nekoliko žica. Tablica povezivanja:

Arduino modul → 32x8 MAX7219 LED matrica

Arduino modul → Adafruit DS3231 sat stvarnog vremena

Arduino modul → gumbi

D2 - tipka 1

D3 - gumb 2

Drugi pin tipki spojen je na GND.

Samo trebate obratiti pažnju i zapamtiti kako su kontaktne rupe na matičnoj ploči povezane jedna s drugom. Sljedeći dijagram ilustrira metodu unutarnjeg spajanja kontaktnih rupa:


Dva reda (1 i 4) s obje strane spojena su vodoravno - obično se koriste kao +5V strujni vod i GND uzemljenje. Svi unutarnji kontakti (2 i 3) zatvoreni su vertikalno. U ovom slučaju, tiskana ploča je podijeljena i okomito i vodoravno na dva simetrična dijela neovisna jedan o drugom. To omogućuje, na primjer, sastavljanje dva različita uređaja na jednoj ploči.

Shema elektroničkog sata s LED indikacijom, kao i raspored elemenata na tiskanoj pločici prikazan je na slici:

Pažljivo provjerite jesu li svi priključci u skladu s prikazanim dijagramom. Također provjerite jesu li vodiči dobro pričvršćeni u kontaktnim rupama na tiskanoj ploči.


Korak 3. Arduino firmware

Nakon što je sastavljanje i testiranje kruga završeno, možete početi učitavati kontrolni program (ili "firmware") u Arduino memoriju.


Da biste to učinili, trebate instalirati besplatno službeno razvojno okruženje - . Trebat će vam i izvorni kod projekta koji možete preuzeti ispod u arhivi sa svim bibliotekama i skicom, a ako vam treba samo skica, možete je zasebno kopirati:

//uključi biblioteke: #include "LedControl.h" #include // Knjižnica fontova #include // DS1307 sat #include "RTClib.h" // DS1307 sat #include // Biblioteka gumba Alexandera Breviga // Postavljanje LED matrice // pin 12 spojen je na DataIn na zaslonu // pin 11 spojen je na CLK na zaslonu // pin 10 spojen je na LOAD na zaslonu LedControl lc = LedControl(6, 5, 4, 4); //postavlja 3 pina kao 12, 11 & 10 i zatim postavlja 4 zaslona (maksimum je 8 zaslona) //globalne varijable byte intensity = 7; // Zadani intenzitet/svjetlina (0-15) byte clock_mode = 0; // Zadani način rada sata. Zadano = 0 (osnovni_način) bool random_mode = 0; // Definirajte nasumični način - mijenja vrstu prikaza svakih nekoliko sati. Zadano = 0 (isključeno) byte old_mode = clock_mode; // Pohranjuje prethodni način rada sata, tako da ako idemo na datum ili bilo što drugo, znamo na koji način da se vratimo nakon toga. bool ampm = 0; // Definirajte vrijeme od 12 ili 24 sata. 0 = 24 sata. 1 = 12 satni bajt change_mode_time = 0; // Zadržava sat kada će se način sata sljedeći put promijeniti ako je u nasumičnim načinima. dugo vrijeme kašnjenja bez predznaka = 500; // Uvijek čekamo malo između ažuriranja prikaza int rtc; // Drži izlaz sata realnog vremena char days = ( "Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"); //niz dana - koristi se u slajd, osnovni_mod i jumble način rada (DS1307 daje 1-7 vrijednosti za dan u tjednu) char daysfull = ( "nedjelja", "ponedjeljak", "utorak", "srijeda", "četvrtak" ", "Petak", "Subota" ); char sufiks = ("st", "nd", "rd", "th"); //niz sufiksa datuma, koristi se u slajdovima, osnovnim_načinima i načinima džumbl. e,g, 1st 2nd ... //definirajte konstante #definirajte NUM_DISPLAY_MODES 3 // Načini prikaza brojeva (sadrži nulu kao prvi način) #definirajte NUM_SETTINGS_MODES 4 // Načini postavki brojeva = 6 (sadrži nulu kao prvi način) # definirajte SLIDE_DELAY 20 // Vrijeme u milisekundama za efekt slajda po znaku u modu slajda. Neka ovo bude veće za sporiji učinak #define cls clear_display // Čisti prikaz RTC_DS1307 ds1307; // Stvaranje RTC objekta Button buttonA = Button(2, BUTTON_PULLUP); // Postavljanje gumba A (koristeći biblioteku gumba) Button buttonB = Button(3, BUTTON_PULLUP); // Gumb za postavljanje B (pomoću biblioteke gumba) void setup() ( digitalWrite(2, HIGH); // uključite pullup otpornik za gumb na pinu 2 digitalWrite(3, HIGH); // uključite pullup otpornik za gumb na pinu 3 digitalWrite(4, HIGH); // uključite pullup otpornik za gumb na pinu 4 Serial.begin(9600); //pokrenite serijski //inicijalizirajte 4 matrične ploče //već smo postavili broj uređaja kada smo kreirali uređaji LedControl int = lc.getDeviceCount(); //moramo pokrenuti sve uređaje u petlji za (int adresa = 0; adresa< devices; address++) { /*The MAX72XX is in power-saving mode on startup*/ lc.shutdown(3-address, false); /* Set the brightness to a medium values */ lc.setIntensity(3-address, intensity); /* and clear the display */ lc.clearDisplay(3-address); } //Setup DS1307 RTC #ifdef AVR Wire.begin(); #else Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino #endif ds1307.begin(); //start RTC Clock if (! ds1307.isrunning()) { Serial.println("RTC is NOT running!"); ds1307.adjust(DateTime(__DATE__, __TIME__)); // sets the RTC to the date & time this sketch was compiled } //Show software version & hello message printver(); //enable red led digitalWrite(13, HIGH); } void loop() { //run the clock with whatever mode is set by clock_mode - the default is set at top of code. switch (clock_mode){ case 0: basic_mode(); break; case 1: small_mode(); break; case 2: slide(); break; case 3: word_clock(); break; case 4: setup_menu(); break; } } //plot a point on the display void plot (byte x, byte y, byte val) { //select which matrix depending on the x coord byte address; if (x >= 0 && x<= 7) { address = 3; } if (x >= 8 && x<= 15) { address = 2; x = x - 8; } if (x >= 16 && x<= 23) { address = 1; x = x - 16; } if (x >= 24 && x<= 31) { address = 0; x = x - 24; } if (val == 1) { lc.setLed(address, y, x, true); } else { lc.setLed(address, y, x, false); } } //clear screen void clear_display() { for (byte address = 0; address < 4; address++) { lc.clearDisplay(address); } } //fade screen down void fade_down() { //fade from global intensity to 1 for (byte i = intensity; i >0; i--) ( za (adresa bajta = 0; adresa< 4; address++) { lc.setIntensity(address, i); } delay(30); //change this to change fade down speed } clear_display(); //clear display completely (off) //reset intentsity to global val for (byte address = 0; address < 4; address++) { lc.setIntensity(address, intensity); } } //power up led test & display software version number void printver() { byte i = 0; char ver_a = "MADE"; char ver_b = "IN"; char ver_c = "RUSSIA"; //test all leds. for (byte x = 0; x <= 32; x++) { for (byte y = 0; y <= 7; y++) { plot(x, y, 1); } } delay(300); fade_down(); while (ver_a[i]) { puttinychar((i * 4), 1, ver_a[i]); delay(35); i++; } delay(500); fade_down(); i = 0; while (ver_b[i]) { puttinychar((i * 4), 1, ver_b[i]); delay(35); i++; } delay(500); fade_down(); i = 0; while (ver_c[i]) { puttinychar((i * 4), 1, ver_c[i]); delay(35); i++; } delay(500); fade_down(); } // puttinychar // Copy a 3x5 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate // This is unoptimized and simply uses plot() to draw each dot. void puttinychar(byte x, byte y, char c) { byte dots; if (c >= "A" && c<= "Z" || (c >= "a" && c<= "z")) { c &= 0x1F; // A-Z maps to 1-26 } else if (c >= "0" && c<= "9") { c = (c - "0") + 32; } else if (c == " ") { c = 0; // space } else if (c == ".") { c = 27; // full stop } else if (c == ":") { c = 28; // colon } else if (c == "\"") { c = 29; // single quote mark } else if (c == "!") { c = 30; // single quote mark } else if (c == "?") { c = 31; // single quote mark } for (byte col = 0; col < 3; col++) { dots = pgm_read_byte_near(&mytinyfont[c]); for (char row = 0; row < 5; row++) { if (dots & (16 >> red)) plot(x + stupac, y + red, 1); else plot(x + col, y + row, 0); ) ) ) void putnormalchar(byte x, byte y, char c) (byte točkice; // if (c >= "A" && c<= "Z" || (c >= "a" && c<= "z")) { // c &= 0x1F; // A-Z maps to 1-26 // } if (c >= "A" && c<= "Z") { c &= 0x1F; // A-Z maps to 1-26 } else if (c >= "a" && c<= "z") { c = (c - "a") + 41; // A-Z maps to 41-67 } else if (c >= "0" && c<= "9") { c = (c - "0") + 31; } else if (c == " ") { c = 0; // space } else if (c == ".") { c = 27; // full stop } else if (c == "\"") { c = 28; // single quote mark } else if (c == ":") { c = 29; // clock_mode selector arrow } else if (c == ">") ( c = 30; // strelica selektora clock_mode ) else if (c >= -80 && c<= -67) { c *= -1; } for (char col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont[c]); for (char row = 0; row < 7; row++) { //check coords are on screen before trying to plot //if ((x >= 0) && (x<= 31) && (y >= 0) && (y<= 7)){ if (dots & (64 >> red)) ( // samo 7 redaka. iscrtaj(x + stupac, y + red, 1); ) else ( iscrtaj(x + stupac, y + red, 0); ) //) ) ) ) //mali_mod //prikaži vrijeme u malim 3x5 znakovima s prikazom sekundi void small_mode() ( char textchar; // 16 znakova na zaslonu byte mins = 100; //mins byte secs = rtc; //seconds byte old_secs = secs; / /drži staru vrijednost sekundi - od posljednjeg vremena kada su sekunde ažurirane o prikaz - koristi se za provjeru jesu li sekunde promijenile cls(); //pokretanje glavne petlje sata sve dok run_mode vraća true while (run_mode()) ( get_time(); / /provjeri pritisak gumba if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); return; ) //ako su se sekunde promijenile, ažurirajte ih na zaslonu secs = rtc; if (secs != old_secs) ( //secs char buffer; itoa(secs, buffer, 10); //fix - inače ako num ima početnu nulu, npr. "03" secs, itoa to pokriva znakovima s razmakom "3". ako (sek< 10) { buffer = buffer; buffer = "0"; } puttinychar(20, 1, ":"); //seconds colon puttinychar(24, 1, buffer); //seconds puttinychar(28, 1, buffer); //seconds old_secs = secs; } //if minute changes change time if (mins != rtc) { //reset these for comparison next time mins = rtc; byte hours = rtc; if (hours > < 1) { hours = hours + ampm * 12; } //byte dow = rtc; // the DS1307 outputs 0 - 6 where 0 = Sunday0 - 6 where 0 = Sunday. //byte date = rtc; //set characters char buffer; itoa(hours, buffer, 10); //fix - as otherwise if num has leading zero, e.g. "03" hours, itoa coverts this to chars with space "3 ". if (hours < 10) { buffer = buffer; //if we are in 12 hour mode blank the leading zero. if (ampm) { buffer = " "; } else { buffer = "0"; } } //set hours chars textchar = buffer; textchar = buffer; textchar = ":"; itoa (mins, buffer, 10); if (mins < 10) { buffer = buffer; buffer = "0"; } //set mins characters textchar = buffer; textchar = buffer; //do seconds textchar = ":"; buffer; secs = rtc; itoa(secs, buffer, 10); //fix - as otherwise if num has leading zero, e.g. "03" secs, itoa coverts this to chars with space "3 ". if (secs < 10) { buffer = buffer; buffer = "0"; } //set seconds textchar = buffer; textchar = buffer; byte x = 0; byte y = 0; //print each char for (byte x = 0; x < 6 ; x++) { puttinychar(x * 4, 1, textchar[x]); } } delay(50); } fade_down(); } // basic_mode() // show the time in 5x7 characters void basic_mode() { cls(); char buffer; //for int to char conversion to turn rtc values into chars we can print on screen byte offset = 0; //used to offset the x postition of the digits and centre the display when we are in 12 hour mode and the clock shows only 3 digits. e.g. 3:21 byte x, y; //used to draw a clear box over the left hand "1" of the display when we roll from 12:59 ->1:00 ujutro u 12-satnom režimu. //izvršite konverziju 12/24 sata ako je ampm postavljen na 1 bajt sati = rtc; if (sati > 12) ( sati = sati - ampm * 12; ) if (sati< 1) { hours = hours + ampm * 12; } //do offset conversion if (ampm && hours < 10) { offset = 2; } //set the next minute we show the date at //set_next_date(); // initially set mins to value 100 - so it wll never equal rtc on the first loop of the clock, meaning we draw the clock display when we enter the function byte secs = 100; byte mins = 100; int count = 0; //run clock main loop as long as run_mode returns true while (run_mode()) { //get the time from the clock chip get_time(); //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); return; } //check whether it"s time to automatically display the date //check_show_date(); //draw the flashing: as on if the secs have changed. if (secs != rtc) { //update secs with new value secs = rtc; //draw: plot (15 - offset, 2, 1); //top point plot (15 - offset, 5, 1); //bottom point count = 400; } //if count has run out, turn off the: if (count == 0) { plot (15 - offset, 2, 0); //top point plot (15 - offset, 5, 0); //bottom point } else { count--; } //re draw the display if button pressed or if mins != rtc i.e. if the time has changed from what we had stored in mins, (also trigggered on first entering function when mins is 100) if (mins != rtc) { //update mins and hours with the new values mins = rtc; hours = rtc; //adjust hours of ampm set to 12 hour mode if (hours >12) ( sati = sati - ampm * 12; ) if (sati< 1) { hours = hours + ampm * 12; } itoa(hours, buffer, 10); //if hours < 10 the num e.g. "3" hours, itoa coverts this to chars with space "3 " which we dont want if (hours < 10) { buffer = buffer; buffer = "0"; } //print hours //if we in 12 hour mode and hours < 10, then don"t print the leading zero, and set the offset so we centre the display with 3 digits. if (ampm && hours < 10) { offset = 2; //if the time is 1:00am clear the entire display as the offset changes at this time and we need to blank out the old 12:59 if ((hours == 1 && mins == 0)) { cls(); } } else { //else no offset and print hours tens digit offset = 0; //if the time is 10:00am clear the entire display as the offset changes at this time and we need to blank out the old 9:59 if (hours == 10 && mins == 0) { cls(); } putnormalchar(1, 0, buffer); } //print hours ones digit putnormalchar(7 - offset, 0, buffer); //print mins //add leading zero if mins < 10 itoa (mins, buffer, 10); if (mins < 10) { buffer = buffer; buffer = "0"; } //print mins tens and ones digits putnormalchar(19 - offset, 0, buffer); putnormalchar(25 - offset, 0, buffer); } } fade_down(); } //like basic_mode but with slide effect void slide() { byte digits_old = {99, 99, 99, 99}; //old values we store time in. Set to somthing that will never match the time initially so all digits get drawn wnen the mode starts byte digits_new; //new digits time will slide to reveal byte digits_x_pos = {25, 19, 7, 1}; //x pos for which to draw each digit at char old_char; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function char new_char; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function //old_chars - stores the 5 day and date suffix chars on the display. e.g. "mon" and "st". We feed these into the slide animation as the current char when these chars are updated. //We sent them as A initially, which are used when the clocl enters the mode and no last chars are stored. //char old_chars = "AAAAA"; //plot the clock colon on the display cls(); putnormalchar(13, 0, ":"); byte old_secs = rtc; //store seconds in old_secs. We compare secs and old secs. WHen they are different we redraw the display //run clock main loop as long as run_mode returns true while (run_mode()) { get_time(); //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); return; } //if secs have changed then update the display if (rtc != old_secs) { old_secs = rtc; //do 12/24 hour conversion if ampm set to 1 byte hours = rtc; if (hours >12) ( sati = sati - ampm * 12; ) if (sati< 1) { hours = hours + ampm * 12; } //split all date and time into individual digits - stick in digits_new array //rtc = secs //array pos and digit stored //digits_new = (rtc%10); //0 - secs ones //digits_new = ((rtc/10)%10); //1 - secs tens //rtc = mins digits_new = (rtc % 10); //2 - mins ones digits_new = ((rtc / 10) % 10); //3 - mins tens //rtc = hours digits_new = (hours % 10); //4 - hour ones digits_new = ((hours / 10) % 10); //5 - hour tens //rtc = date //digits_new = (rtc%10); //6 - date ones //digits_new = ((rtc/10)%10); //7 - date tens //draw initial screen of all chars. After this we just draw the changes. //compare digits 0 to 3 (mins and hours) for (byte i = 0; i <= 3; i++) { //see if digit has changed... if (digits_old[i] != digits_new[i]) { //run 9 step animation sequence for each in turn for (byte seq = 0; seq <= 8 ; seq++) { //convert digit to string itoa(digits_old[i], old_char, 10); itoa(digits_new[i], new_char, 10); //if set to 12 hour mode and we"re on digit 2 (hours tens mode) then check to see if this is a zero. If it is, blank it instead so we get 2.00pm not 02.00pm if (ampm && i == 3) { if (digits_new == 0) { new_char = " "; } if (digits_old == 0) { old_char = " "; } } //draw the animation frame for each digit slideanim(digits_x_pos[i], 0, seq, old_char, new_char); delay(SLIDE_DELAY); } } } /* //compare date digit 6 (ones) and (7) tens - if either of these change we need to update the date line. We compare date tens as say from Jan 31 ->Feb 01 onda se jedna znamenka ne mijenja ako ((digits_old != digits_new) || (digits_old != digits_new)) ( //promijenite prikazani dan. Petlja ispod prolazi kroz svaki od 3 znaka redom, npr. "MON" za (bajt day_char = 0; day_char<=2 ; day_char++){ //run the anim sequence for each char for (byte seq = 0; seq <=8 ; seq++){ //the day (0 - 6) Read this number into the days char array. the seconds number in the array 0-2 gets the 3 chars of the day name, e.g. m o n slideanim(6*day_char,8,seq,old_chars,days); //6 x day_char gives us the x pos for the char delay(SLIDE_DELAY); } //save the old day chars into the old_chars array at array pos 0-2. We use this next time we change the day and feed it to the animation as the current char. The updated char is fed in as the new char. old_chars = days; } //change the date tens digit (if needed) and ones digit. (the date ones digit wil alwaus change, but putting this in the "if" loop makes it a bit neater code wise.) 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,new_char); delay(SLIDE_DELAY); } } } //print the day suffix "nd" "rd" "th" etc. First work out date 2 letter suffix - eg st, nd, rd, th byte s = 3; //the pos to read our suffix array from. byte date = rtc; 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; } 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[s]); // we pass in the old_char array char as the current char and the suffix array as the new char delay(SLIDE_DELAY); } //save the suffic char in the old chars array at array pos 3 and 5. We use these chars next time we change the suffix and feed it to the animation as the current char. The updated char is fed in as the new char. old_chars = suffix[s]; } }//end do date line */ //save digita array tol old for comparison next loop for (byte i = 0; i <= 3; i++) { digits_old[i] = digits_new[i]; } }//secs/oldsecs }//while loop fade_down(); } //called by slide //this draws the animation of one char sliding on and the other sliding off. There are 8 steps in the animation, we call the function to draw one of the steps from 0-7 //inputs are are char x and y, animation frame sequence (0-7) and the current and new chars being drawn. void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) { // To slide one char off and another on we need 9 steps or frames in sequence... // seq# 0123456 <-rows of the display // | ||||||| // seq0 0123456 START - all rows of the display 0-6 show the current characters rows 0-6 // seq1 012345 current char moves down one row on the display. We only see it"s rows 0-5. There are at display positions 1-6 There is a blank row inserted at the top // seq2 6 01234 current char moves down 2 rows. we now only see rows 0-4 at display rows 2-6 on the display. Row 1 of the display is blank. Row 0 shows row 6 of the new char // seq3 56 0123 // seq4 456 012 half old / half new char // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456 END - all rows show the new char //from above we can see... //currentchar runs 0-6 then 0-5 then 0-4 all the way to 0. starting Y position increases by 1 row each time. //new char runs 6 then 5-6 then 4-6 then 3-6. starting Y position increases by 1 row each time. //if sequence number is below 7, we need to draw the current char if (sequence < 7) { byte dots; // if (current_c >= "A" && || (trenutni_c >= "a" && trenutni_c<= "z")) { // current_c &= 0x1F; // A-Z maps to 1-26 // } if (current_c >= "A" && struja_c<= "Z") { current_c &= 0x1F; // A-Z maps to 1-26 } else if (current_c >= "a" && trenutni_c<= "z") { current_c = (current_c - "a") + 41; // A-Z maps to 41-67 } else if (current_c >= "0" && trenutni_c<= "9") { current_c = (current_c - "0") + 31; } else if (current_c == " ") { current_c = 0; // space } else if (current_c == ".") { current_c = 27; // full stop } else if (current_c == "\"") { current_c = 28; // single quote mark } else if (current_c == ":") { current_c = 29; //colon } else if (current_c == ">") ( current_c = 30; // strelica selektora clock_mode ) bajt curr_char_row_max = 7 - sekvenca; //maksimalni broj redaka za crtanje je 6 - broj sekvence bajt start_y = sekvenca; //y pozicija za početak - isto je kao broj sekvence. Uključujemo ovu svaku petlju //crtamo svaki redak do maksimuma retka (izračunatog iz broja sekvence) za (bajt 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); if (dots & (64 >> curr_char_row)) plot(x + col, y + start_y, 1); //nacrt vodi na else plot(x + col, y + start_y, 0); //else plot led off ) start_y++;//dodaj jedan u y tako da nacrtamo sljedeći redak jedan prema dolje ) ) //nacrtaj praznu liniju između znakova ako je niz između 1 i 7. Ako to ne učinimo, dobit ćemo ostaci trenutnih znakova zadnja pozicija lijevo na zaslonu ako (sekvenca >= 1 && sekvenca<= 8) { for (byte col = 0; col < 5; col++) { plot(x + col, y + (sequence - 1), 0); //the y position to draw the line is equivalent to the sequence number - 1 } } //if sequence is above 2, we also need to start drawing the new char if (sequence >= 2) ( //odredite char byte točkice; //if (new_c >= "A" && new_c<= "Z" || (new_c >= "a" && novi_c<= "z")) { // new_c &= 0x1F; // A-Z maps to 1-26 //} if (new_c >= "A" && novo_c<= "Z") { new_c &= 0x1F; // A-Z maps to 1-26 } else if (new_c >= "a" && novi_c<= "z") { new_c = (new_c - "a") + 41; // A-Z maps to 41-67 } else if (new_c >= "0" && novi_c<= "9") { new_c = (new_c - "0") + 31; } else if (new_c == " ") { new_c = 0; // space } else if (new_c == ".") { new_c = 27; // full stop } else if (new_c == "\"") { new_c = 28; // single quote mark } else if (new_c == ":") { new_c = 29; // clock_mode selector arrow } else if (new_c == ">") ( new_c = 30; // strelica selektora clock_mode ) byte newcharrowmin = 6 - (sekvenca - 2); //minimalni broj retka za crtanje za novi char - ovo generira izlaz od 6 do 0 kada se dodaju sekvencijski brojevi 2-8 . Ovo je minimalni redak za crtanje za novi bajt znakova start_y = 0; //y položaj od kojeg treba početi - isti je kao broj sekvence. Upisujemo svaki redak //crtamo svaki red prema gore od minimuma retka (izračunato prema broju sekvence ) do 6 za (bajt newcarrow = newcarrowmin; newcarrow<= 6; newcharrow++) { for (byte col = 0; col < 5; col++) { dots = pgm_read_byte_near(&myfont); if (dots & (64 >> newcarrow)) plot(x + col, y + start_y, 1); //nacrt vodi na else plot(x + col, y + start_y, 0); //else plot led off ) start_y++;//dodaj jedan u y tako da nacrtamo sljedeći redak jedan prema dolje ) ) ) //ispiši sat koristeći riječi umjesto brojeva void word_clock() ( cls(); char numbers = ( "one ", "dva", "tri", "četiri", "pet", "šest", "sedam", "osam", "devet", "deset", "jedanaest", "dvanaest", "trinaest", "četrnaest", "petnaest", "šesnaest", "sedamnaest", "osamnaest", "devetnaest"); char numberstens = ("deset", "dvadeset", "trideset", "četrdeset", "pedeset"); //potencijalno 3 retka za prikaz char str_a; char str_b; char str_c; //bajt sati_y, mins_y; //sati i minute i pozicije za sate i minute linije bajt sati = rtc; if (sati > 12) ( sati = sati - ampm * 12; ) ako (sati< 1) { hours = hours + ampm * 12; } get_time(); //get the time from the clock chip byte old_mins = 100; //store mins in old_mins. We compare mins and old mins & when they are different we redraw the display. Set this to 100 initially so display is drawn when mode starts. byte mins; //run clock main loop as long as run_mode returns true while (run_mode()) { //check for button press if (buttonA.uniquePress()) { switch_mode(); return; } if (buttonB.uniquePress()) { display_date(); } get_time(); //get the time from the clock chip mins = rtc; //get mins //if mins is different from old_mins - redraw display if (mins != old_mins) { //update old_mins with current mins value old_mins = mins; //reset these for comparison next time mins = rtc; hours = rtc; //make hours into 12 hour format if (hours >12) ( sati = sati - 12; ) if (sati == 0) ( sati = 12; ) //podijeliti mins vrijednost u dvije odvojene znamenke int minsdigit = rtc % 10; bajt minsdigitten = (rtc / 10) % 10; //ako je min<= 10 , then top line has to read "minsdigti past" and bottom line reads hours if (mins < 10) { strcpy (str_a, numbers); strcpy (str_b, "PAST"); strcpy (str_c, numbers); } //if mins = 10, cant use minsdigit as above, so soecial case to print 10 past /n hour. if (mins == 10) { strcpy (str_a, numbers); strcpy (str_b, " PAST"); strcpy (str_c, numbers); } //if time is not on the hour - i.e. both mins digits are not zero, //then make first line read "hours" and 2 & 3rd lines read "minstens" "mins" e.g. "three /n twenty /n one" else if (minsdigitten != 0 && minsdigit != 0) { strcpy (str_a, numbers); //if mins is in the teens, use teens from the numbers array for the 2nd line, e.g. "fifteen" //if (mins >= 11 && min<= 19) { if (mins <= 19) { strcpy (str_b, numbers); } else { strcpy (str_b, numberstens); strcpy (str_c, numbers); } } // if mins digit is zero, don"t print it. read read "hours" "minstens" e.g. "three /n twenty" else if (minsdigitten != 0 && minsdigit == 0) { strcpy (str_a, numbers); strcpy (str_b, numberstens); strcpy (str_c, ""); } //if both mins are zero, i.e. it is on the hour, the top line reads "hours" and bottom line reads "o"clock" else if (minsdigitten == 0 && minsdigit == 0) { strcpy (str_a, numbers); strcpy (str_b, "O"CLOCK"); strcpy (str_c, ""); } }//end worknig out time //run in a loop //print line a "twelve" byte len = 0; while (str_a) { len++; }; //get length of message byte offset_top = (31 - ((len - 1) * 4)) / 2; // //plot hours line byte i = 0; while (str_a[i]) { puttinychar((i * 4) + offset_top, 1, str_a[i]); i++; } //hold display but check for button presses int counter = 1000; while (counter >0)( //provjeri pritisak gumba if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); ) delay(1); counter--; ) fade_down (); //ispis linije b len = 0; dok (str_b) (len++;); //dobijte duljinu poruke offset_top = (31 - ((len - 1) * 4)) / 2; i = 0; while (str_b[i]) ( puttinychar((i * 4) + offset_top, 1, str_b[i]); i++; ) //zadrži prikaz ali provjeri brojač pritisaka gumba = 1000; while (counter > 0)( if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); ) delay(1); counter--; ) fade_down() ; //ispiši liniju c ako postoji. duljina = 0; dok (str_c) (len++;); //dobijte duljinu poruke offset_top = (31 - ((len - 1) * 4)) / 2; i = 0; while (str_c[i]) ( puttinychar((i * 4) + offset_top, 1, str_c[i]); i++; ) brojač = 1000; while (brojač > 0)( //provjeri pritisak gumba if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); ) delay(1); counter- -; ) fade_down(); //drži zaslon praznim, ali prije ponovnog pokretanja provjeri pritiskanje gumba. brojač = 1000; while (brojač > 0)( //provjeri pritisak gumba if (buttonA.uniquePress()) ( switch_mode(); return; ) if (buttonB.uniquePress()) ( display_date(); ) delay(1); counter- -; ) ) fade_down(); ) /// poruka o pomicanju - trenutno se ne koristi - presporo. void scroll() ( char message = ("Hello There "); cls(); byte p = 6; //trenutni položaj u nizu byte chara = (0, 1, 2, 3, 4, 5); //chara iz niza int x = (0, 6, 12, 18, 24, 30); //xpos za svaki char bajt y = 0; //y pos // clear_buffer(); while (message[p] != "\ 0") ( //nacrtaj svih 6 znakova za (bajt c = 0; c< 6; c++) { putnormalchar(x[c],y,message[ chara[c] ]); //draw a line of pixels turned off after each char,otherwise the gaps between the chars have pixels left in them from the previous char for (byte yy = 0 ; yy < 8; yy ++) { plot(x[c] + 5, yy, 0); } //take one off each chars position x[c] = x[c] - 1; } //reset a char if it"s gone off screen for (byte i = 0; i <= 5; i++) { if (x[i] < -5) { x[i] = 31; chara[i] = p; p++; } } } } //display_date - print the day of week, date and month with a flashing cursor effect void display_date() { cls(); //read the date from the DS1307 byte dow = rtc; // day of week 0 = Sunday byte date = rtc; byte month = rtc - 1; //array of month names to print on the display. Some are shortened as we only have 8 characters across to play with char monthnames = { "January", "February", "March", "April", "May", "June", "July", "August", "Sept", "October", "November", "December" }; //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) { len++; }; byte offset = (31 - ((len-1)*4)) / 2; //our offset to centre up the text //print the name int i = 0; while(daysfull[i]) { puttinychar((i*4) + offset , 1, daysfull[i]); i++; } delay(1000); fade_down(); cls(); // print date numerals char buffer; 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={"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); //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); offset = 8; //offset prema središnjem tekstu ako ima 4 znaka) //ispis 2 znaka sufiksa puttinychar(suffixposx+offset, 1, suffix[s) ]); puttinychar(sufiksposx+4+pomak, 1, sufiks[s]); kašnjenje (1000); fade_down(); //ispiši naziv mjeseca //dobijte duljinu teksta u pikselima, na taj način ga možemo centrirati na zaslonu dijeljenjem preostalih piksela b2 i korištenjem toga kao pomaka len ​​= 0; dok(imena mjeseci) (len++;); pomak = (31 - ((len-1)*4)) / 2; //naš pomak za centriranje teksta i = 0; dok(imena mjeseca[i]) ( puttinychar((i*4) +pomak, 1, imena mjeseca[i]); i++; ) kašnjenje(1000); fade_down(); ) //prikaži izbornik za promjenu načina rada sata void switch_mode() ( //zapamti način rada u kojem se nalazimo. Koristimo ovu vrijednost ako idemo u način rada s postavkama, tako da se možemo vratiti iz načina s postavkama (6) u bilo koji način u kojem smo bili in. old_mode = clock_mode; char* modes = ("Basic", "Small", "Slide", "Words", "Setup"); byte next_clock_mode; byte firstrun = 1; //petlja čeka gumb (vrijeme nakon 35 petlje za povratak u mod 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; ) //ispiši strelicu i naziv trenutnog clock_modea u prvom retku i ispis sljedećeg clock_mode naziva u drugom redu char str_top; //strcpy (str_top, "-"); strcpy(str_top, načini); sljedeći_način_sata = način_sata + 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; ) kašnjenje(50); ) ) //pokretanje glavne petlje sata sve dok run_mode vraća pravi bajt run_mode() ( //ako je nasumični način rada uključen... provjerite sat kada mijenjamo način. if (random_mode) ( //ako je vrijednost sata u načinu promjene vrijeme = sati. zatim reurn false = tj. izlaz iz moda. if (change_mode_time == rtc) ( //postavi sljedeći nasumični način rada sata i vrijeme za njegovu promjenu set_next_random(); //izlaz iz trenutnog načina. return 0; ) ) / /else return 1 - nastavi raditi u ovom načinu rada return 1; ) //postavi sljedeći sat kada će sat promijeniti način rada kada je uključen nasumični način rada void set_next_random() ( //postavi sljedeći sat kada će se način rada sata promijeniti - trenutno vrijeme plus 1 - 4 sata get_time(); change_mode_time = rtc + nasumično (1, 5); //ako je change_mode_time sada preko 23, tada ga postavite na između 1 i 3 ujutro if (change_mode_time > 23) ( change_mode_time = nasumično (1 , 4); ) //postavite novi način rada sata clock_mode = random(0, NUM_DISPLAY_MODES + 1); //odaberite novi način rada slučajnog odabira sata ) //prikažite izbornik za promjenu postavki sata void setup_menu() ( char* set_modes = ( "Rndom", "24 sata", "Set", "Brght", "Exit"); if (ampm == 0) ( set_modes = ("12 Hr"); ) byte setting_mode = 0; bajt next_setting_mode; prvo pokretanje bajta = 1; //petlja čeka gumb (vrijeme nakon 35 petlji za povratak u mod 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; ) //ispiši strelicu i naziv trenutnog clock_modea u prvom redu i ispis sljedećeg clock_mode naziva u drugom redu char str_top; strcpy(str_top, set_modes); sljedeći_način_postavke = način_postavke + 1; if (next_setting_mode > NUM_SETTINGS_MODES) ( next_setting_mode = 0; ) bajt i = 0; dok(str_top[i]) ( putnormalchar(i*6, 0, str_top[i]); i++; ) prvo pokretanje = 0; ) kašnjenje(50); ) //odaberite prekidač načina(setting_mode)( slučaj 0: set_random(); break; slučaj 1: set_ampm(); break; slučaj 2: set_time(); break; slučaj 3: set_intensity(); break; slučaj 4: //izlaz iz prekida izbornika; ) //promijenite sat iz moda 6 (postavke) nazad na onaj u kojem je bio prije clock_mode=old_mode; ) //prebacivanje nasumičnog načina rada - odaberite drugi način rada sata svakih nekoliko sati void set_random())( cls(); char text_a = "Isključeno"; char text_b = "Uključeno"; byte i = 0; //ako je nasumični način uključeno, isključi ako (random_mode)( //isključi slučajni način rada random_mode = 0; //ispiši poruku na zaslonu while(text_a[i]) ( putnormalchar((i*6), 0, text_a[i] ) ; i++; ) ) else ( //uključi nasumični način rada. random_mode = 1; //postavljeni sat će se promijeniti set_next_random(); //ispiši poruku na zaslonu while(text_b[i]) ( putnormalchar((i * 6), 0, text_b[i]); i++; ) ) delay(1500); //ostavite poruku na sekundu ili tako nešto ) //postavite 12 ili 24 satni sat void set_ampm() ( // AM/ PM ili 24-satni način rada - okrenite bit (čini 0 u 1 ili 1 u 0 za ampm način) ampm = (ampm ^ 1); cls(); ) //promjena intenziteta zaslona void set_intensity() ( cls() ; byte i = 0; char text = "Bright"; while(text[i]) ( puttinychar((i*4)+4, 0, text[i]); i++; ) //pričekajte unos gumba dok ( ! buttonA.uniquePress()) ( traka razine (0,6,(intenzitet*2)+2,2); //prikaži razinu intenziteta kao traku while (buttonB.isPressed()) ( if(intensity == 15) ( intensity = 0; cls (); ) else ( intensity++; ) //ispis nove vrijednosti i = 0; while(text[i]) ( puttinychar((i*4)+4, 0, text[i]); i++; ) //prikaži razinu intenziteta kao traku razine (0,6,(intenzitet*2)+ 2,2); //promijenite postavku svjetline na zaslonima za (adresa bajta = 0; adresa< 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, ybar void levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x = 0; x < xbar; x++) { for (byte y = 0; y <= ybar; y++) { plot(x+xpos, y+ypos, 1); } } } //set time and date routine void set_time() { cls(); //fill settings with current clock values read from clock get_time(); byte set_min = rtc; byte set_hr = rtc; byte set_date = rtc; byte set_mnth = rtc; int set_yr = rtc; //Set function - we pass in: which "set" message to show at top, current value, reset value, and rollover limit. set_date = set_value(2, set_date, 1, 31); set_mnth = set_value(3, set_mnth, 1, 12); set_yr = set_value(4, set_yr, 2013, 2099); set_hr = set_value(1, set_hr, 0, 23); set_min = set_value(0, set_min, 0, 59); ds1307.adjust(DateTime(set_yr, set_mnth, set_date, set_hr, set_min)); cls(); } //used to set min, hr, date, month, year values. pass //message = which "set" message to print, //current value = current value of property we are setting //reset_value = what to reset value to if to rolls over. E.g. mins roll from 60 to 0, months from 12 to 1 //rollover limit = when value rolls over int set_value(byte message, int current_value, int reset_value, int rollover_limit){ cls(); char messages = { "Set Mins", "Set Hour", "Set Day", "Set Mnth", "Set Year"}; //Print "set xyz" top line byte i = 0; while(messages[i]) { puttinychar(i*4 , 1, messages[i]); i++; } delay(2000); cls(); //print digits bottom line char buffer = " "; itoa(current_value,buffer,10); puttinychar(0 , 1, buffer); puttinychar(4 , 1, buffer); puttinychar(8 , 1, buffer); puttinychar(12, 1, buffer); delay(300); //wait for button input while (!buttonA.uniquePress()) { while (buttonB.isPressed()){ if(current_value < rollover_limit) { current_value++; } else { current_value = reset_value; } //print the new value itoa(current_value, buffer ,10); puttinychar(0 , 1, buffer); puttinychar(4 , 1, buffer); puttinychar(8 , 1, buffer); puttinychar(12, 1, buffer); delay(150); } } return current_value; } void get_time() { //get time DateTime now = ds1307.now(); //save time to array rtc = now.year(); rtc = now.month(); rtc = now.day(); rtc = now.dayOfWeek(); //returns 0-6 where 0 = Sunday rtc = now.hour(); rtc = now.minute(); rtc = now.second(); //flash arduino led on pin 13 every second //if ((rtc % 2) == 0) { // digitalWrite(13, HIGH); //} //else { // digitalWrite(13, LOW); //} //print the time to the serial port - useful for debuging RTC issues /* Serial.print(rtc); Serial.print(":"); Serial.print(rtc); Serial.print(":"); Serial.println(rtc); */ }

Sada, da biste dovršili rad na uređaju, trebate izvršiti samo nekoliko jednostavnih operacija:


Sastavljanje programskog koda i njegovo daljnje učitavanje u memoriju mikrokontrolera će potrajati neko vrijeme, obično ne više od jedne minute. Uspješan završetak operacije bit će izviješten u Arduino IDE konzoli. Nakon čega ostaje samo ponovno pokrenuti Arduino pomoću gumba Reset na uređaju - jednostavan sat na LED matricama je spreman!

Spremni sat na Arduinu

Sat se podešava pomoću dva gumba. Uređaj podržava 12- i 24-satni format vremena, prikazuje datum i dan u tjednu te prikazuje vrijeme sa ili bez sekundi. Također je moguće promijeniti svjetlinu LED dioda.


Vjerojatno ćete htjeti dodati više značajki u budućnosti (na primjer, termometar) ili instalirati uređaj u tijelo vlastitog dizajna - dobri rezultati mogu se postići pomoću strojeva za lasersko rezanje. Ali sada možete sa sigurnošću reći da ste vlastitim rukama sastavili punopravni elektronički sat!

Nedavno se pojavila potreba da imam sat u kući, ali samo elektronski, jer ne volim satove, jer otkucavaju. Imam dosta iskustva u lemljenju i jetkanju krugova. Nakon pretraživanja interneta i čitanja neke literature, odlučio sam odabrati najjednostavniju shemu, jer mi ne treba sat s budilicom.

Odabrao sam ovu shemu jer je jednostavna napravite svoj sat

Počnimo, pa što nam je potrebno da bismo napravili sat vlastitim rukama? Pa, naravno, ruke, vještina (čak ni velika) u čitanju dijagrama strujnog kruga, lemilice i dijelova. Evo kompletnog popisa onoga što sam koristio:

10 MHz kvarc – 1 kom., mikrokontroler ATtiny 2313, otpornici 100 Ohm – 8 kom., 3 kom. 10 kOhm, 2 kondenzatora od 22 pF, 4 tranzistora, 2 gumba, LED indikator 4-bitni KEM-5641-ASR (RL-F5610SBAW/D15). Izveo sam instalaciju na jednostrani PCB.

Ali postoji nedostatak u ovoj shemi: pinovi mikrokontrolera (u daljnjem tekstu MK), koji su odgovorni za kontrolu pražnjenja, primaju prilično pristojno opterećenje. Ukupna struja je mnogo veća od maksimalne struje priključka, ali s dinamičkom indikacijom MK nema vremena za pregrijavanje. Kako bismo spriječili kvar MK, dodamo otpornike od 100 Ohma u krugove pražnjenja.

U ovoj shemi, indikator se kontrolira prema principu dinamičke indikacije, prema kojem se segmenti indikatora kontroliraju signalima iz odgovarajućih izlaza MK. Brzina ponavljanja ovih signala je veća od 25 Hz i zbog toga se čini da svijetljenje indikatorskih brojeva traje neprekidno.

Elektronički satovi izrađeni prema gornjoj shemi može prikazati samo vrijeme (sati i minute), a sekunde su prikazane točkom između segmenata, koji treperi. Za upravljanje načinom rada sata, u njegovoj strukturi nalaze se prekidači s tipkama koji kontroliraju podešavanje sati i minuta. Ovaj krug se napaja iz izvora napajanja od 5V. Tijekom izrade tiskane pločice u krug je uključena 5V zener dioda.

Budući da imam napajanje od 5 V, isključio sam zener diodu iz kruga.

Za izradu ploče, krug je primijenjen pomoću željeza. Odnosno, tiskani krug je ispisan na inkjet pisaču pomoću sjajnog papira; može se uzeti iz modernih sjajnih časopisa. Nakon toga je izrezan tekstolit potrebne veličine. Ispostavilo se da je moja veličina 36*26 mm. Takva mala veličina je zbog činjenice da su svi dijelovi odabrani u SMD paketu.

Ploča je urezana željeznim kloridom (FeCl3). Jetkanje je trajalo oko sat vremena, budući da je kupka s daskom bila na kaminu, visoka temperatura utječe na vrijeme jetkanja, u ploči nije korišten bakar. Ali nemojte pretjerivati ​​s temperaturom.

Dok je proces graviranja trajao, kako ne bih razbijao glavu i pisao firmware za rad sata, otišao sam na Internet i pronašao firmware za ovu shemu. Kako bljeskati MK također se može naći na Internetu. Koristio sam programator koji bljeska samo ATMEGA MK.

I konačno, naša ploča je spremna i možemo početi lemiti naše satove. Za lemljenje vam je potreban lemilo od 25 W s tankim vrhom kako ne biste spalili MK i ostale dijelove. Lemljenje provodimo pažljivo i po mogućnosti prvi put lemimo sve noge MK-a, ali samo odvojeno. Za one koji nisu upućeni, znajte da dijelovi izrađeni u SMD kućištu imaju lim na svojim terminalima za brzo lemljenje.

A ovako izgleda ploča sa zalemljenim dijelovima.

Sjećam se... Prije tridesetak godina šest pokazatelja bilo je malo blago. Svatko tko je tada mogao napraviti sat pomoću TTL logike s takvim indikatorima smatran je sofisticiranim stručnjakom u svom području.

Sjaj indikatora plinskog pražnjenja činio se toplijim. Nakon nekoliko minuta pitao sam se hoće li ove stare lampe raditi i htio sam nešto učiniti s njima. Sada je vrlo lako napraviti takav sat. Sve što trebate je mikrokontroler...

Budući da me u isto vrijeme zanimalo programiranje mikrokontrolera na jezicima visoke razine, odlučio sam se malo poigrati. Pokušao sam konstruirati jednostavan sat koristeći digitalne indikatore pražnjenja plina.

Svrha dizajna

Odlučio sam da sat ima šest znamenki, a da se vrijeme postavlja minimalnim brojem tipki. Osim toga, želio sam pokušati koristiti nekoliko najčešćih obitelji mikrokontrolera različitih proizvođača. Namjeravao sam napisati program u C-u.

Indikatori plinskog pražnjenja zahtijevaju visoki napon za rad. Ali nisam htio imati posla s opasnim mrežnim naponom. Sat je trebao biti napajan bezopasnim naponom od 12 V.

Budući da je moj glavni cilj bila igra, ovdje nećete pronaći opis mehaničkog dizajna ili crteže tijela. Ako želite, možete sami promijeniti sat prema svom ukusu i iskustvu.

Evo što sam dobio:

  • Prikaz vremena: HH MM SS
  • Indikator alarma: HH MM --
  • Način prikaza vremena: 24 sata
  • Preciznost ±1 sekunda po danu (ovisno o kvarcnom kristalu)
  • Napon napajanja: 12 V
  • Potrošnja struje: 100 mA

Dijagram sata

Za uređaj sa šesteroznamenkastim digitalnim zaslonom, multipleks način je bio prirodno rješenje.

Svrha većine elemenata blok dijagrama (slika 1) je jasna bez komentara. U određenoj mjeri, nestandardni zadatak bio je stvoriti pretvarač TTL razina u upravljačke signale indikatora visokog napona. Anodni pokretači izrađeni su pomoću visokonaponskih NPN i PNP tranzistora. Dijagram je posuđen od Stefana Knelera (http://www.stefankneller.de).

74141 TTL čip sadrži BCD dekoder i visokonaponski pokretač za svaku znamenku. Možda će biti teško naručiti jedan čip. (Iako ne znam da li ih itko više radi). Ali ako pronađete indikatore plinskog pražnjenja, 74141 bi mogao biti negdje u blizini :-). U vrijeme TTL logike praktički nije bilo alternative čipu 74141. Pa pokušajte ga negdje pronaći.

Indikatori zahtijevaju napon od oko 170 V. Nema smisla razvijati poseban krug za pretvarač napona, budući da postoji ogroman broj čipova pretvarača pojačanja. Odabrao sam jeftin i široko dostupan IC34063. Krug pretvarača gotovo je u potpunosti kopiran iz podatkovne tablice MC34063. Upravo mu je dodan T13 prekidač napajanja. Interni prekidač nije prikladan za tako visok napon. Koristio sam prigušnicu kao induktivitet za pretvarač. To je prikazano na slici 2; promjer mu je 8 mm, a duljina 10 mm.

Učinkovitost pretvarača je prilično dobra, a izlazni napon relativno siguran. Sa strujom opterećenja od 5 mA, izlazni napon pada na 60 V. R32 djeluje kao otpornik koji očitava struju.

Za napajanje logike koristi se linearni regulator U4. Na krugu i pločici postoji prostor za pomoćnu bateriju. (3,6 V - NiMH ili NiCd). D7 i D8 su Schottky diode, a otpornik R37 je dizajniran da ograniči struju punjenja prema karakteristikama baterije. Ako gradite satove samo iz zabave, neće vam trebati baterije D7, D8 i R37.

Konačni krug je prikazan na slici 3.

Slika 3.

Tipke za podešavanje vremena spojene su preko dioda. Stanje gumba provjerava se postavljanjem logičke "1" na odgovarajući izlaz. Kao bonus značajka, piezo emiter je spojen na izlaz mikrokontrolera. Da utišate to gadno škripanje, upotrijebite mali prekidač. Za to bi bio sasvim prikladan čekić, ali ovo je krajnja opcija :-).

Popis komponenti strujnog kruga, crtež PCB-a i dijagram rasporeda mogu se pronaći u odjeljku "Preuzimanja".

CPU

Gotovo svaki mikrokontroler s dovoljnim brojem pinova, čiji je minimalni potrebni broj naveden u tablici 1, može upravljati ovim jednostavnim uređajem.

Stol 1.
Funkcija zaključke
Prehrana 2
Kvarcni rezonator 2
Upravljanje anodama 6
Vozač 74141 4
Gumb za unos 1
Piezo emiter 1
Ukupno 16

Svaki proizvođač razvija vlastite obitelji i tipove mikrokontrolera. Položaj igala je individualan za svaku vrstu. Pokušao sam dizajnirati univerzalnu ploču za nekoliko vrsta mikrokontrolera. Ploča ima 20-pinsku utičnicu. S nekoliko premosnih žica možete ga prilagoditi različitim mikrokontrolerima.

Mikrokontroleri testirani u ovom krugu navedeni su u nastavku. Možete eksperimentirati s drugim vrstama. Prednost sheme je mogućnost korištenja različitih procesora. Radioamateri, u pravilu, koriste jednu familiju mikrokontrolera i imaju pripadajući programator i programske alate. Mogući su problemi s mikrokontrolerima drugih proizvođača, pa sam vam dao priliku da odaberete procesor iz svoje omiljene obitelji.

Sve specifičnosti uključivanja različitih mikrokontrolera prikazane su u tablicama 2...5 i slikama 4...7.

Tablica 2.
Freescale
Tip MC68HC908QY1
Kvarcni rezonator 12 MHz
Kondenzatori C1, C2 22 pF
Program freescale.zip
(pogledajte odjeljak "Preuzimanja")
postavke

Napomena: Otpornik od 10 MΩ spojen je paralelno s kvarcnim rezonatorom.

Tablica 3.
Mikročip
Tip PIC16F628A
Kvarcni rezonator 32,768 kHz
Kondenzatori C1, C2 22 pF
Program pic628.zip
(pogledajte odjeljak "Preuzimanja")
postavke Int. 4 MHz generator - I/O RA6,
MCLR ISKLJUČEN, WDT ISKLJUČEN, LVP ISKLJUČEN,
BROUT ISKLJUČEN, CP ISKLJUČEN, PWRUP ISKLJUČEN

Napomena: Mikrokrug mora biti rotiran za 180° u utičnici.

Tablica 4.
Atmel
Tip ATtiny2313
Kvarcni rezonator 12 MHz
Kondenzatori C1, C2 15 pF
Program attiny.zip
(pogledajte odjeljak "Preuzimanja")
postavke trg 8 MHz oscilator, RESET ON

Napomena: dodajte SMD komponente R i C na pin RESET (10 kΩ i 100 nF).

Tablica 5.
Atmel
Tip AT89C2051
Kvarcni rezonator 12 MHz
Kondenzatori C1, C2 22 pF
Program at2051.zip
(pogledajte odjeljak "Preuzimanja")
postavke --

Napomena: dodajte SMD komponente R i C na pin RESET (10 kΩ i 100 nF); spojite pinove označene zvjezdicama na sabirnicu napajanja +Ub preko SMD otpornika od 3,3 kOhm.

Kada usporedite kodove za različite mikrokontrolere, vidjet ćete da su vrlo slični. Postoje razlike u pristupu portovima i definiranju funkcija prekida, kao iu tome što ovisi o hardverskim komponentama.

Izvorni kod se sastoji od dva dijela. Funkcija glavni() konfigurira portove i pokreće mjerač vremena koji generira signale prekida. Nakon toga program skenira pritisnute gumbe i postavlja odgovarajuće vrijeme i vrijednosti alarma. Tamo se u glavnoj petlji trenutno vrijeme uspoređuje s budilicom i uključuje se piezo emiter.

Drugi dio je potprogram za rukovanje prekidima timera. Potprogram koji se poziva svake milisekunde (ovisno o mogućnostima mjerača vremena) povećava vremenske varijable i kontrolira znamenke na zaslonu. Osim toga, provjerava se status gumba.

Pokretanje kruga

Prilikom instaliranja komponenti i postavljanja, počnite s izvorom napajanja. Zalemite U4 regulator i okolne komponente. Provjerite napon od 5 V za U2 i 4,6 V za U1. Sljedeći korak je sastavljanje visokonaponskog pretvarača. Pomoću otpornika za podešavanje R36 postavite napon na 170 V. Ako raspon podešavanja nije dovoljan, malo promijenite otpor otpornika R33. Sada instalirajte U2 čip, tranzistore i otpornike kruga anode i digitalnog pogona. Spojite ulaze U2 na sabirnicu GND i spojite jedan od otpornika R25 - R30 u seriju na sabirnicu napajanja +Ub. Brojevi indikatora trebaju svijetliti na odgovarajućim mjestima. U posljednjoj fazi provjere kruga, spojite pin 19 mikro kruga U1 na masu - piezo emiter bi trebao dati zvučni signal.

Izvorne kodove i kompajlirane programe pronaći ćete u odgovarajućoj ZIP datoteci u odjeljku "Preuzimanja". Nakon učitavanja programa u mikrokontroler, pažljivo provjerite svaki pin u položaju U1 i postavite potrebne žice i zalemite kratkospojnike. Pogledajte gornje slike mikrokontrolera. Ako je mikrokontroler ispravno programiran i spojen, njegov generator bi trebao proraditi. Možete postaviti vrijeme i alarm. Pažnja! Na ploči ima mjesta za još jedan gumb - ovo je rezervni gumb za buduća proširenja :-).

Provjerite točnost frekvencije generatora. Ako nije unutar očekivanog raspona, malo promijenite vrijednosti kondenzatora C1 i C2. (Male kondenzatore lemiti paralelno ili ih zamijeniti drugima). Točnost sata trebala bi se poboljšati.

Zaključak

Mali 8-bitni procesori sasvim su prikladni za jezike visoke razine. C izvorno nije bio namijenjen malim mikrokontrolerima, ali za jednostavne aplikacije možete ga sasvim dobro koristiti. Asemblerski jezik je prikladniji za složene zadatke koji zahtijevaju kritična vremena ili maksimalno opterećenje CPU-a. Za većinu radioamatera prikladne su i besplatne i shareware ograničene verzije C prevodioca.

C programiranje je isto za sve mikrokontrolere. Morate poznavati hardverske funkcije (registri i periferija) odabranog tipa mikrokontrolera. Budite oprezni s operacijama s bitovima - jezik C nije prikladan za manipulaciju pojedinačnim bitovima, kao što se može vidjeti na primjeru originala kada je za ATtiny.

Jesi li gotov? Zatim se uključite u promatranje vakuumskih cijevi i gledajte...

...stari dani su se vratili... :-)

Napomena urednika

Potpuni analog SN74141 je mikro krug K155ID1, koji proizvodi Minsk Integral softver.
Mikrokrug se lako može pronaći na Internetu.

Koncept sata s velikim brojevima

Strukturno, uređaj će se sastojati od dvije ploče - jedna iznad druge. Prva ploča je matrica LED dioda koje formiraju sate i minute, druga je energetski dio (LED kontrola), logika i napajanje. Ovaj će dizajn sat učiniti kompaktnijim (bez kućišta, otprilike 22 cm x 9 cm, debljine 4-5 centimetara) + omogućit će zavrtanje matrice na drugi projekt ako nešto pođe po zlu.

Energetski dio će biti izgrađen na bazi UL2003 drajvera i tranzistorskih sklopki. Logično - na Atmega8 i DS1307. Napajanje: 220V - transformator; logika 5V (preko 7805), dio napajanja - 12V (preko LM2576ADJ). Tu će biti i poseban pretinac za 3V bateriju za autonomno napajanje sata realnog vremena - DS1307.

Razmišljam koristiti Atmega8 i DS1307 (planiram objesiti sat na strop, tako da u slučaju nestanka struje ne moram svaki put petljati po postavkama), međutim, izgled ploče će podrazumijevati mogućnost rada uređaja bez DS1307 (prvi put, a možda i zauvijek - kako će raditi).

Dakle, ovisno o konfiguraciji, algoritam rada satnog programa bit će sljedeći:

Atmega8– brojač vremena pomoću mjerača vremena. Rad u ciklusu bez pauza: prozivanje tipkovnice, podešavanje vremena (ako je potrebno), prikaz 4 znamenke i separatora.

Atmega8+DS1307. Rad u ciklusu bez pauza: prozivanje tipkovnice, podešavanje vremena DS1307 (ako je potrebno), očitavanje vremena sa DS1307, prikaz 4 znamenke i razdjelnik. Ili druga opcija - čitanje iz DS1307 na tajmeru, ostalo u petlji (još ne znam kako najbolje).

Segment se sastoji od 4 crvene LED diode povezane u seriju. Jedna znamenka – 7 segmenata sa zajedničkom anodom. Ne planiram odvajati segmente pomoću obrasca osmice, kao što se radi u konvencionalnim indikatorima.

Energetski dio sata

Energetski dio sata izgrađen je na UL2003 drajveru i tranzistorskim sklopkama VT1 i VT2.

UL2003 je odgovoran za kontrolu segmenata indikatora, tipke su za kontrolu znamenki.

Satni i minutni separator se upravlja odvojeno (signal K8).

Segmentima, bitovima i separatorom upravlja mikrokontroler primjenom pozitivnog potencijala (tj. primjenom +5V) na K1-K8, Z1-Z4.

Signali segmentima i bitovima moraju se isporučivati ​​sinkrono i s određenom frekvencijom kako bi se osigurao dinamički izlaz informacija (sati i minute).

Tranzistor BCP52 može se koristiti kao tranzistor VT1 (BCP53).

Shema pogonskog dijela sata s velikim brojevima

Tiskana pločica sedmosegmentnog indikatora za sat s velikim brojevima

Kao što sam ranije rekao, sat će se sastojati od dvije tiskane pločice - indikatorska ploča + logika i energetski dio.

Počnimo s dizajnom i proizvodnjom ploče s indikatorskim krugom.

Izrada tiskane pločice za sedmosegmentni indikator za sat s velikim brojevima

Tiskana pločica sedmosegmentnog indikatora za sat s velikim brojevima u "lay" formatu nalazi se na kraju članka, u priloženim datotekama. Možete pročitati o tehnologiji izrade tiskanih pločica LUT metodom.

Ako ste sve učinili ispravno, gotova PCB će izgledati otprilike ovako.

Gotova tiskana pločica sedmosegmentnog indikatora za sat s velikim brojevima

Montaža sedmosegmentnog indikatora

Budući da je indikatorska ploča dvostrana, prvo što treba učiniti je napraviti međuslojne prijelaze. To radim pomoću nogu nepotrebnih dijelova - provlačim ih kroz rupe i lemim s obje strane. Kad su svi prijelazi dovršeni, očistim ih ravnom, finom turpijom - ispadne vrlo uredno i lijepo.

Međuslojne bočice na indikatorskoj ploči

Sljedeći korak je zapravo sastavljanje indikatora. Zašto nam treba paket crvenih (zelenih, bijelih, plavih) LED dioda. Na primjer, uzeo sam ove.

Priprema za sastavljanje indikatora

Prilikom ugradnje dioda ne zaboravite da izrađujemo indikator sa zajedničkom anodom - tj. "+" diode moraju biti spojene zajedno. Uobičajene anode na PCB-u su veliki komadi bakra. Obavezno obratite pozornost na anodu s razdjelnom točkom.

Položaj anoda na tiskanoj ploči indikatora

Kao rezultat, nakon 2 sata mukotrpnog rada trebali biste dobiti ovo:

Indikator sa sedam segmenata

Digitalni dio sata

Sastavit ćemo digitalni dio sata s velikim brojevima prema sljedećoj shemi:

Dijagram sata s velikim brojevima

Krug sata je prilično transparentan, tako da ne vidim smisla objašnjavati kako radi. Tiskanu pločicu u *.lay formatu možete preuzeti na kraju članka. Imajte na umu da je tiskana ploča uglavnom dizajnirana za dijelove za površinsku montažu.

Dakle, baza elemenata koju sam koristio:

1. Diodni most DFA028 (bilo koji kompaktni za površinsku montažu će učiniti);
2. Regulatori napona LM2576ADJ u kućištu D2PAK, 78M05 u kućištu HSOP3-P-2.30A;
3. Tranzistorske sklopke BCP53 (kućište SOT223) i BC847 (kućište SOT23);
4. Atmega8 mikrokontroler (TQFP);
5. Sat realnog vremena DS1307 (SO8);
6. Napajanje 14V 1.2A iz nekog starog uređaja;
7. Ostali dijelovi su bilo koje vrste, prikladne veličine za ugradnju na tiskanu ploču.

Naravno, ako želite koristiti druge pakete dijelova, morat ćete napraviti neke promjene na PCB-u.

Obratite pozornost na vrijednosti otpora R3 i R4 - one moraju biti točno onako kako je naznačeno na dijagramu - ni više, ni manje. Ovo je učinjeno kako bi se osiguralo točno 12 V na izlazu regulatora napona LM2576ADJ. Ako i dalje ne možete pronaći takve vrijednosti otpornika, tada se vrijednost otpora R4 može izračunati pomoću formule:

R4=R3(12/1,23-1) ili R4=8,76R3

Sastavljanje digitalnog dijela. Verzija 1, bez DS1307

Ako ste se prilikom izrade tiskane pločice za sat pridržavali preporuka navedenih u, onda je suvišno podsjetiti da je prije montaže tiskanu pločicu potrebno izbušiti, ukloniti sve vidljive kratke spojeve na njoj i ploča mora biti prekrivena tekućim kolofonijem? Zatim počinjemo sastavljati sat.

Preporučam započeti sa sastavljanjem napajanja pa tek onda instalirati digitalni dio. Ovo je opća preporuka za samostalnu montažu uređaja. Zašto? Jednostavno zato što ako je napajanje sastavljeno s greškom, možete spaliti svu niskonaponsku elektroniku koja bi se trebala napajati ovim napajanjem.

Ako je sve učinjeno ispravno, napajanje bi trebalo odmah raditi. Provjeravamo sklop napajanja - mjerimo napon na ispitnim točkama.

Slika prikazuje ispitne točke na kojima treba provjeriti napon napajanja. Ako napon odgovara deklariranom, možete početi sastavljati digitalni dio sata. Inače, vršimo provjeru ugradnje i funkcionalnosti napojnih elemenata.

Ispitne točke i vrijednosti napona za napajanje sata

Nakon provjere napajanja, prelazimo na montažu digitalnog dijela sata - ugradnju svih ostalih elemenata na tiskanu pločicu. Provjeravamo kratke spojeve, posebno u nogama Atmega mikrokontrolera i UL2003 drajvera.

Ugradnja digitalnog dijela sata

Imajte na umu da sastavljamo sat BEZ instaliranja DS1307 sata stvarnog vremena, međutim, sve ožičenje ovog čipa mora biti dovršeno. U budućnosti, ako se ukaže potreba, to će nam uštedjeti vrijeme na modificiranju sata za drugu verziju, gdje će se i dalje koristiti zasebni, neovisni sat stvarnog vremena na DS1307.

Preliminarno testiranje mikrokontrolera ATMEGA8

Za provjeru ispravnosti i funkcionalnosti mikrokontrolera potrebno nam je:

1. Programer, na primjer.
2. za unutarkružno programiranje mikrokontrolera.
3. AVRDUDESHELL program.

Spojimo ploču sata na podatkovni kabel. Spojimo podatkovni kabel na programator. Programator za računalo na kojem je instaliran program AVRDUDESHELL. Ploča sata ne bi trebala biti spojena na napajanje od 220 V.

Uspješno očitavanje podataka iz mikrokontrolera programom AVRDUDESHELL

Ako se pojave problemi pri očitavanju osigurača, provjerite instalaciju - možda negdje postoji kratki spoj ili "nedostaje spoj". Još jedan savjet - možda je mikrokontroler u načinu programiranja male brzine, tada jednostavno prebacite programator u ovaj način rada (