60 nap alatt Arduino #34 - I2C busz adatgyűjtó rendszer

A "60 nap alatt Arduino" tanfolyam házi feladatai és közvetlen témái
Válasz küldése
Avatar
szegoj
SzínkódFestő
Hozzászólások: 92
Csatlakozott: 2010. február 4. csütörtök, 7:00

60 nap alatt Arduino #34 - I2C busz adatgyűjtó rendszer

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

31. Lecke házi feladatának "közelítő megoldása",
by szegoj :D

Megjegyzés: elnézést a hosszúság miatt, de gy ilyen feladat megoldása bonyolultabb, mintha a Bascon/Arduino versenyre írnánk programot :D :D :D

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

/*----------------------------------------------------------------  
 Projekt:       AVR-DUINO/Shieldboard Ext1
 Fájlnév:       DATA_LOGGER1.PDE
 Dátum:         2012.08.20.
 Mcu:           ATMega168
 Board:         Arduino Duemilanove w/ ATmega168
 Program:       Arduino 0022
 Verziószám:    V1.1
 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
 RS       -> Digital pin 4
 E        -> Digital pin 5
 LCD konfiguráló parancs LiquidCrystal(rs, enable, d4, d5, d6, d7)
 
 A 24LC128 EEPROM kezelése
 -------------------------
 A memóriát "lap írás" és "szekvenciális olvasás" módban használjuk
 
 Az EEPROM 1024 db 16 bájos rekord tárolására alkalmas (page = 64 bájt)
 Az első rekordot használjuk az utolsó mentett rekord címének tárolására
 0: last_address, hi bájt 
 1: last_address, lo bájt 
 2: -
 ...
 15: -
 
 A további (16 bájtos) rekordok felépítése
 0: years
 1: months
 2: days
 3: hours
 4: minutes
 5: temperature, hi bájt
 6: temperature, lo bájt
 7: temp_min, hi bájt
 8: temp_min, lo bájt
 9: temp_max, hi bájt
 10: temp_max, lo bájt
 11: -
 12: -
 13: -
 14: -
 15: -
 ------------------------------------------------------------------
 */

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

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 = 0x16;
byte hours = 0x12;
byte days = 0x25;
byte weekday = 0x05;
byte months = 0x08;
byte years = 0x12;

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

int last_address;

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);
  Wire.begin();                     
  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();
  // 24LC128 inicializálás
  lc128_write (0,0);
  lc128_write (1,0);
}

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 eeprom_addr, byte data) {
  byte addr;
  Wire.beginTransmission(lc128_addr);
  addr = highByte(eeprom_addr);       // felső címbitek
  Wire.send(addr);
  addr = lowByte(eeprom_addr);        // alsó címbitek
  Wire.send(addr);
  Wire.send(data);                    // beirandó adat
  Wire.endTransmission();
  delay(5);
}

byte lc128_read(unsigned int eeprom_addr) {
  byte rdata = 0xFF;
  byte addr; 
  Wire.beginTransmission(lc128_addr);
  addr = highByte(eeprom_addr);       // felső címbitek
  Wire.send(addr);
  addr = lowByte(eeprom_addr);        // alsó címbitek
  Wire.send(addr);
  Wire.endTransmission();
  Wire.requestFrom(lc128_addr,1);     // egy bájtot olvasunk
  if (Wire.available()){
    rdata = Wire.receive();
  }
  return rdata;
}  

void param_save() {
  last_address = lc128_read(0);
  last_address = (last_address << 8) | lc128_read(1);
  last_address += 16;
  lc128_write(0,last_address/256);
  lc128_write(1,last_address%256);
  lc128_pagewrite(last_address);
}

void lc128_pagewrite(unsigned int eeprom_addr) {
  byte addr, data;
  Wire.beginTransmission(lc128_addr);
  addr = highByte(eeprom_addr);       // felső címbitek
  Wire.send(addr);
  addr = lowByte(eeprom_addr);        // alsó címbitek
  Wire.send(addr);
  Wire.send(years);                   // beirandó adatok
  Wire.send(months);                  // ...
  Wire.send(days);
  Wire.send(hours);
  Wire.send(minutes);
  data = highByte(temperature);
  Wire.send(data);
  data = lowByte(temperature);
  Wire.send(data);
  data = highByte(temp_min);
  Wire.send(data);
  data = lowByte(temp_min);
  Wire.send(data);
  data = highByte(temp_max);
  Wire.send(data);
  data = lowByte(temp_max);
  Wire.send(data);
  Wire.endTransmission();
  delay(5);
}

