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

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

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

Az I2C EEPROM-ot házasítsd a hőmérővel.

A hőmérő a mért eredményét írja ki az LCD-re. Az adatokat mentsd el és CSV formában a PC-re le tudd tölteni.
Avatar
szegoj
SzínkódFestő
Hozzászólások: 92
Csatlakozott: 2010. február 4. csütörtök, 7:00

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

Muszáj hozzászólnom, hogy a macsekot utolérjem :D

A dataloggerem első változata
Lustaságból nem írtam bele megjegyzéseket, bocsánat ...

Kód: Egész kijelölése

/*----------------------------------------------------------------  
 Projekt:       AVR-DUINO/Shieldboard Ext1
 Fájlnév:       DATA_LOGGER.PDE
 Dátum:         2012.08.20.
 Mcu:           ATMega168
 Board:         Arduino Duemilanove w/ ATmega168
 Program:       Arduino 0022
 Verziószám:    V1.00
 Szerző:        Szegő János
 E-mail:        szego@umszki.hu
 ------------------------------------------------------------------
 Az LCD kijelzőn megjeleníti az időt és dátumot.
 A hőmérő a mért eredményét írja ki az LCD-re.
 Az adatokat EEPROM-ba menti, és CSV formában
 a PC-re letöltheti (gombnyomásra).
 
 A kijelző bekötése
 ------------------
 DB4..DB7 -> Digital pins 6..9 (PD6,7 és PB0,1), külön portokon !!!
 RS       -> Digital pin 4 (PD4)
 E        -> Digital pin 5 (PD5)
 ------------------------------------------------------------------
 */

#include <LiquidCrystal.h>
#include <Wire.h>

// LCD konfiguráló parancs LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);       

byte circle[8] = {
  B00110,
  B01001,
  B01001,
  B00110,
  B00000,
  B00000,
  B00000,
};

int Back_light = 13;                   


// (20)12.08.20 19:00 (We)
byte seconds = 0x00;
byte minutes = 0x00;
byte hours = 0x19;
byte days = 0x20;
byte weekday = 0x00;
byte months = 0x08;
byte years = 0x12;

byte param;

int pcf8563_addr = 0x51; 
int lc128_addr = 0x50;
int tc75_addr = 0x48;

int eeprom_addr;

int temperature;
int temp_min = 32000;
int temp_max = -32000;

void setup() {
  pinMode(Back_light, OUTPUT);
  digitalWrite(Back_light, HIGH);
  lcd.begin(16, 2);
  lcd.createChar(0, circle);
  lcd.clear();
  Serial.begin(9600);
  Serial.println("Temperature DataLogger V1.0");
  Serial.println("---------------------------");
  Serial.println();
  Wire.begin();                     
}

void pcf8563_write() {
  Wire.beginTransmission(pcf8563_addr);
  Wire.send(2);
  Wire.send(seconds);
  Wire.send(minutes);
  Wire.send(hours);
  Wire.send(days);
  Wire.send(weekday);
  Wire.send(months);
  Wire.send(years);
  Wire.endTransmission();
}

void pcf8563_read(){
  Wire.beginTransmission(pcf8563_addr);
  Wire.send(2);
  Wire.endTransmission();
  // 7 bájtot akarunk beolvasni
  Wire.requestFrom(pcf8563_addr,7);
  if (Wire.available()) {
    seconds = Wire.receive();
    minutes = Wire.receive();
    hours = (Wire.receive()) & 63;
    days = (Wire.receive()) & 63;
    weekday =(Wire.receive()) & 7;
    months = (Wire.receive()) & 31;
    years = Wire.receive();
  }
}

