60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

A "60 nap alatt Arduino" tanfolyam házi feladatai és közvetlen témái
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: Robert »

Az i2c eszközöd címe jó?
felhúzóellenállások ott vannak?
Avatar
llori
DrótVégénSzéndarab
Hozzászólások: 18
Csatlakozott: 2011. március 12. szombat, 7:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: llori »

Ellenörzöm!
Köszönöm!

Jelzem az eredményt!
Avatar
zolcsi
Újonc
Újonc
Hozzászólások: 5
Csatlakozott: 2012. október 24. szerda, 6:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: zolcsi »

Sziasztok,

Az lehet, hogy külső megszakításban nem használható az I2C kommunikáció?
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: Robert »

Mi az a külső megszakítás?
Avatar
zolcsi
Újonc
Újonc
Hozzászólások: 5
Csatlakozott: 2012. október 24. szerda, 6:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: zolcsi »

Chipen kívülről érkező. Pl. egy gombnyomás.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: Robert »

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....
Avatar
csabeszq
Bitfaragó
Hozzászólások: 678
Csatlakozott: 2012. szeptember 5. szerda, 6:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: csabeszq »

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.
Avatar
zolcsi
Újonc
Újonc
Hozzászólások: 5
Csatlakozott: 2012. október 24. szerda, 6:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: zolcsi »

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

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;
}
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: Robert »

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....
Avatar
zolcsi
Újonc
Újonc
Hozzászólások: 5
Csatlakozott: 2012. október 24. szerda, 6:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: zolcsi »

Úgy működik. Csak elegánsabbnak gondoltam a megszakításban elintézni az I2C eepromba írást. Köszi!
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: Robert »

EEPROM írás 5-8 msec. INT-ben nem lehet ennyit váraozni..... :)
peterk79
Újonc
Újonc
Hozzászólások: 4
Csatlakozott: 2013. augusztus 8. csütörtök, 6:41

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: peterk79 »

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.

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
  
}
A program nálam működik, remélem hasznos lehet másoknak is.
peterk79
Újonc
Újonc
Hozzászólások: 4
Csatlakozott: 2013. augusztus 8. csütörtök, 6:41

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: peterk79 »

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".

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  
}
Talán nem lett olyan bonyolult...
peterk79
Újonc
Újonc
Hozzászólások: 4
Csatlakozott: 2013. augusztus 8. csütörtök, 6:41

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: peterk79 »

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!
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

Re: 60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Hozzászólás Szerző: kapu48 »

Válasz küldése