Sari la conținut
ELFORUM - Forumul electronistilor

Ceas cu AT2313 rtc si senzor de temperatura


Postări Recomandate

Buna ziua, va prezint un proiect mai vechi, resuscitat din cauze de pandemie, un ceas cu attiny2313, DS1307 sau MCP9740, LM75 si afisaj led.
Ca afisoare am folosit OPD-S8022 de 20mm de diferite culori (rosu, verde, galben, albastru) si OPD-S15012 de 38mm de culoare rosie (celelalte culori nu "merg" din cauza tensiunilor mari de deschidere segment).

Ca RTC am folosit DS1307, mai nou am testat si cu MCP9740N dar numai pentru varianta cu attiny4313, iar ca senzor de temperatura am utilizat DS75/LM75.
La pornire afiseaza "buna" pentru 5 secunde dupa care trece in mod afisare timp si/sau temperatura in functie de optiunea aleasa: numai timp, timp 8 secunde + temperatura 2 secunde, numai temperatura.
Ceasul se potriveste din doua butoane, butonul Mode (Set) si butonul Up. La apasarea butonului Mode, circular, trecem prin potrivirea minutelor (cu resetarea secundelor), potrivirea orei, reglajul luminozitatii afisajului (in gama 0-19) si alegerea optiunii de afisare. Cu butonul Up se incrementeaza valoarea din meniul ales.

Apasarea simultana pe Up si Mode afiseaza versiunea de soft a ceasului "Cyxx" unde y poate lua doua valori, 2 pentru varianta at2313 si 4 pentru varianta at4313. Valori intre 01-49 pentru xx, inseamna ca rtc-ul este cu DS1307, iar valori intre 50-99 rtc-ul este cu MCP7940N. Astfel "C212" inseamna ceas construit cu at2313 si DS1307, varianta 12, iar "C450" inseamna ceas cu at4313 si MCP7949N, prima varianta.
Pentru ca, marimea conteaza, la attiny4313 am adaugat si modificarea automata a orei de vara/iarna.

In acest caz, meniul de potrivire se lungeste cu potrivire an, potrivire luna, potrivire data si alegerea DST, on sau off.
Afisarea temperaturii se face doar pentru temperaturi pozitive in cazul attiny2313, si este extinsa si pentru temperaturi negative in cazul utilizarii attiny4313.

Atasat sunt schemele si cablajele pentru ceas, afisajul de 20mm si cel de 38mm proiectate in Eagle ca si fisierele hex/bin si eep pentru variantele de procesor si rtc.

ceas_attiny2313-4313_firmware.zip ceas_attiny2313-4313_eagle.zip

Link spre comentariu
  • Răspunsuri 39
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Top autori în acest subiect

Imagini postate

Cum spuneam, la pornire afiseaza "buna" pentru 5 secunde, dupa care trece in mod afisare timp, in functie de optiunea aleasa (implicit este optiunea de afisare timp, 8 secunde, alternant cu temperatura, 2 secunde). La modelul at2313 din lipsa de spatiu, a trebuit sa renunt la afisarea temperaturilor negative (oricum ar trebui sa fie un ceas de interior), la modelul cu at4313, pentru ca unul din ceasuri a fost montat in exterior, mi s-a parut util sa extind temperatura si pentru domeniul negativ.

ceas_attiny2313-4313_aa.thumb.jpg.41d69de4a891f9b8092d17a30331401f.jpg

Pentru potrivire se folosesc cele doua butoane Mode si Up, Mode este folosit pentru trecerea prin meniu iar Up pentru potrivirea valorilor respective.

Am folosit diferite afisoare (rosii, verzi, galbene, albastre) care aveau diferente mari de luminozitate intre ele, asa ca am fost nevoit sa fac si un reglaj de luminozitate, "bright" care poate lua valori intre 0 pentru luminozitate minima si 19, luminozitate maxima. Pe timp de noapte, intre orele 22:00 si 06:00, luminozitatea se reduce automat la un sfert.

ceas_attiny2313-4313_b4.thumb.jpg.c77fe838f71e9eb7aa1f0094b72947f8.jpg

Suplimentar, la modelul cu at4313 avem si potrivirea anului, lunii, datei si daca vrem ca DST-ul sa fie activ sau nu. Data maxima va fi in  functie de luna si an (bisect sau nu) si poate avea valorile de 28, 29, 30 sau 31.

