Projekt časovače: Dny v týdnu, reálný čas,LCD a textové menu

Ahoj jsem zacatecnik v programovani C. Pohral jsem si s PWM spinani ledek vypisovanim na lCD, menu,merice teploty a dalsi akorat jsem jeste nezkousel zadne projekty zamerene na ovladani casem maximalne par minut ze to napocita a a splni se nejaka funkce. Rad bych nastavil realny cas a den v tydnu a podle vybrane polzky v menu a nastaveni casu zapnul v urcity cas zarizeni a vypnul zarizeni v urcitou dobu. Viz spodni blokove chema. Az bych porozumel programu chtel bych ovladat timto zpusobem vice vystupu z megy kazdy by mel zvlastni nastaveni zapinani a vypinani v urcty cas a denv tydnu melo by to byt neco jako takove ty hodiny co se daji do zasuvky a da se na nich nastavit cas den zapnuti/vypnuti ale da se rict ze by to melo trebas 10 zasuvek. Rad bych to vyuzil ke studiu funkce hodin neco se na tom naucil a rad bych to take realne pouzil :slight_smile: chtel bych se timto zeptat jestli jste nekdo neco podobneho nedelal nebo nevite jak na to stacil by mi nejaky zaklad nastaveni casu dnu v tydnu a nejake spinani ve vetsim bych si to uz dodelal. Byl bych vdecny za vase rady a materialy z kterych bych se poucil a neco dozvedel :slight_smile: pro zacatek bych rad pouzil Atmegu8 az nebude stacit pamet nebo porty mam pripravenou ATmegu 32.

taktokurvanahraj.okamzite.eu/upl … 520685.png

:arrow_right: administrator: přejmenováno z “Casovac dny v tydnu”

:arrow_right: administrator: příspěvek byl upraven

:arrow_right: administrator: přiloženy externí soubory

Udelat presne pocitani casu, aby se hodiny nezacaly rozchazet s realnym casem je docela narocne.
Pokud ale mas ve svem byte vyhled na zapad, nebydlis v prizemi na sidlisti, doporucil bych DCF modul.
V tomto pripade si prectes presny cas, ktery vysilaji z Nemecka a nerozchazi se.
Dale je nutne udelat vstup hodin. To znamena posouvani kurzoru doleva, doprava, sipkama nahoru/dolu menis hodnotu casu a Enterem potvrdit. Je tedy nutne mit 5 tlacitek a obsluhovat je.
Nebo je mozne taky postavit komunikaci pres seriovou linku a zadavat to z pocitace.
Rozhodni se pro neco, zacni na tom delat a kdyz se zaseknes, radi tady pomuzeme…

nejradsi bych ty tlacitka. ale jen tri sipku nahoru dolu a OK mozna jeste Back ze pokud by se nastavili desitky hodin zmacklo by se ok posunulo by se to na jednotky minut po zmacknuti OK dal na minuty. Pres USART bych chtel ovladat jen jednotlive vystupy kdyz bych byl trebas pryc tak pomoci USARTU to ovladat stim by nemel byt problem. Jinak jak rikam s hodinami nemam zkusenosti neznam uskali tohoto problemu tak se ptam :slight_smile: to rozchazeni casu je cca kolik sekund/minut napriklad za rok ? ja zatim pouzival jen internich 8MHz tak nevim kdybych pouzil trebas externikrystal jestli by se presnost nezvetsila… s DCF nemam take absolutne zadne zkusenosti ale rad bych pouzival trebas to spinani pokud se povede dokoncit i tam kde nemam normalne signal ani na mobil takze DCF asi pro zatim ne. Jeste jsem se chtel zeptat jestli by se mel nekde dat nastavit s hodinami den v tydnu tak jak bych ho mel naprogramovat napriklad ze by se po kazde pocitalo od pondeli a u kazdeho dne se pripocitalo 24Hodin a pak od znovu ? nebo jak by jste to udelali vy ?