void time_write() {
  lcd.clear();
  lcd.setCursor(1, 0);             
  // LCD üzenet kiiratása
  if (months<10) lcd.print(0);
  lcd.print(months,HEX);
  lcd.print('/');
  if (days<10) lcd.print(0);
  lcd.print(days,HEX);
  lcd.print(" ");
  if (hours<10) lcd.print(0);
  lcd.print(hours,HEX);
  lcd.print(':');
  if (minutes<10) lcd.print(0);
  lcd.print(minutes,HEX);
  lcd.print(':');
  if (seconds<10) lcd.print(0);
  lcd.print(seconds,HEX);
}

void temp_write() {
  lcd.setCursor(0, 1);             
  temp_min = min(temperature, temp_min);
  temp_max = max(temperature, temp_max);
  lcd.print(temperature/10);
  lcd.print(',');
  lcd.print(temperature%10);
  lcd.write(0);
  lcd.print('C');
  lcd.print(' ');
  lcd.print(temp_min/10);
  lcd.print(',');
  lcd.print(temp_min%10);
  lcd.print('/');
  lcd.print(temp_max/10);
  lcd.print(',');
  lcd.print(temp_max%10);
}

void tc75_read() {
  byte data;
  Wire.beginTransmission(tc75_addr);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(tc75_addr, 2);
  if (Wire.available()) { 
    data = Wire.receive();
    // negatív eredmény még nincs figyelembe véve
    temperature = data * 10;
    data = Wire.receive();
    // tizedesjegy kompenzálás
    if (data>>7) temperature += 5;
  }
  else {
  }
}

void lc128_write (unsigned int eeaddress, byte data) {
  byte addr;
  Wire.beginTransmission(lc128_addr);
  addr = eeaddress >> 8;              //Cim magas helyierteke
  Wire.send(addr);
  addr = eeaddress;                   //Cim alacsony helyierteke
  Wire.send(addr);
  Wire.send(data);                    //A beirando adat
  Wire.endTransmission();
  delay(5);
}

byte lc128_read (unsigned int eeaddress) {
  byte rdata = 0xFF;
  byte addr; 
  Wire.beginTransmission(lc128_addr);
  addr = eeaddress >> 8;              //Cim magas helyierteke
  Wire.send(addr);
  addr = eeaddress;                   //Cim alacsony helyierteke
  Wire.send(addr);
  Wire.endTransmission();
  Wire.requestFrom(lc128_addr,1);     //Egy byte-ot olvasunk
  if (Wire.available()){
    rdata = Wire.receive();
  }
  return rdata;
}  

void param_save() {
  byte data;
  lc128_write(1,years);
  lc128_write(2,months);
  lc128_write(3,days);
  lc128_write(4,hours);
  lc128_write(5,minutes);
  data = temperature >> 8;
  lc128_write(6,data);
  data = temperature;
  lc128_write(7,data);
  data = temp_min >> 8;
  lc128_write(8,data);
  data = temp_min;
  lc128_write(9,data);
  data = temp_max >> 8;
  lc128_write(10,data);
  data = temp_max;
  lc128_write(11,data);
}


void loop() {
  lcd.clear();
  lcd.print("PCF8563 Clock &");
  lcd.setCursor(3, 1);             
  lcd.print("DataLogger");
  delay(5000);
  // RTC működés ellenőrzése
  pcf8563_read();
  if (seconds & 128) pcf8563_write();
  while(1) {
    pcf8563_read();
    time_write();
    tc75_read();
    temp_write();
    delay(1000);
    if (seconds == 0) {    // most percenként ment
      param_save();
      // ------------------------
      lcd.setCursor(0, 1);             
      lcd.print('*');
      delay(1000);
      for (int i=1; i<12; i++) {
        param = lc128_read(i);
        Serial.print(param,HEX);
      }
      Serial.println();
      // ------------------------
    }
  }
}
Másodpercenként méri a hőmérsékletet.

A 16x2 karakteres LCD kijelző első sorában megjeleníti a dátumot és az
időt, a masodik sorában a pillanatnyi hőmérsékletet, valamint annak min.
illetve max. értékét.