In timpul afisarii timpului sau potrivirii datei, daca DST-ul este activ si ora este de vara, se aprinde punctul zecimal din dreapta afisajului.

Pentru afisarea datei se apasa pe butonul Up si data va fi afisata pentru 2 secunde.

ceas_attiny4313_c3.thumb.jpg.d484e48231279349977ca532babfe6f7.jpg

In orice moment, apasarea simultana pe butoanele Mode si Up va afisa versiunea ceasului:

ceas_attiny2313-4313_ver.thumb.jpg.da5391478228fd5b58c43346928ffc43.jpg

 

Editat de Marin1960
Link spre comentariu

Cateva cuvinte despre senzorul de temperatura LM75.

Din lipsa de spatiu a procesoarelor folosite, am ales acest senzor, pentru ca m-am legat pe sarmele existente: SCL si SDA. Un alt motiv a fost acela ca nu trebuie nici un cuvant de configurare daca vrei sa citesti doar temperatura. Cu alte cuvinte, cod minim pentru aflarea temperaturii (mai ales ca pe mine ma interesa doar partea intreaga, fara zecimale).

Cum, indiferent de producator, acuratetea temperaturii este in jur de ±2ºC, am ales produsul cel mai ieftin, 2 lei si ceva, LM75B-nxp.

Pentru cei care vor precizie ridicata, se poate modifica offset-ul de temperatura din fisierul eep. In acest fisier, varianta at4313, configuratia parametrilor din eeprom este urmatoarea: bright (0-19), option(0-2), temp_offset(254-2), DST(0-1).

Modificand temp_offset la 254, inseamna ca temperatura afisata va fi temperatura citita minus 2.

In timp ce scriam, mi-am dat seama ca in versiunile pe care le-am pus mai sus, temp_offset poate fi modificat doar in intervalul 0-2, orice alta valoare determina revenirea la valoarea implicita 0.

Am atasat o versiune corectata si pentru temp_offset negativ.

ceas_attiny4313_update.zip

Link spre comentariu

Temperatura afisata este stabila, doar ca, fata de un 18B20, arata cam cu 1-2 grade mai mult. Asta este si motivul pentru care am pus un offset de temperatura. Voiam ca cele doua termometre (al ceasului si un altul cu 18B20) sa arate la fel. Cum 18B20 are acuratetea de ±0,5ºC fata de ±2ºC la LM75, mai multa incredere am avut in senzorul 18B20. Am facut masuratori cu diferite exemplare, si LM 75 are tendinta de a arata mai mult (cel putin cele din seria mea).

Link spre comentariu

La proiectul asta, cel mai mult m-a chinuit functia DST.
De-a lungul timpului, am modificat functia asta de nenumarate ori, de aceea o postez, ca potential start pentru cineva interesat.
Comentariile si explicatiile din functie sper ca o vor face inteleasa.
Functia este scrisa in Bascom.