Co jsem slysel od kolegu, tak se da levne dosahnout odchylky ±1s za mesic, ale nesmi se menit teplota. Potom lze samozrejme pouzit presne temperovane krystaly, kde frekvence nezavisi na teplote, ale cena je uplne nekde jinde. Tlacitka si samozrejme muzes udelat jak chces a tu funkci taky…

tak to mi vyhovuje 1s za mesic neni problem stejne letni a zimni cas planuju ze se bude zadavat manualne tak se to proste po kazde seridi. Jinak jaky krystal se pouziva pri takovychto hodinach aby ta odchylka byla cca tu 1s za mesic ?

Ani tak nejde o krystal, ale musel bys mu stabilizovat provozní teplotu (jak píše DragonSoul) - tj. termostat a vytápění. Tak raději počítej s mnohem nižší přesností a s možností cejchování přesnosti buď hw (paralelním kapacitním trimrem) nebo sw (přepočítávání odchylky, např. konfigurovatelný čítač který po určitém počtu tiků jeden tik přidá nebo ubere).

Dobrá metoda je adaptivní korekce přesnosti - jedno tlačítko zajistí vynulování sekund (dotažením na nejbližší celou minutu) a sw si podle uběhlé doby a vzniklé odchylky spočítá korekci o kterou upřesní rychlost hodin.

Robi sa to tak, ze pouzijes hociaky krystal. 1s za den sa samozrejme da dosiahnut aj s internym RC oscilatorom, len je to narocnejsie na kalibrovanie.

MCU bez problemov vie merat aj teplotu. Najlepsie pre kalibraciu pri chode na interny RC oscilator ak pouzijes mcu s meranim teploty na cipe (napr. Atmega88/168/328). Hodiny si “nejako” vhodne naprogramujes a spustis. Nechas ich v izbe a budes kazde 3/6/12 hodin robit záznam o priemernej teplote (napríklad priemer sekundovych vzoriek za vybrane obdobie) nacitaného z cidla a o odchýlke od skutocného casu. Cim dlhsi casovy interval si zvolis, tym presnejsie zmerias korekciu. Teplota sa aj v byte v priebehu dna meni, to riesis prave tym priemerovanim teploty za cely interval. Potom daj zariadenie napriklad do chladnicky na dolnu predpokladanu teplotu pouzitia a sprav to iste. Potom zas na nejaku vyssiu teplotu. Ak sa Ti podari mat solidny pocet vzoriek odchýlok tak pre pať až sedem teplôt z rozsahu v ktorom budes hodiny pouzvať, môžeš si dopočítať kalibračnú funkciu korekcie času. Funkcia zabezpečí aby sa pri danej priemernej teplote za stanovený čas pripočítalo/odpočítalo nejaké malé časové kvantum, napríklad milisekunda. A máš hodiny presného času. Funkčná závislosť zmeny frekvencie od teploty nebýva lineárna. To, ze pisem, ze sa da takto robit aj s RC oscilatorom este neznamena, ze Ti to aj odporucam. Islo mi o vysvetlenie principu. Cim teplotne stabilnejsi kmitaci prvok budes mat, tym menej musis od teploty korigovat a zasahy do casu budu relativne drobne. Ale korigovat musis tak ci tak, uz len z principu “nepresnosti” vyroby Xtalov. Teda ta presnost je slusna, ale na hodinach realneho casu ju je poznat.

napriklad v datasheete

tme.eu/sk/Document/96acf44e0 … hc49_v.pdf

vidis, ze teplotna zavislost v v sirokom rozsahu +/-30ppm, ale to je aj zakladna presnost Xtalu. Vyslednu frekvenciu dalej ovplyvnuju pridavne kapacity a to bud samotneho plosaku, alebo aj tie pridavne dve kapacity ktore sa davaju k oscilatorom v mcu. Miesto 18pF pouzi 22pF a hend vidis, ako sa vysledna frekvencia posunie. Zo skoro vsetkych hladisk ten posun bude sumak, ale minimalne z hladiska RTC to bude velmi vyznamne. Preto si mozes oscilator napriklad doladit tak, ze miesto tych kondenzatorov tam das kapacitne trimre a budes ich dosolichavat. Ale tie su zbytocne velke. Je daleko jednoduchsie a presnejsie zmerat odchylku pri danej teplote za 24h a potom tuto rovnomerne rozdelit tak, aby raz za X sekúnd si do RTC pripocital/odpocital tu jednu milisekundu.