void lc128_seqread(unsigned int eeprom_addr) {
  byte addr; 
  Wire.beginTransmission(lc128_addr);
  addr = highByte(eeprom_addr);       // felső címbitek
  Wire.send(addr);
  addr = lowByte(eeprom_addr);        // alsó címbitek
  Wire.send(addr);
  Wire.endTransmission();
  Wire.requestFrom(lc128_addr,11);     // 11 bájtot olvasunk
  if (Wire.available()){
    years = Wire.receive();
    months = Wire.receive();
    days = Wire.receive();
    hours = Wire.receive();
    minutes = Wire.receive();
    temperature = Wire.receive();
    temperature = (temperature << 8) | Wire.receive();
    temp_min = Wire.receive();
    temp_min = (temp_min << 8) | Wire.receive();
    temp_max = Wire.receive();
    temp_max = (temp_max << 8) | Wire.receive();
  }
}  

void cvs_export() {
  int address;
  last_address = lc128_read(0);
  last_address = (last_address << 8) | lc128_read(1);
  Serial.println();
  Serial.println("Temperature DataLogger V1.1");
  Serial.println("---------------------------");

  // ideiglenes. teszt célú
  Serial.print("(Rekordok szama: ");
  Serial.print(last_address/16);
  Serial.println(") ");
  // ideiglenes. teszt célú

  for (address=16; address<=last_address; address+=16) {
    lc128_seqread(address);
    Serial.print(years,HEX);
    if (months<10) Serial.print(0);
    Serial.print(months,HEX);
    if (days<10) Serial.print(0);
    Serial.print(days,HEX);
    Serial.print('/');
    if (hours<10) Serial.print(0);
    Serial.print(hours,HEX);
    if (minutes<10) Serial.print(0);
    Serial.print(minutes,HEX);
    Serial.print(',');
    Serial.print(temperature/10);      
    Serial.print('.');
    Serial.print(temperature%10);      
    Serial.print(',');
    Serial.print(temp_min/10);      
    Serial.print('.');
    Serial.print(temp_min%10);      
    Serial.print(',');
    Serial.print(temp_max/10);      
    Serial.print('.');
    Serial.print(temp_max%10);      
    Serial.println();
  }
}


void loop() {
  pcf8563_read();
  time_write();
  tc75_read();
  temp_write();
  delay(1000);
  // ***** percenként mentünk *****
  if (seconds == 0) {    
    param_save();
    cvs_export();
  }
}
A program percenkét a 24LC128 EEPROM-ba menti az idő és hőmérséklet adatokat, majd az összes elmentett adatot a soros porton kilistázza.

Hyperterminál képernyő

Kép
A képet a Képfeltöltés.hu tárolja. http://www.kepfeltoltes.hu

Szöveges kimenet
  • Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 1)
    120825/1218,33.5,33.0,34.0

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 2)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 3)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 4)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 5)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 6)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 7)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5
    120825/1224,34.5,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 8)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5
    120825/1224,34.5,33.0,34.5
    120825/1225,34.0,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 9)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5
    120825/1224,34.5,33.0,34.5
    120825/1225,34.0,33.0,34.5
    120825/1226,34.5,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 10)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5
    120825/1224,34.5,33.0,34.5
    120825/1225,34.0,33.0,34.5
    120825/1226,34.5,33.0,34.5
    120825/1227,34.0,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 11)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5
    120825/1224,34.5,33.0,34.5
    120825/1225,34.0,33.0,34.5
    120825/1226,34.5,33.0,34.5
    120825/1227,34.0,33.0,34.5
    120825/1228,34.5,33.0,34.5

    Temperature DataLogger V1.1
    ---------------------------
    (Rekordok szama: 12)
    120825/1218,33.5,33.0,34.0
    120825/1219,34.0,33.0,34.0
    120825/1220,34.0,33.0,34.5
    120825/1221,34.0,33.0,34.5
    120825/1222,34.5,33.0,34.5
    120825/1223,34.5,33.0,34.5
    120825/1224,34.5,33.0,34.5
    120825/1225,34.0,33.0,34.5
    120825/1226,34.5,33.0,34.5
    120825/1227,34.0,33.0,34.5
    120825/1228,34.5,33.0,34.5
    120825/1229,34.0,33.0,35.0
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 »

Macsek figyelmébe "ajánlom a tömör" loop() függvényt.
Előbb lemeredt a kijelző kép:

Kép
A képet a Képfeltöltés.hu tárolja. http://www.kepfeltoltes.hu
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

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

Kíváncsi voltam meddig él a Logered?

