60 nap alatt Arduino #16 - LCD-ből óra
Hónap hossz átszámítás egyszerűsítése:
Ez a kész kódban 140 byte rövidülés a többszörös IF helyett.. De többet kellett gépelni:)
Kód: Egész kijelölése
switch (ho) {
case 1:
honaphossz = 31;
break;
case 2:
// szokoev van?
// Szökoévek a következok: minden néggyel osztható év, kivéve a százzal is oszthatókat.
// Szökoévek viszont a 400-zal osztható évek. Vagyis a századfordulók évei közül
// csak azok szökoévek, amelyek 400-zal is oszthatók.
// http://hu.wikipedia.org/wiki/Sz%C3%B6k%C5%91%C3%A9v
honaphossz = 28;
if( (ev%4)==0 ) // neggyel oszthato ev
{
if( (ev%100)!=0 ) {// nem oszthato 100-zal akkor egyertelmuen szokoev
honaphossz = 29;
} else {
if( (ev%400)==0 ) { // ha 400-zal oszthato akkor szokoev
honaphossz=29;
} // neggyel oszthato?
}
}
case 3:
honaphossz = 31;
break;
case 4:
honaphossz = 30;
break;
case 5:
honaphossz = 31;
break;
case 6:
honaphossz = 30;
break;
case 7:
honaphossz = 31;
break;
case 8:
honaphossz = 31;
break;
case 9:
honaphossz = 30;
break;
case 10:
honaphossz = 31;
break;
case 11:
honaphossz = 30;
break;
case 12:
honaphossz = 31;
break;
}
kicsit előre szaladtam
Sziasztok!
Én csak a #14-es leckénél tartok, de valamiért ma felmerült bennem a kérdés, hogy milyen lehet-e órát programozni a arduino EXT1 egységgel.
TávIR-től rendeltem, a tanfolyamhoz.
arduino.cc ről van programozóm, 1,0,2 verzióval.
A kód hamarabb megvolt, minthogy egy a fórumot megtaláltam volna
Íme a program kód:
Aztán gondolkodtam, és rájöttem, hogy ha //k = i + 1000; // k változo beállítjuk 1 mp-cel későbbre, ennek a számnak jelentősége van az óra pontosságára...
// - vel oldom meg a léptetést, akkor nem lesz pontos, mert pontosan tudni kellene hogy a kiírással és a helyi-érték beállítással, számítással mennyi idő tellik el, és ennek függvényében korrigálni az k = i + 1000; ezres értéket.
Folyamatosan fut a program, 25 perce, és most ~10 másodpercet késik egy stopperhez képes...
De tanulságos
Elolvastam a korábbi hozzászólásokat, látom van erre kiforrotabb módszer is, jó programozási gyakorlat volt.
Megvárom azt a leckét, ahol ez lesz, és megcsinálom úgy is
Köszönöm!
Lóri
Én csak a #14-es leckénél tartok, de valamiért ma felmerült bennem a kérdés, hogy milyen lehet-e órát programozni a arduino EXT1 egységgel.
TávIR-től rendeltem, a tanfolyamhoz.
arduino.cc ről van programozóm, 1,0,2 verzióval.
A kód hamarabb megvolt, minthogy egy a fórumot megtaláltam volna
Íme a program kód:
Kód: Egész kijelölése
#include <LiquidCrystal.h> / LCD meghívása
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // TávIR-es panel bekötés, átböngészve a huzalozást a nyákon :)
int led = 13; // hátér villágítás port
int mp_x = 7; // helyiérték helyes kijelzéshez a mp x koordinátája
int perc_x = 4; // helyiérték helyes kijelzéshez a perc x koordinátája
int ora_x = 2; // helyiérték helyes kijelzéshez a ora x koordinátája
long i, j, k, l; // ido tellésének változói, és az l egy sebesség index
int ora, perc, mp; // idő változok
void setup()
{
pinMode(led, OUTPUT); // háttérvillágítás port kimenetre kapcsolás
digitalWrite(led, HIGH); // LCD háttérvillágítás felkapcsolás
lcd.begin(16, 2); // LCD definiálás
lcd.setCursor(0, 0); // cursor pozicóba állítás
lcd.print("ido:"); //"ido:" felírat kiirás egyszer
mp = 0; // változo nullázás
perc = 0; // változo nullázás
ora = 0; // változo nullázás
}
void loop ()
{
i = millis(); // i változonak átadjuk az aktuélis miilis() értékez
j = millis(); // i változonak átadjuk az aktuélis miilis() értékez
k = i + 1000; // k változo beállítjuk 1 mp-cel későbbre, ennek a számnak jelentősége van az óra pontosságára...
while ( k > j ) // ha k nagyobb lesz mint j
{
j = millis(); // j aktualizálás
l++; // sebbeség index generálás
}
mp++; // eltelt egy másodperc
if ( mp > 59 ) // mp perc váltás
{
mp = 0;
perc++;
}
if ( perc > 59 ) // perc óra váltás
{
perc = 0;
ora++;
}
if ( ora > 9 ) { ora_x = 0; } else { ora_x = 1; } // helyiérték kijelzés, eltolás az LCD-n
if ( ora == 0 ) { lcd.setCursor(0, 1); lcd.print(" "); }
lcd.setCursor(ora_x, 1); // helyiérték beállítás
lcd.print(ora); // ora érték kiirás
if ( perc > 9 ) { perc_x = 3; } else { perc_x = 4; } // helyiérték kijelzés, eltolás az LCD-n
if ( perc == 0 ) { lcd.setCursor(3, 1); lcd.print(" "); }
lcd.setCursor(perc_x, 1); // helyiérték beállítás
lcd.print(perc); // perc érték kiirás
if ( mp > 9 ) { mp_x = 6; } else { mp_x = 7; }// helyiérték kijelzés, eltolás az LCD-n
if ( mp == 0 ) { lcd.setCursor(6, 1); lcd.print(" "); }
lcd.setCursor(mp_x, 1); // helyiérték beállítás
lcd.print(mp); // mp érték kiirás
lcd.setCursor(9, 1); // sebesség index cursor beállítása
lcd.print(l); // sebesség index kiirás
l = 0; // sebesség index nullázás
}
// - vel oldom meg a léptetést, akkor nem lesz pontos, mert pontosan tudni kellene hogy a kiírással és a helyi-érték beállítással, számítással mennyi idő tellik el, és ennek függvényében korrigálni az k = i + 1000; ezres értéket.
Folyamatosan fut a program, 25 perce, és most ~10 másodpercet késik egy stopperhez képes...
De tanulságos
Elolvastam a korábbi hozzászólásokat, látom van erre kiforrotabb módszer is, jó programozási gyakorlat volt.
Megvárom azt a leckét, ahol ez lesz, és megcsinálom úgy is
Köszönöm!
Lóri
Köszönöm!
Igyekeztem a fórum feltételeinek megfelelni.
Változtattam a kódon.
Nem sebesség index van, hanem ciklus idő.
nhadrián barátom ötletéből, és javaslatára. Szerinte egy programnál es használhatóbb. azt hiszem igaza van.
bevezettem egy új változót:
(static uint32_t deklarálást nem láttam még...)
Aminél aktualizálom a millis() értéket a loop rész leges leg elején:
A végén képzek egy "elteltmiliszekundom" különbséget:
A
sorban lévő 997 eltolás azt eredményezte, hogy a kiirásnál pont 1000 ms a ciklusidő.
Így a pontosság nagyban növekedett, ha azt feltételezem, hogy a arduino miliszekunduma pontos.
Következő feladat, hogy a ciklusidő eltérésével a 1000ms-tól szabályozza a "997"-es értéket.
A teljes kód:
Igyekeztem a fórum feltételeinek megfelelni.
Változtattam a kódon.
Nem sebesség index van, hanem ciklus idő.
nhadrián barátom ötletéből, és javaslatára. Szerinte egy programnál es használhatóbb. azt hiszem igaza van.
bevezettem egy új változót:
Kód: Egész kijelölése
static uint32_t CurrentTime =0; // ciklus ido véltozó definiálás
Aminél aktualizálom a millis() értéket a loop rész leges leg elején:
Kód: Egész kijelölése
CurrentTime = millis(); // ciklusidohoz alapjel
Kód: Egész kijelölése
l = millis() - CurrentTime; // ciklusidő átadás és alapjeltől eltérés.
lcd.print(l); // ciklus ido kiirás
Kód: Egész kijelölése
k = i + 997; // k változo beállítjuk 1 mp-cel későbbre, ennek a számnak jelentősége van az óra pontosságára...
Így a pontosság nagyban növekedett, ha azt feltételezem, hogy a arduino miliszekunduma pontos.
Következő feladat, hogy a ciklusidő eltérésével a 1000ms-tól szabályozza a "997"-es értéket.
A teljes kód:
Kód: Egész kijelölése
#include <LiquidCrystal.h> / LCD meghívása
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // TávIR-es panel bekötés, átböngészve a huzalozást a nyákon :)
int led = 13; // hátér villágítás port
int mp_x = 7; // helyiérték helyes kijelzéshez a mp x koordinátája
int perc_x = 4; // helyiérték helyes kijelzéshez a perc x koordinátája
int ora_x = 2; // helyiérték helyes kijelzéshez a ora x koordinátája
long i, j, k, l; // ido tellésének változói, és az l egy sebesség index
int ora, perc, mp; // idő változok
// static uint32_t CycleTime = 0;
static uint32_t CurrentTime =0; // ciklus ido véltozó definiálás
void setup()
{
pinMode(led, OUTPUT); // háttérvillágítás port kimenetre kapcsolás
digitalWrite(led, HIGH); // LCD háttérvillágítás felkapcsolás
lcd.begin(16, 2); // LCD definiálás
lcd.setCursor(0, 0); // cursor pozicóba állítás
lcd.print("ido:"); //"ido:" felírat kiirás egyszer
lcd.setCursor(5, 0);
lcd.print("Ciklus ido:");
mp = 0; // változo nullázás
perc = 0; // változo nullázás
ora = 0; // változo nullázás
}
void loop ()
{
CurrentTime = millis(); // ciklusidohoz alapjel
i = millis(); // i változonak átadjuk az aktuélis miilis() értékez
j = millis(); // i változonak átadjuk az aktuélis miilis() értékez
k = i + 997; // k változo beállítjuk 1 mp-cel későbbre, ennek a számnak jelentősége van az óra pontosságára...
while ( k > j ) // ha k nagyobb lesz mint j
{
j = millis(); // j aktualizálás
// l++; // sebbeség index generálás
}
mp++; // eltelt egy másodperc
if ( mp > 59 ) // mp perc váltás
{
mp = 0;
perc++;
}
if ( perc > 59 ) // perc óra váltás
{
perc = 0;
ora++;
}
if ( ora > 9 ) {
ora_x = 0;
} else {
ora_x = 1;
} // helyiérték kijelzés, eltolás az LCD-n
if ( ora == 0 ) { lcd.setCursor(0, 1); lcd.print(" "); }
lcd.setCursor(ora_x, 1); // helyiérték beállítás
lcd.print(ora); // ora érték kiirás
if ( perc > 9 ) { perc_x = 3; } else { perc_x = 4; } // helyiérték kijelzés, eltolás az LCD-n
if ( perc == 0 ) { lcd.setCursor(3, 1); lcd.print(" "); }
lcd.setCursor(perc_x, 1); // helyiérték beállítás
lcd.print(perc); // perc érték kiirás
if ( mp > 9 ) { mp_x = 6; } else { mp_x = 7; }// helyiérték kijelzés, eltolás az LCD-n
if ( mp == 0 ) { lcd.setCursor(6, 1); lcd.print(" "); }
lcd.setCursor(mp_x, 1); // helyiérték beállítás
lcd.print(mp); // mp érték kiirás
lcd.setCursor(10, 1); // sebesség index cursor beállítása
l = millis() - CurrentTime; // ciklusidő átadás és alapjeltől eltérés.
lcd.print(l); // ciklus ido kiirás
}
Átírtam a programot millis() -ről micros()-ra.
Jobban látható a eltérés.
Pl.: lázszik, hogy a két számjegynél a helyes kijelzésre fordított program sorok több időt igényelnek...
Azt gondolom:
Ha feltételezzük, hogy a AVR-nek pontos a ms-ja vagy a us-ja, akkor pontos órát tudunk készíteni.
Szerintem ha pontos óra kell AVR-be, akkor csatolni kell hozzá egy GPS-t, és onnan szinkronizálni "időnként" (percenként, óránként, naponként) a pontos időt.
Egyéb más, az programozási gyakorlat.
Pl,: szabályzási gyakorlat, a jelen program kód lefutásának idejét lehető legkisebb eltéréssel egy másodpercen tartani. Függetlenül attól, hogy mit csináltatunk még vele.
Ide már kell PID szabályzás minden gyakorlati tapasztalata...
Biztos van rengeteg felhasználás, ahol fontos, hogy egy bizonyos kód meghatározott időközönként fusson le...
Jobban látható a eltérés.
Pl.: lázszik, hogy a két számjegynél a helyes kijelzésre fordított program sorok több időt igényelnek...
Azt gondolom:
Ha feltételezzük, hogy a AVR-nek pontos a ms-ja vagy a us-ja, akkor pontos órát tudunk készíteni.
Szerintem ha pontos óra kell AVR-be, akkor csatolni kell hozzá egy GPS-t, és onnan szinkronizálni "időnként" (percenként, óránként, naponként) a pontos időt.
Egyéb más, az programozási gyakorlat.
Pl,: szabályzási gyakorlat, a jelen program kód lefutásának idejét lehető legkisebb eltéréssel egy másodpercen tartani. Függetlenül attól, hogy mit csináltatunk még vele.
Ide már kell PID szabályzás minden gyakorlati tapasztalata...
Biztos van rengeteg felhasználás, ahol fontos, hogy egy bizonyos kód meghatározott időközönként fusson le...
Az AVR-en belül a pontosítás lehetősége:
- Interrupt alapon (ami pl. 1 sec lehet) Ekkor a kvarc határozza meg a pontosságot
- külső óraIC, INT-tel : ekkor a külső 32 kHz-s hangolt kvarc adja a pontosságot
- GPS: abszolút pontossága jó. Műhold és vevő + légköri viszonyoltól függ + rálátás
- GSM hálózat: legyen jel és a torony pontos legyen
- Ethernet NTP: pontos.
Cikk:
http://avr.tavir.hu/modules.php?name=Co ... ge&pid=167
- Interrupt alapon (ami pl. 1 sec lehet) Ekkor a kvarc határozza meg a pontosságot
- külső óraIC, INT-tel : ekkor a külső 32 kHz-s hangolt kvarc adja a pontosságot
- GPS: abszolút pontossága jó. Műhold és vevő + légköri viszonyoltól függ + rálátás
- GSM hálózat: legyen jel és a torony pontos legyen
- Ethernet NTP: pontos.
Cikk:
http://avr.tavir.hu/modules.php?name=Co ... ge&pid=167
A pontos alatt azt értettem , hogy nem késik nekem egy óra alatt 5-6 percet.
Elnézést amúgy az "okos " kérdésért de eddig csak PLC programozással foglalkoztam ill. PIC-kel csináltam ezt azt amihez eddig nem kellett a pontos óra . De a többiek által beküldöttek alapján már értem mit és hol hibáztam .
Elnézést amúgy az "okos " kérdésért de eddig csak PLC programozással foglalkoztam ill. PIC-kel csináltam ezt azt amihez eddig nem kellett a pontos óra . De a többiek által beküldöttek alapján már értem mit és hol hibáztam .
Re: 60 nap alatt Arduino #16 - LCD-ből óra
Van egy óra programom aminek van két hibája az egyik nem váltja a hét nap kezdőbetűit a másik az évet sem jelzi ki .
Esetleg adhatnátok tippet ébresztő funkcióhoz. Előre is köszi. (egy kezdő)
Esetleg adhatnátok tippet ébresztő funkcióhoz. Előre is köszi. (egy kezdő)
Kód: Egész kijelölése
// 2013.03.15
#include "LiquidCrystal.h"
#include "EEPROM.h"
LiquidCrystal lcd( 4, 5, 6, 7, 8 ,9); // RS, E, D4, D5, D6, D7
//LiquidCrystal lcd(4, 5, 6, 7, 8, 9); TavIR panel
// ora
unsigned char ora=23;
unsigned char perc=59;
unsigned char mp=0;
unsigned long start_time;
unsigned int ev=2013;
unsigned char ho=3;
unsigned char nap=14;
unsigned char hetnapja=3; // H=0
char const hetnapjai[]={'H','K','S','C','P','o','V'};
char const honapok[][3]={ {'J','a','n'}, {'F','e','b'}, {'M','a','r'},
{'A','p','r'}, {'M','a','j'}, {'J','u','n'},
{'J','u','l'}, {'A','u','g'}, {'S','z','e'},
{'O','k','t'}, {'N','o','v'}, {'D','e','c'} };
int tmp;
int tmp2;
unsigned char ch; // ezt arduinoul byte-nak hivjak
unsigned char ch2;
//ez lesz a beallitasnal annak a jelzese, h mit allitunk be eppen
unsigned char uzemmod=0; // kijelzes, beallitas:ev, ho, nap, hetnap, ora_h, ora_l, perc_h, perc_l, mp_h, mp_l
//4 byte datum: ne kelljen mar nullarol beallitani mindig
#define EEPROM_START 500
#define EEPROM_EV_H (EEPROM_START)
#define EEPROM_EV_L (EEPROM_START+1)
#define EEPROM_HO (EEPROM_START+2)
#define EEPROM_NAP (EEPROM_START+3)
#define VILLOGO_SZIV1 10 // az ora kiiras SZIV pozicioja villogtatashoz
#define BEKAPCSOLASSZAMLALO_L (EEPROM_NAP+1)
#define BEKAPCSOLASSZAMLALO_H (BEKAPCSOLASSZAMLALO_L +1)
byte heart[8] ={
0b00000,
0b00000,
0b01010,
0b10101,
0b10001,
0b01010,
0b00100
};
byte heart2[8] ={
0b00000,
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100
};
byte abetu[8] ={
0b00010,
0b00100,
0b01110,
0b00001,
0b01111,
0b10001,
0b01111
};
byte obetu[8] ={
0b00010,
0b00100,
0b01110,
0b10001,
0b10001,
0b10001,
0b01110
};
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// bekoszono uzenet
lcd.print("Arduino!LCD ora");
delay(1000);
lcd.begin(16, 2);
Serial.begin(9600);
Serial.print("Program start\n");
delay(3500);
ch=EEPROM.read(BEKAPCSOLASSZAMLALO_L);
ch2=EEPROM.read(BEKAPCSOLASSZAMLALO_H);
// 8 bittel eltoljuk balra, azaz felso bajt lesz, es hozzatesszuk az alsot
tmp = ch2<<8|ch; // eddigi bekapcsolasok szama
Serial.print("Eddigi bekapcsolasok: LSB:0x");
Serial.print(ch, HEX);
Serial.print(" MSB:0x");
Serial.print(ch2, HEX);
Serial.print(" (");
Serial.print(tmp);
Serial.println(")");
EEPROM.write(BEKAPCSOLASSZAMLALO_L, ++ch); // megnovelt erteket visszairjuk
if(!ch) // ch == 0 csak programozoul irva :-)
{ // akkor lesz tmp 0 ha a kisebbik helyiertek tulcsordul a szamlalo novelesekor
EEPROM.write(BEKAPCSOLASSZAMLALO_H, ++ch2); // es ekkor kell a nagyobbik helyierteket novelni es visszairni
}
tmp2 = ch2<<8 | ch;
lcd.setCursor(0,0); // hulye modon X ,Y
lcd.print("Bekapcs. #");
lcd.print(tmp2);
lcd.print(" "); // esetleg ott maradt kiiras letorlese
Serial.print("Mostani bekapcsolas: ");
Serial.println(tmp2);
ch=EEPROM.read(EEPROM_HO);
if(ch && ch<13)
{
Serial.print("Honap jo: ");
Serial.println(ch);
ch2=EEPROM.read(EEPROM_NAP);
if(ch2 && ch2<32) // hiheto napszam IDE JOHETNE MEG A HONAPHOSSZ ELLENORZES
{
Serial.print("Nap jo: ");
Serial.println(ch2);
ho = ch;
nap = ch2;
ch =EEPROM.read(EEPROM_EV_H);
ch2=EEPROM.read(EEPROM_EV_L);
tmp = ch<<8|ch2; //ev osszeallitva nem nulla
if(tmp && !(tmp+1) ) // ha az ev nem nulla es nem -1 akkor legyen jo
{
ev = tmp;
Serial.print("Ev jo: ");
Serial.println(ev);
lcd.setCursor(0,1);
lcd.print("Eltarolt datum jo");
} //ev
} // nap
} // honap
else
{
Serial.print("Honap NEM jo: ");
Serial.println(ch);
lcd.setCursor(0,1);
lcd.print("Datum programbol");
delay(7000);
}
lcd.clear();
lcd.print("Guly");
lcd.write(3);
lcd.print("s/ LCD ");
lcd.write(4);
lcd.print("ra");
start_time = millis();
lcd.createChar(3, abetu);
lcd.createChar(4, obetu);
lcd.createChar(2, heart2);
lcd.createChar(1 ,heart);
}
void loop() {
unsigned char honaphossz;
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0,1);
if(millis()-start_time>997)
{
if(++mp>59)
{
mp=0;
if(++perc>59)
{
perc=0;
if(++ora>23)
{
ora=0;
honaphossz = (ho==2) ? ((!(ev%4) && (ev%100))||!(ev%400) ? 29 : 28) : ((ho+(ho>7))%2) ? 31 : 30 ;
if(++nap>honaphossz)
{
nap=1;
if(++ho>12)
{
ho = 1;
ev++;
}
}
}
}
}
//////////////////////
// 1234567890123456 //
// 2012.12.31 12:59 //
//////////////////////
//////////////////////
// 1234567890123456 //
// Dec.31H 12:59:51 //
//////////////////////
// H K S C P S V
// H K e C P o V
start_time+=1000;
lcd.write(honapok[ho-1][0]);
lcd.write(honapok[ho-1][1]);
lcd.write(honapok[ho-1][2]);
lcd.print(".");
lcdprint2(nap);
lcd.print(hetnapjai[hetnapja]);
lcd.setCursor(8,1);
lcdprint2(ora);
lcd.print(" ");
lcdprint2(perc);
lcd.print("/");
lcdprint2(mp);
}
digitalWrite(13, HIGH); // szivdobogas
int sensorReading=analogRead(A0);
int delayTime=map(sensorReading,0,1023,200,1200);
lcd.setCursor(VILLOGO_SZIV1, 1); //x=10 line=2
lcd.write(2); // mp-kent villogo sziv
delay(delayTime);
lcd.setCursor(VILLOGO_SZIV1, 1);
lcd.write(1);
delay(delayTime);
}
void lcdprint2(char cc) // ket szamjeggyel irja ki a megadott szamot
{
lcd.print(cc/10);
lcd.print(cc%10);
return;
}
A hozzászólást 1 alkalommal szerkesztették, utoljára Bagameri 2013. március 15. péntek, 22:47-kor.