pozri si

old.krystaly.cz/index_201c.htm

a parameter “tolerance kmitoctu”. Tak nejako moze vyzerat teplotna zavislot aj toho Tvojho Xtalu.

Z dovodu malej spotreby sa vyrabaju samostatne RTC cipy, aby zariadenie malo aj po zapnuti presny cas. Samotny procesor este nevie pri svojom behu dosiahnut nizku spotrebu specializovaneho svaba. Ta sa pohybuje pod 500nA. Preto sa k MCU dava takyto svabik, ktory je napajany cez jednu diodu z 5V od MCU a cez druhu diodu z 3V baterky, napriklad CR2032. Baterka pri odbere 500nA dlho vydrzi.
Svabik hned pepocita cas na sekundy, minuty, hodiny, dni, dni v tyzdni, mesiace a aj prestupne roky. MCU nemusi nic pocitat.

Tieto svabiky tiez obsahuju RAM, ktora je tou baterkou tiez zalohovana. PCF8583 obsahuje az 256B takejto RAM dostupnej po I2C zbernici. Do RAM si ukladaj napriklad v pravidelnych sekundovych intervaloch spatne cas. Po vypnuti a znovuzapnuti zariadenia vies s presnostou na sekundu, kedy bolo zariadenie vypnute. Vkladaj si tam cas poslednej casovej korekcie a tiez dolezite interne premenne, aby si mal informaciu o kontexte. Nezabudni, ze v nejakej aplikacii sa moze mcu len zresetovat nasledkom rusiveho impulzu. Ak predtym drzal zopnute nejake rele na zaklade povelu cez seriovu linku, po resete by ho vypol, co by mohol byt pruser. Preto, ak si tento stav zapise do RAM v RTC a po restarte si ho odtial nacita, zmena povelu na rele nemusi trvat ani 2ms, takze toto ani nemusi pripadny neziaduci restart “vsimnut”. To su velmi cenne vlastnosti zariadeni, ktore su mozu byt vystavene ruseniu.

tento je lacny 0,86E

tme.eu/sk/Document/809cb4b24 … 00_1_2.pdf

a obsahuje tiez sw kalibraciu oscilatora v rozsahu +/- 127ppm.
Okrem ineho aj jedinecne cislo napriklad pre identifikaciu celeho zariadenia.
Vie sledovat funkcnost baterky. Ved ak zariadenie niekde slape 5 rokov, nikto priebezne neskuma baterku. No a pri vypadku napajania by mohlo dojst k strate realneho casu a tym aj k znehodnoteniu nejakych vyrobnych procesov od casu zavislych, alebo vykurovania. Preto je fajn na dispecingu vidiet, alebo cez sirenku upozornit, ze baterka nie je v poriadku.

P.S. Kym som to dopisal, Panda mnohe z toho uviedol :slight_smile:

Postavit hodiny není problém. Postavit PŘESNÉ hodiny ale až taková legrace není. MCU ATmega8 jsem nechal běžet na IntRC 8 MHz a pro čítání času jsem použil externí hodinkový krystal 32768 Hz pro čítač 2 v asynchronním režimu. Přesnost záleží na použitém krystalu a spoustě dalších věcí. Specializované IO pro svou funkci v drtivé většině případů také potřebuje hodinkový krystal a v tom okamžiku je úplně jedno, jestli čas čtu z IO nebo si ho sám načítám. U ATmega8 při naprogramované pojistce CKOPT není potřeba ani použití externích kondenzátorů. Nicméně nakonec to stejně dopadlo tak, že jsem použil DCF modul a bylo vyřešeno. Ono načtení a dekódování tohoto signálu není nikterak složité. Člověk získá výhodu automatického seřizování času a automatický přechod letní/zimní čas. A to jsem si také původně říkal, nebudu se dělat s nějakým dekódováním DCF. Postavil jsem tedy hodiny s DCF řízením a získal jsem :

  1. Automatické nastavení času do 2 minut od zapnutí. (výpadku elrktřiny)
  2. Automatický posun času letní/zimní
  3. Automatické synchronizace času každou minutu (ve druhé verzi bez použití krystalu)