'Zeller's Rule (http://mathforum.org/dr.math/faq/faq.calendar.html)
'day=(Date+(13Month-1)/5+YY+YY/4+CC/4-2CC)Mod7
'day este numarul zilei din saptamana (0=du,1=lu,2=ma,3=mi,4=jo,5=vi,6=sa)
'Date este data
'Month este luna in format 1=Mar,2=Apr...8=Oct,9-Noi,10=Dec,11=Ian,12=Feb
'YY ultimele doua cifre din an 2019 => YY=19
'CC primele cifre din an 2019 => CC=20
'pentru Martie, secol 21, avem ultima duminica=31-(33-(YY+YY/4))Mod7
'pentru Octombrie, secol21, avem ultima duminica=31-(15-(YY+YY/4))Mod7
'Ds(2) ora
'Ds(4) luna
'Ds(5) data
'Ds(6) an
Is_dst:
Dst_led = Led_off : Dst = 0
If Dst_flag = 0 Then Return
C1 = 0 : C2 = 0 : C3 = 0 : C4 = 0 : C5 = 0 : C6 = 0
Temp = Ds(6) / 4 : Temp = Temp + Ds(6)
Ud3 = Temp - 2 : Ud3 = Ud3 Mod 7
Ud10 = Temp + 16 : Ud10 = Ud10 Mod 7
'conditia0, ultima duminica din martie si octombrie
Ud3 = 31 - Ud3
Ud10 = 31 - Ud10
'conditia1, conditia ultimei duminici din martie ora>3
Temp = 0
If Ds(4) = 3 And Ds(5) = Ud3 Then Temp = 1
If Temp = 1 And Ds(2) >= 3 Then C1 = 1
'conditia2, conditia lunii martie (ok)
If Ds(4) = 3 And Ds(5) > Ud3 Then C2 = 1
'conditia3, conditia dintre martie si octombrie (ok)
If Ds(4) > 3 And Ds(4) < 10 Then C3 = 1
'conditia4, conditia lunii octombrie (ok)
If Ds(4) = 10 And Ds(5) < Ud10 Then C4 = 1
'conditia5, conditia ultimei duminici din octombrie (ok)
Temp = 0
If Ds(4) = 10 And Ds(5) = Ud10 Then Temp = 1
If Temp = 1 And Ds(2) < 4 Then C5 = 1
'conditia6, conditia lunii octombrie ora<4(ok)
If C5 = 1 And Ora_change = 1 Then C6 = 1
'calcul dst
I = C1 Or C2 : J = C3 Or C4 : Temp = I Or J
If Temp = 1 Or C6 = 1 Then Dst_led = Led_on
If Temp = 1 Or C5 = 1 Then Dst = 1
'nu schimba ordinea if-urilor!
Change_time:
If Dst = 0 And Ora_change = 2 Then
   Ora_change = 0
End If
If Dst = 1 And Ora_change = 0 Then
   Ora_change = 1
   Incr Ds(2)
   Gosub Ds_send_ora
End If
If Dst = 0 And Ora_change = 1 Then
   Ora_change = 2
   Decr Ds(2)
   Gosub Ds_send_ora
End If
Return

 

Link spre comentariu

Erata: dintr-o regretabila eroare, in antetul functiei dst, formulele de calcul al ultimei duminici din Martie, respectiv Octombrie sunt gresite.

Din fericire codul propriu zis este in regula. Liniile de comentariu 8 si 9 se vor modifica astfel:

'pentru Martie, secol 21, avem ultima duminica=31-((YY+YY/4)-2)Mod7
'pentru Octombrie, secol21, avem ultima duminica=31-(16+(YY+YY/4))Mod7

Am testat codul din 2019 pana in 2099 si pare in regula (mai putin pentru anii 2000 si 2001). Pentru a pastra codul cat mai compact am preferat sa nu iau in considerare cele doua cazuri.

Atasez si programelul de testare care este rulat pe un arduino nano (test_ud_v1.ino cu modificarea pentru cele doua cazuri).

test_ud.ino

test_ud_v1.ino

Editat de Marin1960
Link spre comentariu

Nu ştiu dacă ajută sau nu, în computerul de bord făcut pentru fosta mea Corsa aveam aşa calculul pentru ziua din săptămînă.

    // Calculate initial day of the week; Jan 1st 2005 = day 1, repeats each 12 years
    rtc.dow = 1 + ((rtc.year % 12) + 6) % 7; // 1 + 0...6!
    // Calculate days passed from year's beginning
    days = 0;
    for (i=1;
         i<rtc.month;
         i++
        )
    {
      // Add whole month to the number of days
      days += TOP_DAY[i];
    }
    // Add extra day if leap year
    if ((rtc.year % 4 == 0) && (rtc.month > 2)) days += 1;
    // Add number of days from current month
    days += rtc.day;
    // Calculate day of the week
    rtc.dow = (rtc.dow + (days % 7)) % 7 + 1;

 

Pentru zilele din lună e un look up table:

// Days for each month
const flash unsigned char TOP_DAY[13] =
{
  0,  // unused, month is 1...12
  31, // January
  28, // February (add one day in leap years)
  31, // March
  30, // April
  31, // May
  30, // June
  31, // July
  31, // August
  30, // September
  31, // October
  30, // November
  31  // December
};

 

Editat de ratza
Am uitat tabela :(
Link spre comentariu

metoda rapida de calcul a zilei din saptamana dupa data:
(merge de la 2000 la 2099)

ex.:  14 februarie 2010

1. se iau ultimile 2 cifre ale anului  (=10 )
   si se adauga la rezultat un sfert din valoarea lor  ( 10:4=2,5 ;  10+2=12 )
   daca restul este 0 iar luna este ianuarie sau februarie se mai scade 1 de la rezultat.
2. luati codul corespunzator pentru luna ( februarie = 2 )
        luna             cod
    01    ianuarie      6
    02    februarie    2
    03    martie        2
    04    aprilie         5
    05    mai              0
    06    iunie            3
    07    iulie              5
    08    august          1
    09    septembrie  4
    10    octombrie    6
    11    noiembrie     2
    12    decembrie    4
3. se ia numarul zilei ( zi = 14 )
4. se aduna rezultatele de la punctele 1, 2 si 3 intre ele
   ( 12+2+14=28 )
5. scadeti multipli de 7 pana cand restul e mai mic decat 7
   ( 17 - 7 = 10.  10 - 7 = 3 )
6. Acest numar corespunde cu ziua saptamanii.
    0 = duminica
    1 = luni
    2 = marti
    3 = miercuri
    4 = joi
    5 = vineri
    6 = sambata
    7 = duminica

7. pentru anii 1500 se adauga 9    
   pentru anii 1600 se adauga 7     
   pentru anii 1700 se adauga 5    
   pentru anii 1800 se adauga 3
   pentru anii 1900 se adauga 1
   pentru anii 2000 se adauga 0
   pentru anii 2100 se adauga -2
   pentru anii 2200 se adauga -4
   pentru anii 2300 se adauga -6

 

 

metoda merge foarte bine. Am si programas facut dar e in asm pentru Z80

Editat de cimitavita
Link spre comentariu

Cu alte cuvinte, pentru secolul 21, avem dow = (Date + YY + YY/4 + Mcode)%7, unde YY=ultimele doua cifre din an (2018 => YY=18), Date este data din luna (1...28/29/30/31), Mcode, codul corespunzator de la punctul 2.

Am verificat codul si, intr-adevar "merge" foarte bine in intervalul 2000-2099.

In aplicatia mea am nevoie doar de o anume zi din luna si anume pentru data de 31 Martie, respectiv Octombrie. Daca stiu ce zi este in acea data, in functie de an, prin scaderea zilei din 31, aflu data pentru ultima duminica din luna respectiva a acelui an, necesara pentru calculul dst.
Exemplu pentru Martie 2018, data de 31 Martie cade intr-o sambata (31+18+4+2)%7=6, (numerotarea 0=duminica, 1=luni, 2=marti, etc) si ultima duminica va fi in data de 31-6=25 Martie (la fel pentru Octombrie).
Cei doi algoritmi sunt similari, al tau este chiar mai bun pentru ca valorile calculate pentru dow, sunt pozitive pe tot intervalul, la mine pentru primii doi ani din secol devin negative. Cred ca voi utiliza pentru urmatoarele versiuni ale ceasurilor mele, algoritmul tau. Multumesc!

PS. Am lucrat si eu cu Z80 acu mai bine de 25 de ani si cu fratele mai mare Z80180 acu cativa ani... ce vremuri:)

Obs. Vezi ca la punctul 5, ar trebui 28%7=0 si ziua este duminica, nu miercuri.

Editat de Marin1960
Link spre comentariu

mi-am facut si eu un ceas dar cu DS3231. Senzorul de temperatura din DS3231 arata in plus cu 1,5 grade din cauza ca chipul se incalzeste asa ca am folosit LM73. In plus LM73 are o precizie de 0,03 grade si vine etalonat din fabrica. Am LM73 din mai multe loturi si daca carcasele lor sunt alipite una de alta, diferenta de temperatura aratata e mai mica de 0,1 grade. DS3231 foloseste numere in format BCD si am facut un programas care calculeaza denumirea zilei in functie de data:

 

calcul_zi_saptamana.asm

Link spre comentariu

Codul postat (calcul_zi_saptamana.asm) vad ca e scris pentru AVR, desi eu, nu stiu de ce, am ramas cu impresia ca este scris pentru Z80!

Elegant cod si bine comentat! Felicitari!

Cat despre senzorul de temperatura, pentru ca l-am pus direct pe cablaj, imi arata o temperatura putin mai mare (nu am verificat cu cat) din cauza incalzirii cablajului de la afisaj si de la regulatorul 7805. Din acest motiv, foarte aproape de terminalele care sunt la masa, am lipit o tabla de Cu de 0,7mm grosime, 3mm latime si 30mm lungime ca radiator si stabilizator termic ca in imaginea de mai jos:

LM75_1.thumb.jpg.4882de0417659ca2b05ed580e886f0d1.jpg

Temperatura este stabila si foarte aproape de un termometru "etalon" cu 18B20.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări