60 nap alatt Arduino #16 - LCD-ből óra
60 nap alatt Arduino #16 - LCD-ből óra
Hogyan oldanád meg a 60 nap alatt Arduinoban felmerült:
LCD-ből óra problémakört?
Kitételek: csak az eddigi _tanfolyami_ tudás használható! TIMER, DATETIME függvénykönyvtár nem!
LCD-ből óra problémakört?
Kitételek: csak az eddigi _tanfolyami_ tudás használható! TIMER, DATETIME függvénykönyvtár nem!
A hozzászólást 1 alkalommal szerkesztették, utoljára Robert 2012. augusztus 25. szombat, 10:04-kor.
kód jöhet ide?
Szia Robi!
Úgy érted másoljam ide az óra programom forrását? (bocs a láma kérdésért)
Addig egy érdekesség.
Van két, gyakorlatilag ugyanolyan, kék háttérvilágításos, 2*16 karakteres LCD-t tartalmazó arduino shieldem. (Máshonnan vettem őket és kicsit más alkatrészek vannak beültetve, kicsit más a nyákterv is, de azonos pontok vannak összekötve rajtuk.) A tanfolyami anyagban szereplő sebességteszttel megmértem őket. Az érdekesség az volt, h az első 14 mérési eredmény pontosan egyezett (tovább pedig nem mértem):
(úgy, hogy az idemásolt eredményeket néztem és a soros monitoron vártam, h az az érték jön-e ki)
Úgy érted másoljam ide az óra programom forrását? (bocs a láma kérdésért)
Addig egy érdekesség.
Van két, gyakorlatilag ugyanolyan, kék háttérvilágításos, 2*16 karakteres LCD-t tartalmazó arduino shieldem. (Máshonnan vettem őket és kicsit más alkatrészek vannak beültetve, kicsit más a nyákterv is, de azonos pontok vannak összekötve rajtuk.) A tanfolyami anyagban szereplő sebességteszttel megmértem őket. Az érdekesség az volt, h az első 14 mérési eredmény pontosan egyezett (tovább pedig nem mértem):
Másik kék LCD shieldemmel ugyanaz. De sorról sorra ugyanaz!!Egyik kék kijelzős LCD shield írta: Start..
10 sec alatt 28926 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28924 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28922 karakterkiiras volt.
10 sec alatt 28921 karakterkiiras volt.
10 sec alatt 28922 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28924 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28924 karakterkiiras volt.
(úgy, hogy az idemásolt eredményeket néztem és a soros monitoron vártam, h az az érték jön-e ki)
Másik kék kijelzős LCD shield írta: Start..
10 sec alatt 28926 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28924 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28922 karakterkiiras volt.
10 sec alatt 28921 karakterkiiras volt.
10 sec alatt 28922 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28924 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28925 karakterkiiras volt.
10 sec alatt 28924 karakterkiiras volt.
Majdnem.
Egy valódi, időmérő elkészítése a feladat...
#17 lecke vége:
A sebesség teszt az LCD-től nem is függ igazán. Viszont, ha az Arduino más-más verziójával fordítod, akkor már van eltérés (az 1.x verziók pazarlóbbak és így lassabb a kiírás).
Nálam a kiírás: 2x16 és 4x20 LCD-n tesztelve:
Arduino-0022: 3033 karakter/sec
Arduino-1.0.1: 2886 karakter/sec
Egy valódi, időmérő elkészítése a feladat...
#17 lecke vége:
Kód: Egész kijelölése
A kijelzőből csináljunk egy órát, ami az idő kiírása mellett tájékoztat arról is, hogy hányszor kapcsoltuk be eddig az áramkörünket. Könnyítés: bekapcsoláskor 12:00-tól járjon az óra:).
Nálam a kiírás: 2x16 és 4x20 LCD-n tesztelve:
Arduino-0022: 3033 karakter/sec
Arduino-1.0.1: 2886 karakter/sec
Macsek írta:// Macsek arduino LCD ora
// 2012.08.05
// Duemilanove ATmega328
#include <LiquidCrystal.h>
#include <EEPROM.h>
/*
Macsek LCD:
* LCD RS pin to digital pin 8
* LCD Enable pin to digital pin 9
* LCD D4 pin to digital pin 4
* LCD D5 pin to digital pin 5
* LCD D6 pin to digital pin 6
* LCD D7 pin to digital pin 7
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // RS, E, D4, D5, D6, D7
//LiquidCrystal lcd(4, 5, 6, 7, 8, 9); TavIR panel
// ora
unsigned char ora=0;
unsigned char perc=0;
unsigned char mp=0;
unsigned long start_time;
unsigned int ev=2012;
unsigned char ho=8;
unsigned char nap=5;
unsigned char hetnapja=5; // H=0
char const hetnapjai[]={'H','K','e','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_KETTOSPONT1 10 // az ora kiiras kettospontjanak pozicioja villogtatashoz
#define VILLOGO_KETTOSPONT2 13 // a perc kiiras kettospontjanak pozicioja villogtatashoz
#define BEKAPCSOLASSZAMLALO_L (EEPROM_NAP+1)
#define BEKAPCSOLASSZAMLALO_H (BEKAPCSOLASSZAMLALO_L +1)
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// bekoszono uzenet
lcd.print("Macsek: LCD ora");
delay(1000);
Serial.begin(9600);
Serial.print("Program start\n");
//delay(2000);
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) // tmp == 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 Y, X
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(5000);
lcd.clear();
lcd.print("Macsek: LCD ora");
start_time = millis();
}
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>1000)
{
if(++mp>59)
{
mp=0;
if(++perc>59)
{
perc=0;
if(++ora>24)
{
ora=0;
honaphossz = (ho==2) ? (! (ev%4) && (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][0]);
lcd.write(honapok[ho][1]);
lcd.write(honapok[ho][2]);
lcd.print(".");
lcdprint2(nap);
lcd.print(hetnapjai[hetnapja]);
lcd.setCursor(8,1);
lcdprint2(ora);
lcd.print(":");
lcdprint2(perc);
lcd.print(":");
lcdprint2(mp);
}
ch = (millis()/1000)%2;
digitalWrite(13, ch); // szivdobogas
ch = ch ? ' ' : ':' ;
//lehet, h mar tul csicsas igy
lcd.setCursor(VILLOGO_KETTOSPONT1, 1); //x=11 line=2
lcd.write( ch ); // mp-kent villogo kettospont
lcd.setCursor(VILLOGO_KETTOSPONT2, 1); //x=14 line=2
lcd.write( ch );
}
void lcdprint2(char cc) // ket szamjeggyel irja ki a megadott szamot
{
lcd.print(cc/10);
lcd.print(cc%10);
return;
}
Még egy hiba:
(lassan teleírom a fórumot... nem lenne jobb az utolsó hsz szerkesztését engedélyezni mondjuk 15 percig?)
Vagy ne írjak ennyit, az is alternatíva
lcd.write(honapok[ho-1][0]);
lcd.write(honapok[ho-1][1]);
lcd.write(honapok[ho-1][2]);
(lassan teleírom a fórumot... nem lenne jobb az utolsó hsz szerkesztését engedélyezni mondjuk 15 percig?)
Vagy ne írjak ennyit, az is alternatíva
macsek írta: lcd.write(honapok[ho][0]);
lcd.write(honapok[ho][1]);
lcd.write(honapok[ho][2]);
lcd.write(honapok[ho-1][0]);
lcd.write(honapok[ho-1][1]);
lcd.write(honapok[ho-1][2]);
Akkor a kezdők kér(d)ését tolmácsolom:
Hogyan bontható ki _értelmesen_ több if-re szerkesztve?
És mit jelent:?
Ez CPP nyelv, nem natív összevonható C!
És jellemzően 0-ról kezdők vannak benne! akik annyit tanultak, amennyi eddig a tanfolyamon volt! NEM lehet háttértudásra építeni >300 főnél!
Ez micsoda és honnan jön?
Ezt jelen helyzetben:
így írjuk:
És ez sem világos:
Kód: Egész kijelölése
honaphossz = (ho==2) ? (! (ev%4) && (ev%400) ? 29 : 28) : (ho+(ho>7)%2) ? 31 : 30 ;
És mit jelent:
Kód: Egész kijelölése
if(!ch)
Ez CPP nyelv, nem natív összevonható C!
És jellemzően 0-ról kezdők vannak benne! akik annyit tanultak, amennyi eddig a tanfolyamon volt! NEM lehet háttértudásra építeni >300 főnél!
Ez micsoda és honnan jön?
Kód: Egész kijelölése
#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_KETTOSPONT1 10 // az ora kiiras kettospontjanak pozicioja villogtatashoz
#define VILLOGO_KETTOSPONT2 13 // a perc kiiras kettospontjanak pozicioja villogtatashoz
#define BEKAPCSOLASSZAMLALO_L (EEPROM_NAP+1)
#define BEKAPCSOLASSZAMLALO_H (BEKAPCSOLASSZAMLALO_L +1)
Ezt jelen helyzetben:
Kód: Egész kijelölése
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
Kód: Egész kijelölése
ch=EEPROM.read(BEKAPCSOLASSZAMLALO_L);
ch2=EEPROM.read(BEKAPCSOLASSZAMLALO_H);
//Összerakjuk a WORD-ot az alsó és felső helyiértékből, ahogy az EEPROM fejezetben volt:
tmp = ch2*256+ch; // eddigi bekapcsolasok szama
És ez sem világos:
Kód: Egész kijelölése
if(++mp>59)
{
mp=0;
if(++perc>59)
{
perc=0;
if(++ora>24)
{
ora=0;
honaphossz = (ho==2) ? (! (ev%4) && (ev%400) ? 29 : 28) : (ho+(ho>7)%2) ? 31 : 30 ;
if(++nap>honaphossz)
{
nap=1;
if(++ho>12)
{
ho = 1;
ev++;
}
}
}
}
}
Robert írta:Akkor a kezdők kér(d)ését tolmácsolom:Hogyan bontható ki _értelmesen_ több if-re szerkesztve?Kód: Egész kijelölése
honaphossz = (ho==2) ? (! (ev%4) && (ev%400) ? 29 : 28) : (ho+(ho>7)%2) ? 31 : 30 ;
Bocsi, igazad van, van benne olyan szerkezet, amiről még nem volt szó.Robert írta: És jellemzően 0-ról kezdők vannak benne! akik annyit tanultak, amennyi eddig a tanfolyamon volt! NEM lehet háttértudásra építeni >300 főnél!
honaphossz = (ho==2) ? (! (ev%4) && (ev%400) ? 29 : 28) : (ho+(ho>7)%2) ? 31 : 30 ;
Kód: Egész kijelölése
if(ho==2) // februar 28 v szokoevben 29 napos
{
// 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?
}
else // nem februar
{
if(ho>7) // julius utan valtas van.
{
if(ho%2 == 1) // ha paratlan, azaz kettovel osztva a maradek 1
{ // szept, nov
honaphossz = 30;
}
else // aug, okt, dec
honaphossz = 31;
}
else // jan-juli
{
if(ho%2 == 1) // ha paratlan, azaz kettovel osztva a maradek 1
{ // jan, marc, maj, jul
honaphossz = 31;
}
else // (februart kiszurtuk), apr, jun
honaphossz = 30;
}
}
Bocsi, rossz volt a megjegyzésem:Robert írta: És mit jelent:?Kód: Egész kijelölése
if(!ch)
ch nem egyenlő nulla az értelme
írhatjuk így is:
if (ch != 0)
Bocs, ezt meg én nem értem...Robert írta: Ez CPP nyelv, nem natív összevonható C!
Ezt én írtam. Mi a baj vele? (Az, h nem változóban vannak az értékek hanem preprocesszor konstansban? Ilyet nem illik arduinoul vagy csak az a baj vele, h még nem volt róla szó?)Robert írta:
Ez micsoda és honnan jön?Kód: Egész kijelölése
#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_KETTOSPONT1 10 // az ora kiiras kettospontjanak pozicioja villogtatashoz #define VILLOGO_KETTOSPONT2 13 // a perc kiiras kettospontjanak pozicioja villogtatashoz #define BEKAPCSOLASSZAMLALO_L (EEPROM_NAP+1) #define BEKAPCSOLASSZAMLALO_H (BEKAPCSOLASSZAMLALO_L +1)
Az EEPROM olvasás azért van a programban, mert bekapcsoláskor a dátumot onnan akartam beállítan, csak az még nincs megírva.
Robert írta:
És ez sem világos:Kód: Egész kijelölése
if(++mp>59) { mp=0; if(++perc>59) { perc=0; if(++ora>24) { ora=0; honaphossz = (ho==2) ? (! (ev%4) && (ev%400) ? 29 : 28) : (ho+(ho>7)%2) ? 31 : 30 ; if(++nap>honaphossz) { nap=1; if(++ho>12) { ho = 1; ev++; } } } } }
Ez a rész arról szól, mikor eltelik egy perc, kell-e az órát, stb is állítani.
A kommentezéssel van baj vagy valami más gond van vele?
Bocsi, arduinoval én is csak a tanfolyamod kezdete óta foglalkozom, lehet, h vannak olyan megoldásaim, amiket itt nem vagy nem így illik csinálni. Kérlek mutass rá, h mik ezek.
Köszönöm
Köszi, jó találatszegoj írta:macsek!
A vasárnapi programodban írodkésőbb pedig az időkiírásnál pedig ez szerepel
- lcd.setCursor(0,0); // hulye modon Y, X
Netán 8 soros a kijelződ, vagy a jó sorrend mégiscsak lcd.setCursor(col,row) ?
- lcd.setCursor(8,1);
Valamiért nem ment a fejembe ennek a függvénynek a paraméterezése.
Természetesen ahogy te is írtad:
lcd.setCursor(col, row)
lcd.setCursor(X, Y)
http://arduino.cc/en/Reference/LiquidCrystalSetCursor
http://arduino.cc/en/Tutorial/LiquidCrystal
#22 levél példájának javítása
Bocsi Robi, de ez is elvi hibás... (meg van egy hiányzó ")" is)Robert a #22. tanfolyami levélben írta:És az alapelv is talán már ismerős lehet:
unsigned long time;
void setup(){
Serial.begin(9600);
Serial.println("Start");
oldtime = millis();
}
void loop(){
if (oldtime + 1000 >= millis(){
oldtime = millis();
Serial.print("Time: ");
Serial.println(time);
}
}
Macsek helyesen így írta:void loop() {
if ( oldtime + 1000 >= millis() ) {
oldtime += 1000;
Serial.print("Time: ");
Serial.println(time);
}
}
OK.
Csak a pontosítás végett:)
Macsek az oldtime-t lépteti 1000 msecenként és ahhoz hasonlít.
Nálam ha a feltétel teljesül, akkor adom át a millis() értékét. Minthogy a kód<<1msec, így ez nem okoz hibát.
De a Macsek megoldása korrektebb, pontosabb, hibamentesebb...
Az eredmény szempontjából együttfutás lép fel, azaz csak ha az if hossza lenne nagyobb 1 msec, akkor okoz gondot...
Csak a pontosítás végett:)
Macsek az oldtime-t lépteti 1000 msecenként és ahhoz hasonlít.
Nálam ha a feltétel teljesül, akkor adom át a millis() értékét. Minthogy a kód<<1msec, így ez nem okoz hibát.
De a Macsek megoldása korrektebb, pontosabb, hibamentesebb...
Az eredmény szempontjából együttfutás lép fel, azaz csak ha az if hossza lenne nagyobb 1 msec, akkor okoz gondot...
macsek , a hónapok napjainak számítása ( a tömör változat) több helyen nem jó.
Ezt írtad:
Helyesen pedig ez:
hibák:
400 osztható év szökőév
100 osztható nem szökőév
november 30 napos
Egyébként nagyon jó.
Csttom
Ezt írtad:
Kód: Egész kijelölése
honaphossz = (ho==2) ? (! (ev%4) && (ev%400) ? 29 : 28) : (ho+(ho>7)%2) ? 31 : 30 ;
Kód: Egész kijelölése
honaphossz = (ho==2) ? ((!(ev%4) && (ev%100))||!(ev%400) ? 29 : 28) : ((ho+(ho>7))%2) ? 31 : 30;
400 osztható év szökőév
100 osztható nem szökőév
november 30 napos
Egyébként nagyon jó.
Csttom