Hőmérséklet adatgyűjtő

Ebben a “tanuló programban” egy Arduino Uno R3, egy LCD kijelző, DS3231 RTL óra és egy SD kártya illesztő illetve egy SD kártya, volt a főszereplő.
A program az SD kártyára folyamatosan rögzíti a hőmérsékletet 30 percenként. Egy futási eredmény így néz ki. (PC-vel kiolvasva a kártyát):

Datum;Ido;Homerseklet;
2016.07.21;06:04;22.75;
2016.07.21;06:34;23.00;
2016.07.21;07:04;23.00;
2016.07.21;07:34;23.00;
2016.07.21;08:04;23.00;
2016.07.21;08:34;23.25;
2016.07.21;09:04;23.25;

A file dátuma alapértelmezetten 2000.01.01 0:00, a rendszer nem kezeli. Az állomány kiterjesztése CSV, így közvetlenül Excel-el megnyitható és feldolgozható.

Sokat küzdöttem azzal, hogy működés közben ki lehessen venni a kártyát, és az adatok rögzítése folytatódjon, ha visszadugom a helyére. Nem gondoltam ugyanis arra, hogy ez nem probléma. Tudni kell, hogy az SD kártyák példa programjaiban mindenütt úgy használják az SD kártyát, hogy a tápfeszültséget a kártyának az Arduino egyik kivezetés adja. Kimenetnek programozzák, HIGH szintet állítanak be, és az SD kártya innen kapja a tápfeszt. Olyan kicsi az SD kártya áramfelvétele, hogy ez így elméletben jó. Nekem azonban ez a megoldás nem működött. Rengeteget vacakoltam vele, míg rájöttem, hogy direktben a tápra kell kötni az SD modult, különben nem lehet a kártyát használni. Az okot azóta sem sikerült kiderítenem. Több SD modult is kipróbáltam, sehogyan sem működött hibátlanul. A kártya adatait le lehetett kérdezni, de íráskor már hibát dobott a függvény.

Úgy gondoltam, ha a tápfeszt nem lehet lekapcsolni a kártyáról, akkor biztosan nem lehet kivenni. Az első elképzelésem az volt, hogy a kártyát minden egyes írás előtt megnyitom, és ezzel biztosítom, hogy a visszahelyezett kártyát is kezelje program, ha esetleg kivettem, és közben nem volt a helyén, amikor a program írni akart rá. Azonban ez a módszer egyáltalán nem működött, amit nem igazán értettem. Arra jutottam, hogy a kártya kezelő programja hibás ebben a tekintetben. A kártyát egyszer lehet megnyitni egy programon belül és kész. Valamelyik idegen nyelvű fórumon olvastam, hogy ebbe a problémába mások is beleütköztek. Tovább kísérleteztem, és próbálkoztam azzal, hogy csak az SD.begin() függvényt hívtam meg újra és újra, de ez sem működött. Megdöbbentő módon egyedül az a megoldás működött a gyakorlatban, hogy a setup részben SD.begin()-el megnyitom a kártyát és levizsgálom létezik-e a file. Ha nem akkor létrehozom. A loop-ban már csak minden különösebb előkészítés nélkül írok a kártyára amikor kell. Esetemben fél óránként került erre sor. Azonban kísérletezgetés közben a gyakoriságot 5 másodperce állítottam, és kb. 20-30 alkalommal hosszabb rövidebb időre kivettem a kártyát. És láss csodát, minden hiba nélkül működött a kártyára a file írása. Nyilván előfordult, hogy egy vagy több file írást nem tudott a program végrehajtani, hiszen nem volt a kártya a helyén. Azt, hogy belül mi történt, nem tudom, de hiba nélkül folytatta a file írását a program. Szóval szerintem ez működik, lehet használni. Ebből az a tanulság, ha nincs probléma, akkor nem kell megoldani.
Annak aki SD kártya használatra adja a fejét, gondolnia kell a memória igényre. Az SD kártya kezelésére található könyvtárak mindegyike memóriazabáló. Legalább 10kbyte-ot elvesz a rendelkezésre álló flash memóriából. Ez ebben a programban nem okozott problémát, de sikerült olyan adatgyűjtő programot írnom, ahol sajna nem fértem bele a 32Kbyte-ba. Erre megoldásként javasolni tudom a külön datalogger modult, ami gyakorlatilag ugyanannyiba kerül, mint egy SD kártya modul. Ez azonban tartalmaz egy ATmega mikrovezérlőt, és önmagában tartalmazza a leírása szerint a szükséges programokat, és használatához már csak I2C kapcsolat szükséges. Már megérkezett aliexpressz-ről, de nem volt még időm kipróbálni. Így néz ki:

forrás: https://www.aliexpress.com/item/32959138610.html?spm=a2g0s.9042311.0.0.27424c4d81zskG