U DCF bývá často problém s nekvalitou signálu (průmyslové rušení). Někdy je dost problém najít místo s dobrým signálem, proto by měl být DCF přijímač raději oddělitelný od hodin (i kvůli možnosti natáčení antény, hodiny potřebujeme v určitém směru).

Ještě by byla zajímavé varianta pokud se poblíž hodin nachází nějaký domácí PC - jeho čas lze snadno synchronizovat z internetu a tak by mohl např. přes sériový port sesynchronizovat i hodiny, když se občas použije.

Tak potom moze byt pouzite aj toto:

tme.eu/sk/Document/50abdca53 … /gps01.pdf

za 9EUR + externa antena asi za 5EUR

a komunikovat sa s tym da priamo cez UART.

DCF je cim dalej (ako vzdialenejsie) tym horsie chytat. Na Zapadnom Slovensku je v mnohych lokalitach problem a cim dalej, tym je to horsie. Druzice predsa len “dosvietia” dalej. :slight_smile:

:arrow_right: administrator: přiloženy externí soubory
gps01.pdf (144 KB)

Proc se s tim srat.
Za tyhle penize to doma nepostavis.
conrad.cz/digitalni-tydenni-spinaci-minihodiny-gao.k616021?icc=Search&icn=616021
Edit: Beru zpet, nevsiml jsem si, ze pozadujes spinat vice zasuvek…

Je jasné že sériová elektronika vyjde většinou levněji než amatérská, ale kvůli penězům se to nedělá.

Jak jsem psal zatim jsem velkej zacatecnik venuju se programovani cca 3 mesice s zadnymi predchozimi zkusenostmi s programy, ve skole jsme brali vice mene jen HW ale o SW ani zminka. Dekuju vsem za pripominky a napady :slight_smile: Takze co jsem z toho pochopil zaklad je to udelat orezane a pak podle potreby dodelat nejakou z kalibraci bud DCF nebo manualne trimry nebo dalsi z moznosti :slight_smile: tak jdu pohledat nejake priklady z kterych bych pochopil jak vubec na hodiny a dam se do toho az to bude nejak tak v hromane nebo bude problem urcite se na vas obratim diky :slight_smile:

Jestli takhle začínáš tak bych Ti doporučoval nejdříve se vykašlat na vylepšení jako DCF nebo přesnost hodin, ale vzít běžný krystal a zkusit si nejdříve jakoukoliv jednoduchou verzi běžných a vylepšovat ji až postupně. Obvykle když se něco plánuje moc detailně (pokud s tím nejsou dostatečné zkušenosti) tak to stejně pak dopadne úplně jinak, je lepší zkoušet a vyvíjet za pochodu.

Např. si stanovit nejdříve základní elektroniku, jaký displej a tlačítka a krystal, nejdříve na tom rozblikat LED (výborný diagnostický bod), pak rozchodit zobrazování na displej, pak ovládání tlačítek, pak obsluha přerušení od časovače, inkrementace a zobrazení času a nakonec ovládací logiku.

Tak ja si zatim hraju stim Menu ted mi dela nejvetsi problem Sub menu ale to bych mel dat do konce tydne dohromady nebo to tak alespon planuju :slight_smile: dela mi problem pouzivani tlacitek pro zakladni menu sipky nahoru a dolu ktere funguji tak ze premazou LCD a posunou text o radku dolu nebo nahoru a ted kdyz neco ovladam ve switchy v jednotlivych case tak mi to vyskakuje zpet do menu ale uz mam plan jak na to snad to vyjde :slight_smile: hodiny bych chtel mit na LCD spustene a pokud sahnu nebo zacnu neco delat s tlacitky automaticky ot skoci do menu kde se bude dat nastavit cas spinani. pro tlacitka mam udelanou takovou knihvnu proti zakmitum atd… stema by problem byt nemel.ucim se tak za pochodu z cizich kodu a upravuju si je nebo cast pouziju a neco uz mi zustane v hlave a vyuziju to dal knizek sem precetl asi 5 nektere i vicekrat ale pro me kdyz jsem to nikdy nevidel to byl takovy nic nerikavajici text… ted kdyz vidim neco v kodu cemu nerozumim tak si to vyhledam a vyctu o tom co se da.