Percenként elmenti ugyanezen adatokat az Ext1 panel 24LC128 EEPROM-ába, egyelőre mindig ugyanabba a címtartományba (1-11), és ugyanakkor kiküldi azokat a soros porton is (a hőmérséklet adatokat HEX formátumban, lustaság :oops: )

Kép
A képet a Képfeltöltés.hu tárolja. http://www.kepfeltoltes.hu
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

Eddig jó:)
Lesz a PCF8563T chip kezelés is lassan....

Meg a CSV import.... :)


Tetszik a program!
Avatar
szegoj
SzínkódFestő
Hozzászólások: 92
Csatlakozott: 2010. február 4. csütörtök, 7:00

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

A bejegyzés címe
60 nap alatt Arduino #30-#31 - IIC busz és az EEPROM

Én még csak a 30. leckét kaptam meg. A 31-es jelölés nem elírás?
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

Ne légy telhetelen:).
Ma/holnap reggel megy ki a 31-es leckéd:). Az is EEPROM, csak a függvénykezelés, shiftelés és a logikai bitműveletek kerültek bele... Meg a program magyarázata....
Avatar
szegoj
SzínkódFestő
Hozzászólások: 92
Csatlakozott: 2010. február 4. csütörtök, 7:00

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

Ok, bocsánat!
Csak megzavartak a számok.
:D
Avatar
macsek
Bitmanipulátor
Hozzászólások: 121
Csatlakozott: 2008. december 4. csütörtök, 7:00

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

szegoj írta:Muszáj hozzászólnom, hogy a macsekot utolérjem :D
Kép

Egyébként lehagytál már kettővel. A progi pedig jópofa, bár még csak átfutottam.

Viszont van pár kérdésem, bárki megválaszol6ja, aki tudja.

Legelőször is:
Honnan tudja szegény EEPROM vagy egyéb frincfranc, hogy mi most olvasni szeretnénk? Akárhogy nézem a programkódokat, nem látom benne, h az i2c (avagy TWI) R/~W bitjét bárhol is piszkálnánk a címzésnél. (biztos működik a te kódod is, nem próbáltam még ki, mert kell még egy kicsit hardverészkedni, h az LCD és a többi kütyü 1szerre rá legyen kötve az arduinora)

szegoj írta: void pcf8563_write() {
Wire.beginTransmission(pcf8563_addr);
Wire.send(2);
Wire.send(seconds);
Wire.send(minutes);
Wire.send(hours);
Wire.send(days);
Wire.send(weekday);
Wire.send(months);
Wire.send(years);
Wire.endTransmission();
}
szegoj írta: void pcf8563_read(){
Wire.beginTransmission(pcf8563_addr);
Wire.send(2);
Wire.endTransmission();
itt miért van vége a küldésnek? (Wire.endTransmission())
Eddig volt kiküldés (azaz megcímeztük és megmondtuk neki, h "2" kódú parancsot hajtsa végre)?
De az előző rutinban (az idő beállításában) is ugyanez a "2" kód szerepelt, csak ott folyamatosan írtad az adatot bele. (Ez tulajdonképpen az első kérdésemmel azonos)
szegoj írta: // 7 bájtot akarunk beolvasni
Wire.requestFrom(pcf8563_addr,7);
if (Wire.available()) {
seconds = Wire.receive();
minutes = Wire.receive();
hours = (Wire.receive()) & 63;
days = (Wire.receive()) & 63;
weekday =(Wire.receive()) & 7;
months = (Wire.receive()) & 31;
years = Wire.receive();
}
}
Nem a te kódodat akarom "cikizni" csak nem értem (másoknál is láttam már ilyet)
Miért van így és ez így jó-e (üzembiztos-e)?

