Meglett a nagyjából kész ébresztőóra, a milis() használatával méri az időt. Így amennyire ez téved, annyira pontos. A (közel)teljes kód már 7 kbyte, azaz nem kevés.
Ide be is másolom, de nem rövid.
Kód: Egész kijelölése
#include <pitches.h>
#include "LiquidCrystal.h"
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
byte ora, perc, mp; //aktuális ido
byte EORA=22, EPERC=30, EMP=00; //ébresztési idő megadása
unsigned long ORA=22, PERC=30, MP=25; //pontos idő megadása
unsigned long ido; //milisec alapu idő a bekapcsolas óta
int melody[] = {
NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};
int noteDurations[] = {
4, 8, 8, 4,4,4,4,4 };
void alapkepernyo()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ido: : :");
lcd.setCursor(0, 1);
lcd.print("Vekker:");
lcd.setCursor(8, 1);
if (EORA<10)
{
lcd.print("0");
lcd.print(EORA);
}
else
{
lcd.print(EORA);
}
lcd.print(":");
if (EPERC<10)
{
lcd.print("0");
lcd.print(EPERC);
}
else
{
lcd.print(EPERC);
}
lcd.print(":");
if (EMP<10)
{
lcd.print("0");
lcd.print(EMP);
}
else
{
lcd.print(EMP);
}
}
void idomeghatarozas()
{
ido = millis();
//alapértékek kiszamolasa a millis() ertekebol
mp= ((ido+1000*MP) % 60000)/1000;
perc=((ido+mp+1000*MP+60000*PERC) % (60*60000))/60000;
ora= ((ido+mp+perc+1000*MP+60000*PERC+(60000*60*ORA)) % (24*60*60000))/(60000*60);
}
void ebresztes()
{
lcd.setCursor(0, 1);
lcd.print(" Ebreszto! ");
// zenelejatszas
for (int thisNote = 0; thisNote < 9; thisNote++)
{
int noteDuration = 1000/noteDurations[thisNote];
tone(10, melody[thisNote],noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
if (thisNote==8) {delay (1000); thisNote=-1;}
if (digitalRead(3)==0)
{
noTone(10);
lcd.setCursor(0, 1);
lcd.print(" Epp ideje!");
delay(2000);
thisNote=9;
alapkepernyo();
}
}
}
void idokiiras()
{
lcd.setCursor(14, 0);
if (mp<10)
{
lcd.print("0");
lcd.print(mp);
}
else
{
lcd.print(mp);
}
lcd.setCursor(11, 0);
if (perc<10)
{
lcd.print("0");
lcd.print(perc);
}
else
{
lcd.print(perc);
}
lcd.setCursor(8, 0);
if (ora<10)
{
lcd.print("0");
lcd.print(ora);
}
else
{
lcd.print(ora);
}
}
void beallitas() // ebreszto és óra beallitasa
{
byte sora, sperc, smp; //idoallitas segéd
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ebreszto allitas");
lcd.setCursor(0, 1);
lcd.print("Ora:");
delay (2000);
while(digitalRead(50)==1) //Ébresztő óra állítás
{
lcd.setCursor(10, 1);
if (EORA<10)
{
lcd.print("0");
lcd.print(EORA);
}
else
{
lcd.print(EORA);
}
if (digitalRead(51)==0)
{
EORA++;
delay (500);
if (EORA==24)
{
EORA=0;
}
}
}
delay (500);
lcd.setCursor(0, 1);
lcd.print("Perc:");
while(digitalRead(50)==1) //Ébresztő perc állítás
{
lcd.setCursor(10, 1);
if (EPERC<10)
{
lcd.print("0");
lcd.print(EPERC);
}
else
{
lcd.print(EPERC);
}
if (digitalRead(51)==0)
{
EPERC++;
delay (500);
if (EPERC==60)
{
EPERC=0;
}
}
}
delay (500);
sperc=perc; // Idő beállítása
sora=ora; sperc=perc;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ido beallitas");
lcd.setCursor(0, 1);
lcd.print("Ora:");
delay (2000);
while(digitalRead(50)==1) //Óra állítás
{
lcd.setCursor(10, 1);
if (sora<10)
{
lcd.print("0");
lcd.print(sora);
}
else
{
lcd.print(sora);
}
if (digitalRead(51)==0)
{
sora++;
delay (500);
if (sora==24)
{
sora=0;
}
}
}
if (sora>=ora) //ORA meghatározása a beírt beállításból
{ORA=ORA+(sora-ora);}
else
{ORA=ORA+(24-(ora-sora));}
delay (500);
lcd.setCursor(0, 1);
lcd.print("Perc:");
while(digitalRead(50)==1) //Perc állítás
{
lcd.setCursor(10, 1);
if (sperc<10)
{
lcd.print("0");
lcd.print(sperc);
}
else
{
lcd.print(sperc);
}
if (digitalRead(51)==0)
{
sperc++;
delay (500);
if (sperc==60)
{
sperc=0;
}
}
}
if (sperc>=perc) //PERC meghatározása a beírt beállításból
{PERC=PERC+(sperc-perc);}
else
{PERC=PERC+(60-(perc-sperc));ORA=ORA-1;}
delay(2000);
alapkepernyo();
}
void setup() {
pinMode(3, INPUT); //ebreszto leallitas gomb
pinMode(50, INPUT); //beallitas gomb
pinMode(51, INPUT); //ertekadas gomb
pinMode(30, OUTPUT); //+ tap
digitalWrite(30, HIGH);
pinMode(31, OUTPUT); //GND
digitalWrite(31, LOW);
pinMode(13, OUTPUT); //háttérvilágítás
digitalWrite(13, HIGH);
lcd.begin(16,2);
alapkepernyo();
}
void loop()
{
idomeghatarozas();
idokiiras();
if (digitalRead(50)==0)//beállítás
{
delay (500);
beallitas();
}
if (EORA==ora && EPERC==perc && EMP==mp) //ébresztő és óra egyezik
{
ebresztes();
}
}
Van azért pár hozzáfűznivaló is:
1. Két definiált nyomógombbal állítható mind az ébresztő, mind az óra. Az egyik gomb a kiválasztás, mit akarunk állítani, a másik gombbal pedig léptetjük az értéket.
2. A nyomógombok hirtelen ötlettől vezérelve - még ha nem is jó megoldás - a 30-31 pin-ről kapják a tápot, földet, amit a mikrovezérlő kapcsol, természetesen külső ellenállásokat használva. Bár ennek vannak veszélyei, cserébe könnyen letiltható lehet pl az adott gombok lenyomásából származó változás (később jól fog jönni) A két nyomógomb az állításhoz nálam a Mega panel esetén az 50-51-es lábhoz lett konfigurálva.
3. Az ébresztő leállítására az ext shield panelen is rajta lévő 3-as megszakítás lábon lévő gombot használtam.
Pár dolog amit még tovább kell fejleszteni, nincsen teljesen kész:
1. A másodperc jelenleg semmilyen szín alatt nem állítható, nullázható, ez egyelőre kimaradt, pedig fontos lehet pontos idő beállításánál. És ad egy problémát is jelenleg: azt a másodpercnyi időt, amennyi ideig végezzük a beállításokat hozzáadja a beállított időhőz képest. Azaz beállítok mondjuk 10.10 percet, de ha a beállítás eltartott 80 másodpercig, akkor már a megjelenő idő 10.11 lesz, mert átbillent egyszer a perc. Azaz a másodperccel van még mit kezdeni.
2. A milis() túlcsordulása sincsen még lekezelve, ez kb 4 sort igényel, hogy a túlcsordulás esetén az óra ugyanonnan folytassa, ahonnan előtte volt.
3. Az ébresztőóra állítást és a pontos idő állítást külön kell vennem, ne egybe történjen. Ehhez kell egy újabb nyomógomb, és nagyon minimális változtatás /átszervezés a progiban.
4. Ugyanígy az értékek fel-le léptetését is meg lehet oldani, jelenleg csak felfelé tudunk léptetni, és körbe kell forgatni, ha kisebb értéket szeretnénk beállítani. Ehhez kell egy plusz nyomógomb, és még egy lefele léptető rutin. Bár végülis így is működik.
5. Az LCD háttérvilágítást is lehet kapcsolgatni fogom, mert minek menjen, meg energiatakarékosság. Csak adott esetekben kell világítania (pl ébresztés, állítás). Végülis csak egy hordozható óra lesz
.
6. Ha a fentieket megcsinálom, akkor azt hiszem neki kell állni az optimalizálásnak, mert sokallom a méretét. Látok benne lehetőséget, de drasztikusat annyira nem 10-15% körülit, ez az én tudatlanságom oka valószínűleg.
De ezek csak a következő napokban, most 2-3 napra félre kell sajnos tennem
És amit még szeretnék:
- soros porton PC-ről kiküldött órát és ébresztőt fogadni, annak megfelelően beállítani (első érzésre ez jelentős kódnövelő tényező lesz..... Legalábbis ha byte-onként az üzeneteket fel kell dolgoznom)
- belevenni a naptárt is, ez egy nagyobb falat......
Ezt azthiszem már csak hétvégén.