A program többi része a DS3231 RTC óramodul leírt programmal azonos. Nem is másoltam a forrásba, ha valaki ki akarja próbálni a programot, akkor onnan ide kell másolgatni a hiányzó függvényeket. A fordító jelezni fogja, hogy mi hiányzik. A forrás sorainak számát nagyon megnöveli, hogy az RTC óra lekérdezését egy függvénykönyvtár alapján megírtam magamnak. Ha ez valakit zavar, a számtalan előre megírt függvénykönyvtár valamelyikét érdemes használni, és sokkal rövidebb lesz a kód. Sőt, ha az RTC óra modul leírásánál használt könyvtárat telepíti, akkor valószínűleg változtatás nélkül futni fog az itt található kód, csak a program elején “#include”-olni be kell a függvénykönyvtárat.

A kód:

#define CLOCK_ADDRESS 0x68  //a modulon található óra IC címe az I2C buszon. A cím vezetékek átforrasztásával
                            //változthat
#include <Wire.h>
#include <LiquidCrystal_I2C.h>  //I2C LCD kezelő könyvtár
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  //LCD paraméterek megadása
#include <SD.h>
#define SD_POWER 8

File temp_adat;

int masodperc,perc,ora,nap,honap,ev,het_napja;
bool h12=true;             //ha true, akkor 12 órás üzemmód, false esetén 24 órás üztemmód
bool PM;              //12 órás üzemmód esetén a délelőtt délután jelzése fals=AM, true=PM
float temperature;
long lepes=millis();
long rogz_ido=millis();
long light_ido=millis();
int elozoperc=100;
String datum;
String ido;
String filenev=String("TEMP_1.CSV");
byte letrehozas=0;
String error=String("");

void setup() {
  pinMode(2, INPUT);

  Wire.begin();  // I2C busz használat indítása
  /*  setClockMode(false); //true értékkel 12 órás, false értékkel 24 órás üzemmód, ha átállítod az üzemmódot
                      //ujra be kell állítani az órát ( setTime() ), mert fals eredményt ad vissza.  
  masodperc=0;perc=34;ora=19;het_napja=7;nap=18;honap=7;ev=16; //óra beállításhoz az értékek
  setTime();   //óra beállítása */

  getTime();
  temperature=getTemperature();
  date_format();
  time_format();
  error="SD OK!";
  if (SD.begin(10)) {
    if (!SD.exists(filenev)) {
      temp_adat = SD.open(filenev, FILE_WRITE);
      temp_adat.println("Datum;Ido;Homerseklet;");
      error="File create OK!";
    }
  }
  else {error="No SD";}
  lcd.begin(16,2); //LCD inicializálása
  lcd.backlight();      //háttérvilágítás bekapcsolása
  lcd.print(error);
  delay(3000);
  lcd.noBacklight();
}

void loop() {
  if (digitalRead(2)==LOW) {lcd.backlight();light_ido=millis();}
  //30 percenként sd kártyára írunk
  if (millis()>rogz_ido+1800000){
    getTime();
    temperature=getTemperature();
    date_format();
    time_format();
    temp_adat.print(datum+";"+ido+";");
    temp_adat.print(temperature);
    temp_adat.println(";");
    temp_adat.flush();
    lcd.backlight();
    lcd.setCursor(14,1);
    lcd.print("+");
    rogz_ido=millis();
    light_ido=millis();
  }
  //5 másodperc után kikapcsoljuk az LCD háttétvilágítását
  if (millis()>light_ido+5000){
    lcd.setCursor(14,1);
    lcd.print(" ");
    lcd.noBacklight();
  }
  //másodpercenként frissítjük az LCD-n az időt
  if (millis()>lepes+1000) {
    getTime();            //kiolvassuk az időt a DS3132-ből a "masodperc, perc, ora, het_napja, nap, honap, ev" változókba
    if (elozoperc!=perc) {
      date_format();
      time_format();
      lcd.setCursor(0,0);
      lcd.print(datum);
      lcd.print(" ");
      lcd.print(ido);
      temperature=getTemperature();
      lcd.setCursor(0,1);  
      lcd.print(temperature);
      lcd.print(" C");
      elozoperc=perc;
    }
    lepes=millis();
  }
}

void date_format() {
  datum="";
  datum="20"+String(ev)+".";
    if (honap<10) {
      datum=datum+"0";
    }
    datum=datum+String(honap)+".";
    if (nap<10) {
      datum=datum+"0";
    }
    datum=datum+String(nap);
}

void time_format() {
  ido="";
  if (ora<10) {
    ido="0";
  }
  ido=ido+String(ora)+":";
  if (perc<10) {
    ido=ido+"0";
  }
  ido=ido+String(perc);
}

byte bcd_Dec(byte val) {
// Ckonvertál bcd számból decimalisba
  return ( (val/16*10) + (val%16) );
}

byte dec_bcd(byte val) {
// Convertál decimalis számból bcd-be
  return ( (val/10*16) + (val%10) );
}

Mennyire volt hasznos amit olvastál?

Kattints egy csillagra az értékeléshez!

Sajnálom, hogy amit olvastál nem volt hasznos számodra!

Szeretném ha elégedett lennél!

Írd le kérlek, hogy mi nem tetszett!?