Azt mondod a Wire.requestFrom(pcf8563_addr,7); függvénnyel, h hét bájtot szeretnél beolvasni.
Aztán megnézed, h jött-e adat if (Wire.available()), és ha igen, akkor beolvasol HÉT bájtot. De mi van, ha nem küldte még el? Megvárja a kód? (Nem a tied, hanem a "gyári" Wire könyvtár)
A WireRead leírásában nem említik, h várna, de azt sem, h nem vár. Viszont az itteni példa minden beolvasás előtt megnézi, h jött-e be byte.
Amúgy a WireAvailable leírásában az van, h megmondja, h mennyi karakter érkezett be, amit még nem olvastunk ki. Tehát lehet, h if (Wire.available()==7) már korrekt megoldás lenne?
Most már nagyon indulnom kellene itthonról (tudjátok, nézegetni a csajokat), tehát nem olvasok most utána, de az dereng, h 32 byte a Wire buffere, akkor abba beleférhet.

Mi a szép és működő megoldás?



szegoj írta: void loop() {
lcd.clear();
lcd.print("PCF8563 Clock &");
lcd.setCursor(3, 1);
lcd.print("DataLogger");
delay(5000);
// RTC működés ellenőrzése
pcf8563_read();
if (seconds & 128) pcf8563_write();
while(1) {
pcf8563_read();
time_write();
tc75_read();
temp_write();
delay(1000);
if (seconds == 0) { // most percenként ment
param_save();
// ------------------------
lcd.setCursor(0, 1);
lcd.print('*');
delay(1000);
for (int i=1; i<12; i++) {
param = lc128_read(i);
Serial.print(param,HEX);
}
Serial.println();
// ------------------------
}
}
}
[/code]
Bocsi, egy kis belekotyogás a stílusba:
A loop() függvényedben a while(1) előtti sorok szebben mutatnának a setup()-ban és akkor nem kéne while(1) sem.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

Nyomás vissza a 29. leckét átolvasni :).

Kód: Egész kijelölése

Iras:
  Wire.beginTransmission(cím);
  Wire.send(mit_irok_byte1);
  Wire.send(mit_irok_byte2);
  Wire.send(mit_irok_byte3);
  Wire.send(mit_irok_byte4);
  Wire.endTransmission();

Olvasas:
  Wire.requestFrom(cim,olvasandodarab);
    rdata = Wire.receive(); //1. byte olvasva
    rdata = Wire.receive(); //2. byte olvasva
    rdata = Wire.receive(); //3. byte olvasva
    rdata = Wire.receive(); //4. byte olvasva
//Ha olvasandodarab: 3 akkor a 4. byte kérésekor a slave csak pislog, de nem kuld semmit!
A leckében is valahol benne van, hogy a R/W+-t az Arduino rakja hozzá, hogy írod vagy olvasod!

Kód: Egész kijelölése

void pcf8563_read(){ 
Wire.beginTransmission(pcf8563_addr); 
Wire.send(2); 
Wire.endTransmission(); 
A PCF8563T adatlapot vedd elő és világos lesz -> 28. lecke. I2C-t csak adatlap bitrokában érted meg!
Ezzel azt mondod meg, hogy 2. regisztertől akarsz majd valamit csinálni vele. Órát olvasol vagy állítasz be a következőkben....


A nem küldte el/fogadja: NEM RS232/sorosport. A MASTER adja az ütemet! Ő ad órajelet, és a slave _ezzel szinkronban_ csinálhat bármit! -> Philips leírás.


Az I2C NEM LED villogtató!
Komplex és összetett valami. Ha kihagysz 1-2 lépést : kuka. Borul a teljes későbbi tudás. "Tan'tónéni, nem tudom leírni a nevemet, mert a 'R' betűnél beteg voltam :P "
És ez csak egy vacak egyszerű I2C. A Dallas (1-wire), SPI (SD kártya, ethernet) protokollok az I2C megértése nélkül esélytelenek...
Nálam az I2C megértése, logikája 2 hétvége volt! Mit miért csinálok, hogyan épül fel. És ekkor nem volt csak egy LM75-s hőmérőm + adatlapja.
Itt meg itt a Philips leírás :)...
Szóval, ahogy Lenin is mondta: tanulni-tanulni-tanulni....