128K I2C™ CMOS Serial EEPROM
http://ww1.microchip.com/downloads/en/d ... 21191m.pdf

Max: 1,000,000 erase/write cycles

1,000,000/60=16666,6 óra/24= 964 nap / 365 = 1,9 Év!
Elég jó!

:lol:
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

1.000.000 -> egy cellára! Nema teljes IC-re!

És nem egy cellát írsz végig....

Számolj úgy:
1 adatcsomag 32 byte: 32 írás (lapmódú írás miatt).
A chipbe minden 1024. íráskor jutsz újra ide, erre a cellára.
Így az 1.9 év *1024 -> ~2100 év: Na ekkor már nemhogy kukactáp, de még kőzet sem leszek már....
A hozzászólást 1 alkalommal szerkesztették, utoljára Robert 2012. augusztus 25. szombat, 18:50-kor.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

És még elvi hibás is az egész, mert az óraIC az 1900...2199-ig tud csak járni :)
És az EEPROM adatmegőrzési ideje 100 év.

Szóval mars az I2C EEPROM-ot RAID tömbbe rakni, cserélhető/redundásként...
És időnként archiválás/adatmentés.

És az ÓraIC is problémás, szóval külön óraIC-t gyártani hozzá - mondjuk egy külön AVR chipből, ami lekezeli a XXXX. századot is :).

És legyen az áramkör redundáns, mert a Marsi ÚjKolónia betelepülésének millenárisára berendezett: "A Földi élet elmúlt 14 évszázada" című kiállításon, az Oppurtunity és a Curiosity mellett, mint hobbi adatgyűjtő és űrtechnikai eszköz-modell fog szerepelni. "És még működik!" felirattal. Igaz búra alatt, N2-O2 mesterséges légkörben....

:P
Avatar
kapu48
Elektronbűvölő
Hozzászólások: 3375
Csatlakozott: 2008. augusztus 29. péntek, 6:00

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

Ezt a két címet minden mentéskór felül írja!

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

Az EEPROM 1024 db 16 bájos rekord tárolására alkalmas (page = 64 bájt) 
  Az első rekordot használjuk az utolsó mentett rekord címének tárolására 
  0: last_address, hi bájt 
  1: last_address, lo bájt
Ezek biztos elfáradnak 2 év alatt!
Igaz marad még hely bőven.

Addigra meg úgy is lesz másik!
:lol:
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

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

Tényleg. A címjegyzés meg mehetne az AVR-be belülre CRC-sen és körülfordulósan....


Nálam jobb trükk lett:

Minden adatmező 16 byte hosszú. A 17. ugye a következő blokk első byte-ja. A kiírt adatmező _után_ FF kerül kiírásra (17. byte). A program elején megnézem, hogy a n+1. mező FF-e. Ha igen: ide kell írnom először:) Ha igen, akkor az az első szabad. Így innen írom tovább.

Így megúszom, hogy le kelljen tárolni, hogy hol járok.
Ha körbeértem a chipben, akkor a felülírást jelszo, mert a törlendő mező első byte-ja FF lesz.
Az üres chip FF-eket tartalmaz.



Így lett az adatgyűjtő a SMT kemencéhez (Bascom).
http://avr.tavir.hu/modules.php?name=Co ... ge&pid=161
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:Macsek figyelmébe "ajánlom a tömör" loop() függvényt.
Irígykedek is, hogy milyen jól állsz vele! És valóban szép lett a loop().
Én még mindig csak az ihletet várom, h megírjam. (Meg a ti programjaitokat :) )
Avatar
Bagameri
DrótVégénSzéndarab
Hozzászólások: 37
Csatlakozott: 2013. március 15. péntek, 14:21

Re: 60 nap alatt Arduino #34 - I2C busz adatgyűjtó rendszer

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

Nagyon jól megy az adat gyűjtő (átírtam egy két dolgot hogy menjen az UNO-n) egy olyan gond van hogy a real time nem a valós időt mutatja ezt hogy
lehet korrigálni ? A hőmérő is 17.5 C° helyett 23.5 C°-t mutat ,de ez lehet hogy az EXT 1 melegedése miatt lehet.
Avatar
Robert
Elektronbűvölő
Hozzászólások: 10191
Csatlakozott: 2005. december 9. péntek, 7:00

Re: 60 nap alatt Arduino #34 - I2C busz adatgyűjtó rendszer

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

A hőmérőnél ez a normál.
Melegedés + a pontatlansága (adatlap).

A PCF8563 beállítása az óra fejezetben/leckében volt.
Válasz küldése