RTC je plne postacujuce mne robi odchylku za rok 2min ale kedze sa prestavuje manualne letny zimny cas tak 1min (teoreticky to ide doladit trimrom ale namam cas a presbnost mi staci), ak uz chcete hodinovy signal neviem ale GPS asi chytat pod strechov nejde, da sa pouzit RDS signal s FM radia spolahlivejsie ako DCF i ked narocnejsie

mam ted problem ze pokud dam OK a dostanu se do case jednotlivych polozek tak pak v Submenu nemuzu pouzivat sipky hodi me to zpet do Menu coz je logicke z toho programu jak funguje menu. pravdepodobne mam chybu ve viuziti voidu ze bych mel pouzit nejakou jinou vec ale nemuzu prijit na to jakou :frowning: zatim jsem se stim nesetkal nevedel by nekdo z vas jak na to ? jinak to snimani tlacitek uz mam udelane jinak tohle byl jen nejaky zaklad z netu.

[code] #include “template.h” // Code-Tamplate I use in my Projects
#include “lcd.h” // LCD HEADER FILE

#define UP PB0
#define DOWN PB1
#define OK PB2

void submenu1()
{
if((PIND & (1 << PD0)) == 0)
{
PORTD |= (1 << PD6); // rozsvieť LED
lcd_clrscr();
lcd_puts(“Menu1”);
lcd_gotoxy(0,1); // chod na poziciu x=4, y=0
lcd_puts(“Zapnuto”); // vypis text
}
if((PIND & (1 << PD1)) == 0)
{
PORTD &= ~(1 << PD6); // zhasni LED
lcd_clrscr();
lcd_puts(“Menu1”);
lcd_gotoxy(0,1); // chod na poziciu x=4, y=0
lcd_puts(“Vypnuto”); // vypis text
}
}

#define MAX_OPTIONS 6

// MENU Options

char menu_opt[MAX_OPTIONS][16] = { “MENU 1”, //jednotlive polozky v menu
“MENU 2”,
“MENU 3”,
“MENU 4”,
“MENU 5”,
“MENU 6”,
};

unsigned char item = 0, item_old=0;

void disp_opt(unsigned char);
void chk_btns(void);

int main(void){

DDRD = 0b11111000; // PD 0, 1, 2 jako vstupní
PORTD |= (1 << PD0)|(1 << PD1)|(1 << PD2); //zapnutí Pull-up na PD0, 1, 2

// LCD
lcd_init(LCD_DISP_ON);
lcd_clrscr();

// i/o Setup D.0-2 [PULLED UP]
//PREV NEXT SELECT BACK
IN(D,0); IN(D,1); IN(D,2); IN(D,3);
SET(D,0); SET(D,1); SET(D,2); SET(D,3);

// Initial LCD Text
lcd_putc('>');
lcd_putc(' ');
lcd_puts(&menu_opt[item][0]);
lcd_gotoxy(2,1);
lcd_puts(&menu_opt[item+1][0]);


while(1){
		chk_btns();	// Poll Buttons
}

return(0);
}