Off: A felmérés eredménye, ami a #27. lecke volt: "Ki hol tart most az anyagokkal?"
- Időben vagyok: 33%
- kicsit lemaradva 26%
- hát...: 31%

"Lecke szinten:"
jellemző a 18-22. lecke.
És ez csak az elolvasás, kicsit ízlelgetés....
Avatar
macsek
Bitmanipulátor
Hozzászólások: 121
Csatlakozott: 2008. december 4. csütörtök, 7:00

24LC04

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

Ne használjatok i2c óraIC-t és 24LC04 vagy 24LC08 eepromot egy rendszerben.
Úgysem tudtok :-P

1db i2c óraIC, 1 db hőmérő és 1 db 24LC04 eepromot dugtam arduinora.
Azt hittem én kötöttem el valamit, mikor ezt láttam:

Kód: Egész kijelölése

I2CScanner ready!
starting scanning of I2C bus from 1 to 127
------------------------------------------

addr: 01       	addr: 02       	addr: 03       	addr: 04       
addr: 05       	addr: 06       	addr: 07       	addr: 08       
addr: 09       	addr: 0A       	addr: 0B       	addr: 0C       
addr: 0D       	addr: 0E       	addr: 0F       	addr: 10       
addr: 11       	addr: 12       	addr: 13       	addr: 14       
addr: 15       	addr: 16       	addr: 17       	addr: 18       
addr: 19       	addr: 1A       	addr: 1B       	addr: 1C       
addr: 1D       	addr: 1E       	addr: 1F       	addr: 20       
addr: 21       	addr: 22       	addr: 23       	addr: 24       
addr: 25       	addr: 26       	addr: 27       	addr: 28       
addr: 29       	addr: 2A       	addr: 2B       	addr: 2C       
addr: 2D       	addr: 2E       	addr: 2F       	addr: 30       
addr: 31       	addr: 32       	addr: 33       	addr: 34       
addr: 35       	addr: 36       	addr: 37       	addr: 38       
addr: 39       	addr: 3A       	addr: 3B       	addr: 3C       
addr: 3D       	addr: 3E       	addr: 3F       	addr: 40       
addr: 41       	addr: 42       	addr: 43       	addr: 44       
addr: 45       	addr: 46       	addr: 47       	addr: 48 found!
addr: 49       	addr: 4A       	addr: 4B       	addr: 4C       
addr: 4D       	addr: 4E       	addr: 4F       	addr: 50 found!
addr: 51 found!	addr: 52 found!	addr: 53 found!	addr: 54 found!
addr: 55 found!	addr: 56 found!	addr: 57 found!	addr: 58       
addr: 59       	addr: 5A       	addr: 5B       	addr: 5C       
addr: 5D       	addr: 5E       	addr: 5F       	addr: 60       
addr: 61       	addr: 62       	addr: 63       	addr: 64       
addr: 65       	addr: 66       	addr: 67       	addr: 68       
addr: 69       	addr: 6A       	addr: 6B       	addr: 6C       
addr: 6D       	addr: 6E       	addr: 6F       	addr: 70       
addr: 71       	addr: 72       	addr: 73       	addr: 74       
addr: 75       	addr: 76       	addr: 77       	addr: 78       
addr: 79       	addr: 7A       	addr: 7B       	addr: 7C       
addr: 7D       	addr: 7E       	addr: 7F       	
A 24LC04-nek van A0, A1 és A2 lába. De nem használja!
3.6 Device Addressing
A control byte is the first byte received following the
start condition from the master device. The control byte
consists of a 4-bit control code, for the 24LC04B/08B
this is set as 1010 binary for read and write operations.
The next three bits of the control byte are the block
select bits (B2, B1, B0). B2 is a don't care for both the
24LC04B and 24LC08B; B1 is a don't care for the
24LC04B.
They are used by the master device to select
which of the two or four 256 word blocks of memory are
to be accessed. These bits are in effect the most sig-nificant bits of the word address.
8.4 A0, A1, A2
These pins are not used by the 24LC04B/08B. They
may be left floating or tied to either VSS or VCC.
Tehát van fizikailag ilyen nevű lába, de mindegy mit csinálsz vele, ha olyanod van bekötheted pl. földre vagy tápra, de hagyhatod lebegve is.
A címekből pedig 8 db-ot elfoglal, mert így címzi a memóriáját. Kép
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

