60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Az i2c eszközöd címe jó?
felhúzóellenállások ott vannak?
felhúzóellenállások ott vannak?
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Ellenörzöm!
Köszönöm!
Jelzem az eredményt!
Köszönöm!
Jelzem az eredményt!
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Sziasztok,
Az lehet, hogy külső megszakításban nem használható az I2C kommunikáció?
Az lehet, hogy külső megszakításban nem használható az I2C kommunikáció?
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Mi az a külső megszakítás?
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Chipen kívülről érkező. Pl. egy gombnyomás.
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Ahogy belelestem a wire.h és a wire.cpp függvényekbe, ott nem láttam ilyet. Nem lehet, hogy a főprogramban fut egy I2C utasítássor és a közben esik be a megszakításban levő?
Mert az okozhat ilyet....
Mert az okozhat ilyet....
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Az I2C-t még a _delay_ms(1000) sem teszi lapátra. Amíg nem kezelődik le rendesen, addig az SCL vonalat alacsonyan tartja és mindenki vár.
Volt szerencsém, hogy az ADC interrupt túlterhelte a procit és nem jutott idő az I2C-nek. Multiméterrel látható volt, hogy az SCL alacsonyan van tartva.
Azt, hogy Arduino alatt hogyan van megírva nem tudom, de ha értelmesen csinálták, akkor baj nem lehet, max a túloldal vár.
Volt szerencsém, hogy az ADC interrupt túlterhelte a procit és nem jutott idő az I2C-nek. Multiméterrel látható volt, hogy az SCL alacsonyan van tartva.
Azt, hogy Arduino alatt hogyan van megírva nem tudom, de ha értelmesen csinálták, akkor baj nem lehet, max a túloldal vár.
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Adott az alábbi program. És nem tudom, mit rontok el.
Azt kéne csinálnia, hogy gombnyomás esetén megszakítást generálok, és megszakításban I2C eepromba írom az esemény azonosítóját, és dátumot meg időt. Aztán visszatérek. Igen ám, de nem jön vissza megszakításból.
Ha kicsit változtatok rajta és gombnyomás esetén megszakításban egy flag-et állítok át, s ezt a főprogramban figyelem, úgy működik a dolog.
De ennek is van egy szépséghibája. Mindezt egy Shield Ext1-en kísérletezem. És néha gombnyomás nélkül is bepottyan egy gombnyomás. A D3-ra van kötve a gomb és az infravevő is. Lehet, hogy az infravevő rángatja a lábat?
Köszi,
Zolcsi
Azt kéne csinálnia, hogy gombnyomás esetén megszakítást generálok, és megszakításban I2C eepromba írom az esemény azonosítóját, és dátumot meg időt. Aztán visszatérek. Igen ám, de nem jön vissza megszakításból.
Ha kicsit változtatok rajta és gombnyomás esetén megszakításban egy flag-et állítok át, s ezt a főprogramban figyelem, úgy működik a dolog.
De ennek is van egy szépséghibája. Mindezt egy Shield Ext1-en kísérletezem. És néha gombnyomás nélkül is bepottyan egy gombnyomás. A D3-ra van kötve a gomb és az infravevő is. Lehet, hogy az infravevő rángatja a lábat?
Köszi,
Zolcsi
Kód: Egész kijelölése
#include <Wire.h>
#include <Rtc_Pcf8563.h>
#include <LiquidCrystal.h>
#define device_address_eeprom 0x50
#define event_push_button 101
//init the real time clock
Rtc_Pcf8563 rtc;
LiquidCrystal lcd(4 ,5 ,6 ,7 ,8, 9);
unsigned int eeprom_pointer();
void setup()
{
//D3 GND fele nyomogomb (opcio!)
pinMode(3,INPUT);
//D3 belso felhuzoellenallas (opcio!)
digitalWrite(3, HIGH);
//Megszakitaskezeles
interrupts();
attachInterrupt(1, push_button, RISING); //Gomb felengedést figyelem, amikor visszaáll magasba
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
Serial.begin(9600);
Wire.begin();
}
void loop()
{
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 0);
lcd.print(rtc.formatTime());
lcd.setCursor(0, 1);
lcd.print(rtc.formatDate(RTCC_DATE_ASIA));
}
void push_button()
{
delay(20); //Prellmentesítés
if (digitalRead(3)) write_timestamp_to_eeprom(event_push_button, eeprom_pointer());
}
void write_timestamp_to_eeprom( byte event, unsigned int eeaddress) //Eepromba írom az esemény azonosítóját és dátumot, időt
{
Wire.beginTransmission(device_address_eeprom);
Wire.write((int)(eeaddress >> 8)); //Cím felső byte-ja
Wire.write((int)(eeaddress & 0xFF)); //Cím alsó byte-ja
Serial.print(eeaddress);
Wire.write(event); //Az esemény azonosítója
Serial.print(" ");
Serial.print(event);
Serial.print(" ");
Wire.write(rtc.getYear()); //Év utolsó 2 számjegye
Serial.print(rtc.getYear());
Serial.print("/");
Wire.write(rtc.getMonth()); //Hónap
Serial.print(rtc.getMonth());
Wire.write(rtc.getDay()); //Nap
Serial.print("/");
Serial.print(rtc.getDay());
Serial.print(" ");
Wire.write(rtc.getHour());
Serial.print(rtc.getHour());
Serial.print(":");
Wire.write(rtc.getMinute());
Serial.print(rtc.getMinute());
Serial.print(":");
Wire.write(rtc.getSecond());
Serial.println((rtc.getSecond()));
Wire.endTransmission();
// delay(5);
//Az Eeprom 0,1 byte-jába a következő szabad címet (7-et ugrok)
eeaddress+=7;
Wire.beginTransmission(device_address_eeprom);
Wire.write(0);
Wire.write(0);
Wire.write((int)(eeaddress >> 8));
Wire.write((int)(eeaddress & 0xFF));
Wire.endTransmission();
// delay(5);
}
unsigned int eeprom_pointer() //Kiolvasom az Eeprom 0,1 byte-ját, vagyis a következő szabad címet
{
unsigned int return_data;
Wire.beginTransmission(device_address_eeprom);
Wire.write(0);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(device_address_eeprom, 2);
if (Wire.available()) {
return_data = (Wire.read() << 8);
return_data += Wire.read(); }
return return_data;
}
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
A flag-ot a főprogramban billentsd be!
Tipp: INTben flag bebillent és a főprogram értékelje ki.
A nyomógombba az IR vevő bejátszhat....
Tipp: INTben flag bebillent és a főprogram értékelje ki.
A nyomógombba az IR vevő bejátszhat....
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Úgy működik. Csak elegánsabbnak gondoltam a megszakításban elintézni az I2C eepromba írást. Köszi!
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
EEPROM írás 5-8 msec. INT-ben nem lehet ennyit váraozni.....
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
A magam részéről a következőképpen oldottam meg a problémát. Ugyan nem olyan kidolgozott, mint ahogy azt a fórumban láttam, de ...
A memória byte és a hőfok float tulajdonsága egyenlőre még elgondolkodtat.
A program nálam működik, remélem hasznos lehet másoknak is.
A memória byte és a hőfok float tulajdonsága egyenlőre még elgondolkodtat.
Kód: Egész kijelölése
#include <Wire.h> //Wire könyvtár használata
#include <LiquidCrystal.h> //LiquidCeystal könyvtár használata
LiquidCrystal lcd (4,5,6,7,8,9);
#define memory 0x50 //alias memoria
#define homero 72 //alias homero
byte hofok=0.0;//változó a hőm tárolására
unsigned long ora = 0;//ora
unsigned long perc = 0;//perc
unsigned long mp=0;//másodperc
unsigned long seged=millis(); //segédváltozó az órapontosításhoz
unsigned int hely=0;
void setup ()
{
Wire.begin(); //IIC nyitása
Serial.begin(9600);//soros komm nyitása
Wire.beginTransmission(homero);
Wire.write(1);//config beállítása (ha nem 0,5-ről indulna
Wire.write(00000000); //pontosság beállítása 1,5-re (vagy bármire)
Wire.endTransmission(); //elég a beszéd
lcd.begin(16,2);//lcd inicializálása
pinMode(13,OUTPUT);//háttérvilágítás a 13 lábon
digitalWrite(13,HIGH);//háttérvilágítás bekapcsol
lcd.clear();//lcd törlése
delay(500);//egy kis késleltetés
lcd.setCursor(0,0);//cursor beállítása 0,0-ra
lcd.println("HOMERO KP V 1_4 ");
lcd.setCursor(0,1);
lcd.println("AAAAAAAAAAAAAAAAA");
delay(5000);
lcd.clear();
}
void loop()
{
orabeall(); //orabeall eljárás indítása
lcd.setCursor(0,0); //lcd beállításai
lcd.print("IDO: ");
lcd.print(ora);
lcd.print(":");
lcd.print(perc);
lcd.print(":");
lcd.print(mp);
lcd.setCursor(0,1);
lcd.print("Homers:");
lcd.print(homeromuk(hofok)); //homeromuk függvény eredménye
lcd.println(" Fok");
Serial.print("Mentett adatok:");
Serial.println(memolvasas(memory,hely)); //kiolvasás a memoriából
}
void orabeall () //orabeall eljárás
{
mp=mp+1; //másodpercmutató léptetése
delay(1000); //várjunk
if((mp%10)==0) //elég ha 10 sec-onként pontosítjuk az órát
{
if(mp>=(millis()/1000))
{
mp=(millis()/1000);
}
}
if(mp==60)
{
perc=perc+1; //léptetjük a perceket
mp=0;
}
if(perc==60)
{
ora=ora+1;//léptetjük az órákat
perc=0;
}
}
float homeromuk (float hofok) //eljárás a hőmérő kezelésére
{
int tb,lb; //belső valtozok a tarolashoz also felso byte
float fokb=0.0; //belső floatban tároljuk az adatokat
Wire.beginTransmission(homero);//mondjuk a hőmérőnek hogy:
Wire.write(0x00);//áljon az ambient temp registerre
Wire.endTransmission();//elég is volt
Wire.requestFrom(homero,2);//kérek 2 byte-ot a hőmérőtől
while(Wire.available())//amíg van adat menjünk tovább
{
tb=Wire.read();//első byte olvasása IIC-ről
lb=Wire.read();//második byte kiolvasása
lb=lb/16;//számolgassunk kicsit (a 16 csak 0.625-nél igaz)
if(perc%5==0) //5 percenként mentsük el az adatokat
{
memiras(memory,hely,tb); //itt írjuk a memóriát
delay(5); //azért, mert még nem tudok floatot a memoriába másolni
}
fokb=tb; //innentől float-tá alakítás
fokb=fokb+lb*0,125;//szerintem itt 0,625 a szorzó az adatlap szerint
}
Serial.print("Hofok: ");//soros hőfok kiírás
Serial.println(fokb);
delay(5); //csak kicsit várjunk
return fokb; //adjuk vissza az eljárás eredményét a programnak
}
void memiras (int kulsomemcimb, unsigned int helyb, byte adatb)//memória írás eljárása
{
Wire.beginTransmission(kulsomemcimb);//0x50 címen indul az IIC komm
Wire.write((int)(helyb>>8));//felső kinullázása
Wire.write((int)(helyb&0xFF));//alsó kinullázása
Wire.write(adatb);//eltesszük a hőmérésnél kapott adatot
Wire.endTransmission();//elég a kommunikációból
delay(5);
}
byte memolvasas(int kulsomemcimb, unsigned int helyb) //kiolvasó függvény
{
byte visszaad=0xFF;
Wire.beginTransmission(kulsomemcimb);
Wire.write ((int)(helyb>>8));
Wire.write ((int)(helyb&0xFF));
Wire.endTransmission();
Wire.requestFrom(kulsomemcimb,1); //kérünk 1 byte-ot 0x50-től
if(Wire.available())
{
visszaad=Wire.read();//visszaad értéke a rendelkezésre álló adat
}
return visszaad; //visszatérés
}
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Az előző kódot kicsit továbbfejlesztve: így már kezelhetőek a float típusok is (memóriába menti).
A mentés 2 percenként történik meg.
Az óra pontossága még "kézi".
Talán nem lett olyan bonyolult...
A mentés 2 percenként történik meg.
Az óra pontossága még "kézi".
Kód: Egész kijelölése
#include <Wire.h> //Wire könyvtár használata
#include <LiquidCrystal.h> //LiquidCeystal könyvtár használata
LiquidCrystal lcd (4,5,6,7,8,9);
#define memory 0x50 //alias memoria
#define homero 0x48 //alias homero
byte hofok=0.0;//változó a hőm tárolására
unsigned long ora = 12; //ora
unsigned long perc = 1; //perc
unsigned long mp=0;//másodperc
unsigned long seged=millis(); //segédváltozó az órapontosításhoz
byte hely=0;
void setup ()
{
Wire.begin(); //IIC nyitása
Serial.begin(9600);//soros komm nyitása
Wire.beginTransmission(homero);
Wire.write(1);//config beállítása (ha nem 0,5-ről indulna)
Wire.write(0x60); //pontosság beállítása 0,5-re (vagy bármire)
Wire.endTransmission(); //elég a beszéd
lcd.begin(16,2);//lcd inicializálása
pinMode(13,OUTPUT);//háttérvilágítás a 13 lábon
digitalWrite(13,HIGH);//háttérvilágítás bekapcsol
lcd.clear();//lcd törlése
lcd.setCursor(0,0);//cursor beállítása 0,0-ra
lcd.println("HOMERO KP V 1_7 ");
lcd.setCursor(0,1);
lcd.println("AAAAAAAAAAAAAAAAA");
delay(5000);//indítási késleltetés
lcd.clear();//lcd letisztítása
}
void loop()
{
orabeall(); //orabeall eljárás indítása
lcd.setCursor(0,0); //lcd beállításai
lcd.print("Ido: ");
lcd.print(ora/10);
lcd.print(ora%10);
lcd.print(":");
lcd.print(perc/10);
lcd.print(perc%10);
lcd.print(":");
lcd.print(mp/10);
lcd.print(mp%10);
lcd.setCursor(0,1);
lcd.print("Homers:");
lcd.print(homeromuk(hofok)); //homeromuk függvény eredménye
lcd.println(" Fok");
}
void orabeall () //orabeall eljárás
{
mp=mp+1; //másodpercmutató léptetése
delay(1000); //várjunk
if((mp%10)==0) //elég ha 10 sec-onként pontosítjuk az órát
{
if(mp>=(millis()/1000))
{
mp=(millis()/1000);
}
}
if(mp==60)
{
perc=perc+1; //léptetjük a perceket
mp=0;
}
if(perc==60)
{
ora=ora+1;//léptetjük az órákat
perc=0;
}
if(((perc%2)==0)&&(mp<=1))
{
memiras(memory, 3, ora); //itt mentjük az időadatokat
memiras(memory, 4, perc);
memiras(memory, 5, mp);
Serial.println("Mentett adatok:");
Serial.print(memolvasas(memory,1)); //kiolvasás a memoriából 1 byte
Serial.print(".");
Serial.print(memolvasas(memory,2));//második byte kiolvasása
Serial.println(" Fok");
Serial.println("Mentesi ido:");
Serial.print(memolvasas(memory,3));
Serial.print(".");
Serial.print(memolvasas(memory,4));
Serial.print(".");
Serial.println(memolvasas(memory,5));
}
}
float homeromuk (float hofok) /*eljárás a hőmérő kezelésére
a visszaadott érték float legyen*/
{
int tb,lb; //belső valtozok a tarolashoz also felso byte
float fokb=0.0; //belső floatban tároljuk az adatokat
Wire.beginTransmission(homero);//mondjuk a hőmérőnek hogy:
Wire.write(0x00);//áljon az ambient temp registerre
Wire.endTransmission();//elég is volt
Wire.requestFrom(homero,2);//kérek 2 byte-ot a hőmérőtől
while(Wire.available())//amíg van adat menjünk tovább
{
tb=Wire.read();//első byte olvasása IIC-ről
lb=Wire.read();//második byte kiolvasása
lb=lb/16;//számolgassunk kicsit (a 16 csak 0.625-nél igaz)
if(((perc%2)==0)&&(mp<=1)) //2 percenként mentjük el az adatokat
{
memiras(memory, 1, tb); //itt írjuk a memóriába tb-t 1byte
memiras(memory, 2, lb); //itt írjuk a memóriába lb-t 2byte
delay(5); //azért, mert még nem tudok floatot a memoriába másolni
}
fokb=tb; //innentől float-tá alakítás
fokb=fokb+lb*0,125; //2 byte-ból 2x8 bit-es float lesz
//Serial.print("Hofok: ");//soros hőfok kiírás
//Serial.println(fokb); //Csak ha fontos az ellenőrzés miatt
}
return fokb; //adjuk vissza az eljárás eredményét a programnak
}
void memiras (int kulsomemcimb,unsigned int mem, byte adatb)//memória írás eljárása
{
byte memcim=0;
Wire.beginTransmission(kulsomemcimb);//0x50 címen indul az IIC komm
memcim=mem>>8;//változó, a felső byte kinullázása
Wire.write(memcim);//felsőbe beírni a 0x00 hex-et
memcim=mem; //alsóhoz beállítan a változót 0x01 hex először
Wire.write(memcim);//alsó byte-ba beírás a címmegadáshoz
Wire.write(adatb);/* eltesszük a hőmérésnél kapott adatot
elsőre a felső 0x00 alsó 0x01 címre*/
Wire.endTransmission();//elég a kommunikációból
delay(5);
}
byte memolvasas(int kulsomemcimb,unsigned int mem) //kiolvasó függvény
{
byte visszaad=0; //a visszaadott érték tárolására szolgáló változó
Wire.beginTransmission(kulsomemcimb);//komm indul 0x50 -el
byte memcim=0; //tároló a memóriacím beállításához
memcim=mem>>8;//felső byte 0x00-ra állítása
Wire.write(memcim);//megmondjuk neki, hogy álljon ide
memcim=mem;//az átvett 0x01-re mutatunk
Wire.write(memcim);
Wire.endTransmission();//elég a szövegből
Wire.requestFrom(kulsomemcimb,1); //kérünk 1 byte-ot 0x50-től
if(Wire.available())// ha van valami IIC buszon, akkor kiolvassuk
{
visszaad=Wire.read();//visszaad értéke a rendelkezésre álló adat
}
return visszaad; //visszatérés
}
Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM
Lehet, hogy ez kezdő kérdés. A helyzet az, hogy ha valamit beírok az EEPROM-ba, akkor az ott is marad.
Tehát: a törlés csak újabb írással lehetséges? Pl.: küldjünk az adott címre mondjuk 0x00 hex-et? Vagy shifteljünk?
Ha valaki megválaszolná a kérdésemet: előre is köszi!
Tehát: a törlés csak újabb írással lehetséges? Pl.: küldjünk az adott címre mondjuk 0x00 hex-et? Vagy shifteljünk?
Ha valaki megválaszolná a kérdésemet: előre is köszi!