// Display Options / Update LCD Display
void disp_opt(unsigned char item){
if(item>item_old){
lcd_clrscr();
lcd_gotoxy(2,0);
lcd_puts(&menu_opt[item-1][0]);
lcd_gotoxy(0,1);
lcd_putc(’>’);
lcd_putc(’ ‘);
lcd_puts(&menu_opt[item][0]);
}
else if(item<item_old) {
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_putc(’>’);
lcd_putc(’ ');
lcd_puts(&menu_opt[item][0]);
lcd_gotoxy(2,1);
lcd_puts(&menu_opt[item+1][0]);
}
}

// Check Buttons
void chk_btns(void){
// PRIMITIVE BUTTON POLLING
// Will detect the FIRST ACTIVE BUTTON
// One Active Signal on a single press
// Will Ignore Buttons which are checked LATER if any previously checked Button is ACTIVE

if(READ(D,0)==LOW){	// Prev Option
	delay(BTBOUNCE);
	while(READ(D,0)==LOW){};
	item_old = item;
	item    -= item<1 ? 0 : 1;
	disp_opt(item);
	delay(BTBOUNCE);
}

if(READ(D,1)==LOW){	// Next Option
	delay(BTBOUNCE);
	while(READ(D,1)==LOW){};
	item_old = item;
	item    += item>(MAX_OPTIONS-2) ? 0 : 1;
	disp_opt(item);
	delay(BTBOUNCE);
}

if(READ(D,2)==LOW){ // OK Button

delay(BTBOUNCE);
while(READ(D,2)==LOW){};
delay(BTBOUNCE);
switch(item)
{
case 0:
submenu1(); // vlozeny Void
break;
case 1:
break;
case 2:
break;
}
}

}

[/code]

na kazde menu asubmenu musis mat polohu kurzora samostatne.Sipkami potom menis len hodnotu urcujucu polohu kurzora toho “menu”, v ktorom sa nachadzas.

polohu kurzoru to myslis jako CMDD nikdy sem se stim nesetkal nemel bys nejaky priklad ?

No - program se chová tak, jak má - resp. tak, jak je napogramováno. Po stisku OK (pro item=0) se provede funkce submenu1. Ta provede následující :

  1. Pokud je stisknuté tlačítko na pinu D0, tak rozsvítí LEDku, smaže displej, napíše na displej “Menu1”, přesune kursor displeje na pozici 0,1 (1. znak, 2. rádek - předpokládám) a napíše na displej “Zapnuto”

  2. Pokud je stisknuté tlačítko na pinu D1, tak zhasne LEDku, smaže displej, napíše na displej “Menu1”, přesune kursor displeje na pozici 0,1 (1. znak, 2. rádek - předpokládám) a napíše na displej “Vypnuto”

  3. Ukončí se a vrátí zpět.

V této funkci není žádné menu, je to jenom výpis položky - a pokud jsou stisknutá obě tlačítka (na D0 i na D1), tak se sice provedou kroky 1 i 2, ale tak rychle za sebou, že vlastně krok 1 ani nezpozoruješ. Submenu1 musíš nejprve naprogramovat…

Kromě toho, funkce chk_btns je původním programátorem zamýšlena tak, že v ní žádné menu být NEMÁ. Je to (už jenom podle názvu) pouhé načtení tlačítek a úprava položky item. Výsledek by pak měl být de-facto univerzálně použitelný pro veškerá menu (a submenu), která si naprogramuješ. Proměnné item a item_old jsou pak použitelné jako parametry pro volání této funkce. Není to úplně čisté řešení - čistší by bylo, kdyby funkce byla napsána jako void chk_btns(int *item, int *item_old), protože pokud máš více menu nebo submenu, měl bys tyto 2 položky mít uložené pro každé menu a do těchto proměnných pak hodnoty kopírovat a pro ukončení funkce zase kopírovat zpátky, což by se předáváním přes ukazatele na proměnnou zabezpečilo samo, protože by funkce chk_btns pracovala přes ukazatele přímo proměnnýma daného menu. Navíc tady jsou zamíchány 2 věci. Načtení tlačítek a provedení menu. Buď bys musel celou funkci psát pro každé menu a submenu zlášť, nebo by bylo úplně nejlepší, aby funkce chk_btns měla buď 3. parametr **void chk_btns(int *item, int item_old, char buttons) nebo byla napsaná jako char chk_btns(int *item, int *item_old). Pak by funkce buď přes ukazatel buttons nebo jednodušeji přes return hodnota vracela stisk tlačítek (OK, ESC, Back apod.)