24LC1025 még rosszabb:
Az A2 lábbal választod ki, hogy az alsó vagy a felső 21lc512-t kéred :).
Avatar
muszer
Biztosítékgyilkos
Hozzászólások: 50
Csatlakozott: 2009. december 28. hétfő, 7:00

Re: 24LC04

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

macsek írta:Ne használjatok i2c óraIC-t és 24LC04 vagy 24LC08 eepromot egy rendszerben.
Úgysem tudtok :-P
Ezt kifejtenéd bővebben?
Avatar
macsek
Bitmanipulátor
Hozzászólások: 121
Csatlakozott: 2008. december 4. csütörtök, 7:00

Re: 24LC04

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

muszer írta:
macsek írta:Ne használjatok i2c óraIC-t és 24LC04 vagy 24LC08 eepromot egy rendszerben.
Úgysem tudtok :-P
Ezt kifejtenéd bővebben?
Persze.
Cím-ütközés miatt nem használhatóak.
Az óra az 51h i2c címen lakik.
A 24LC04 illetve 24LC08 elfoglalja mind a 8 címet az 50h-57h tartományban. (egészen értelmetlen tervezés miatt, ugyanis onnan veszi a belső címzéséhez a címinformáció egy részét, h melyik címen szólnak hozzá)
Mivel ugyanarra a címre két I2C eszköz válaszol, így egyik sem tud adatot küldeni, mert összegabalyodnak. (Ha ugyanolyan értékű bitet küldenének, akkor jó, de ha az egyik 1-est, a másik 0-t akkor 0 lesz olvasható)
Avatar
muszer
Biztosítékgyilkos
Hozzászólások: 50
Csatlakozott: 2009. december 28. hétfő, 7:00

Re: 24LC04

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

macsek írta:
muszer írta:
macsek írta:Ne használjatok i2c óraIC-t és 24LC04 vagy 24LC08 eepromot egy rendszerben.
Úgysem tudtok :-P
Ezt kifejtenéd bővebben?
Persze.
Cím-ütközés miatt nem használhatóak.
Az óra az 51h i2c címen lakik.
A 24LC04 illetve 24LC08 elfoglalja mind a 8 címet az 50h-57h tartományban. (egészen értelmetlen tervezés miatt, ugyanis onnan veszi a belső címzéséhez a címinformáció egy részét, h melyik címen szólnak hozzá)
Mivel ugyanarra a címre két I2C eszköz válaszol, így egyik sem tud adatot küldeni, mert összegabalyodnak. (Ha ugyanolyan értékű bitet küldenének, akkor jó, de ha az egyik 1-est, a másik 0-t akkor 0 lesz olvasható)
Így már értem, hogy mire gondoltál.
Csak a megfogalmazás nem volt érthető számomra, mert nem minden óraIC lakik ezen a címen.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

Kérnék súgást!

Az általam eddig használt órachipek:
PCF8563 - 0x51
PCF8583 - 0x50/0x51
R5S372 - ??
MCP4v411 - ?

Keresgéltem, de nem lelem, hogy hol van az a tábla, hogy melyik címtartomány mihez dedikált I2C esetén....
Volt, de a netben elsüllyedt:(
Avatar
macsek
Bitmanipulátor
Hozzászólások: 121
Csatlakozott: 2008. december 4. csütörtök, 7:00

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

Robert írta: hol van az a tábla, hogy melyik címtartomány mihez dedikált I2C esetén....
http://www.nxp.com/acrobat_download2/se ... LGUIDE.PDF
Válasz küldése