Arduino-suli: Kártyák a mikrovezérlődben
Arduino projektjeidet könnyen kiegészítheted memóriakártya-kezelési funkciókkal, és meg is mutatjuk, hogyan valósíthatod ezt meg.
Legtöbb hordozható eszközödben már jó ideje lehetőséged van arra, hogy egy aprócska kártya behelyezésével jelentős extra tárhelyet szerezz, az ilyen jellegű plusz adattárolási lehetőségnek pedig mikrovezérlős projektjeid során is hasznát veheted. Egy pöttöm, írható és olvasható memóriakártyával ugyanis rendkívül egyszerűen megvalósíthatod az információk tárolását, és bizony még jelentős helyigényt sem támaszt egy-egy ilyen modul, vagyis egyszerűen beépíthető akár már kész összeállításokba is.
Cikkünkben bemutatjuk, miként vetheted be mikrovezérlőd memóriakártya-olvasási és -írási funkcióit, illetve azt is, hogyan férhetsz hozzá ezekhez a fájlban tárolt információkhoz.
Előkészületek
Mivel mindössze a kártya írási és olvasási képességeivel szeretnél megismerkedni, extra hardveres komponensre (a kártyán és a csatlakoztatására képes modulon kívül) nem igazán lesz szükséged. Rengeteg formája létezik a csatlakoztatható kártyafoglalatoknak, cikkünkben egy 2,4 hüvelykes TFT-lapkát választottunk, amely a képernyő mellett egy fedélzeti kártyaolvasót is kínál felhasználóinak. Hogy megfelelően tudj dolgozni memóriakártyáddal, szükséged lesz egy kártyaolvasóra is, amelyet számítógépedhez csatlakoztatsz, hiszen egy ilyen eszköz segítségével ellenőrizheted legegyszerűbben a kártyára kerülő adatokat.
Emellett abban is segítségedre lehet a külső olvasó, hogy a megfelelő módon formázd a kártyádat, így elkerülheted az esetleges kellemetlenségeket. A formátum választásakor nem kell sokat gondolkodnod: az Arduino író-olvasó moduljai kivétel nélkül a FAT fájlrendszert kezelik, ezért erre kell váltanod, ha használni szeretnéd a kártyát.
Szöveges fájl a kártyára
Az első programkódban egy olyan alkalmazás elkészítésén vezetünk végig, amelynek segítségével memóriakártyád gyökérkönyvtárában létrehozhatsz, és a soros monitor beviteli mezőjén keresztül szöveges adattal feltölthetsz egy txt kiterjesztésű állományt. A fejlesztői környezet elindítását követően nyiss meg egy új állományt, és a setup() függvény előtt néhány külső csomag beemelésével indítsd ela kódodat.
Alapvetően két könyvtárra lesz szükséged a kommunikációs folyamatok és az írási műveletek problémamentes végrehajtásához: az SD-re, valamint az SPI-re (#include<SPI.h> #include<SD.h>). Ezek után egy File típusú, fajl nevű globális változót is hozz létre, a későbbiekben majd ezzel hivatkozhatsz a kártyádon található állományra. Ha elkészültél, ugorhatsz is a setup() belsejébe, ahol elsőként a soros monitoron nyiss egy portot (Serial.begin(9600);), majd a kommunikációs pinként használni kívánt 10-es csatlakozót is címkézd fel (pinMode(10, OUTPUT);).
Következhetnek az SD-kártyád csatlakoztatását ellenőrző lépések, ehhez pedig készítsd el az initSD() nevű függvényt, amit a kódsorod legvégére lépve hozz is létre a void initSD(){} sorral. A magjában egy kiíratással indíts (Serial.print("SD kartya elerese...");), majd egy feltételben reagálj arra, ha nem érhető el a memóriakártyád. Amennyiben ez az eset bekövetkezik, adj meg egy üzenetet, és zárd is le a függvény további futását (if (!SD.begin(10)){ Serial.println("elreres sikertelen!"); return; }).
Ha a folyamat nem lép ebbe feltételbe, akkor kiíratással jelezd a felhasználóknak, hogy a kártya beolvasása elkészült, és némi késleltetést is elhelyezhetsz (Serial.println("eleres kesz."); delay(1000);). Következhet a folyamatosan ismétlődő loop() függvény, amelynek első feltételében a soros monitor elérhetőségét kell ellenőrizned (if (Serial.available())). Minden egyéb interakciót csak a nyitott Serial felület esetén hajt végre a program, így az összes utasítást az if-en belül kell elhelyezned.
Az első lépés, hogy kiolvasod a beviteli mezőről elküldött információkat (String bejovo = Serial.readString();) majd megnyitod írási üzemmódban a fájlodat (fajl = SD.open("minta.txt", FILE_WRITE);). Ezek után már csak a fájl szerkesztése szükséges, amihez a megnyitott állományod elérhetőségét kell ellenőrizned egy feltétellel, majd a magjában a fajl.print(bejovo); és a fajl.close(); begépelésével végre is hajthatod az írási folyamatot. Ha hiba esetén szeretnél valamilyen kiírást, akkor ezt az else ágakban megteheted, de ez nem feltétlenül szükséges jelen esetben.
Amint elkészültél, töltheted is fel mikrovezérlődre a kódot, majd a soros monitor megnyitásával küldheted írásra az adatokat. Amennyiben úgy érzed, eleget bombáztad már információval a lapkádat, kártyaolvasód segítségével csatlakoztasd a microSD-t számítógépedhez, és ha mindent megfelelően hajtottál végre, akkor egy minta.txt állományt találsz felületén, benne az elmentett üzenetekkel.
Olvassunk kártyáról
Azt már tudod, hogyan töltheted meg információval a kártyádat, következő lépcsőként pedig megmutatjuk, miként hasznosíthatod a fájlban elhelyezett adatokat. Ehhez szintén a kijelzőbe épített memóriakártyát vetettük be, csupán annyit csavartunk az egészen, hogy a megjelenítő pixelei a kiolvasott RGB-kódok alapján változzanak. Ehhez elsőként két csomag telepítése szükséges (Eszközök/Könyvtárak kezelése…), hiszen csak így valósíthatod meg a kijelző megfelelő vezérlését.
Először is az MCUFRIEND_kbv csomagot installáld számítógépedre, majd az Adafruit GFX Libraryt, ezt követően pedig nyiss egy új projektet. Ismételten két fejállomány meghívására lesz szükséged, az egyik az előzőleg is használt SD, a másik pedig az újonnan telepítettekből elérhető UTFTGLUE (#include <UTFTGLUE.h> #include <SD.h>).
Ezenkívül itt is kell egy File típusú fajl, továbbá szükséged lesz egy szöveges állományra a számsorozatok tárolásához, egy tömbre, amelyben a számhármasokat tárolod, valamint egy kezdetben 0-ra állított, int típusú változót is érdemes bevetned (String szam; File fajl; int val = 0; int rgb[3];). Ha ezeket elhelyezted kódodban, a képernyőd adatátviteli portjait is élesítened kell a UTFTGLUE myGLCD(0,A2,A1,A3,A4,A0); segítségével.
A setup() függvényben nincs túlzottan sok teendőd, mindössze nyiss egy soros portot (Serial.begin(9600);), majd címkézd meg a kártyádhoz tartozó 10-es pint (pinMode(10,OUTPUT); végül hívd meg a kijelződ beállításához tartozó beépített függvényt ( myGLCD.InitLCD();). Másold át a loopba az előző kódod initSD() függvényének tartalmát a késleltetésig, és a beillesztett kódrészlet mögött nyisd meg a kártyádon található állományt a fajl = SD.open("test.txt"); sorral, majd az előző programhoz hasonlóan itt is a sikeres fájlmegnyitást vizsgáld egy feltételben ( if(file){} ), amelynek magjában indíts egy while függvényt.
Ez egészen addig fusson, amíg a fájlod elérhető (while(fajl.aviable()){}), és a belsejében hajtsd végre a fájlod elválasztókarakterenkénti olvasását (figyelj oda arra, hogy a txt-ben a számok vesszővel elválasztva szerepeljenek, előre állítsd be, akár az előző program segítségével), és a konvertált formáját tárold el az rgb-tömbödben (szam = fajl.readStringUntil(','); rgb[val]=szam.toInt();).
Még mindig ebben a while ciklusban maradva val változód értékére is hozz egy feltételt, és amennyiben ez a 2-es értéket veszi fel, az rgb értékeit állítsd be a képernyődön, majd egy kis késleltetést követően nullázd a val-t (myGLCD.setColor(rgb[0],rgb[1],rgb[2]); myGLCD.fillRect(0, 0, 320, 240); delay(3000); val=0;). Az else ágban minimális késleltetés mellett csupán a val növelését helyezd el (else{delay(100); val++;), majd a while függvényből kilépve zárd le a fájlodat (fajl.close();).
Ezzel el is készült a programod, amely a kártyádról olvasott színkódokkal képes kiszínezni a megjelenítődet, és mindezt egészen addig végrehajtja, amíg áramot kap. Szükség esetén kiírásokkal még kiegészítheted a programkódot, de ez már teljes egészében rajtad múlik.
Kód 1
#include <SPI.h>
#include <SD.h>
File fajl;
void setup() { Serial.begin(9600); pinMode(10, OUTPUT); initSD(); }
void loop(){
if (Serial.available()){ String bejovo = Serial.readString(); fajl = SD.open("proba.txt", FILE_WRITE);
if (fajl) {Serial.print("proba.txt fajlba iras..."); fajl.print(bejovo); fajl.close(); Serial.println("kesz."); delay(1000); Serial.println("Irja be a szamharmasokat ( helyes formatum: <szam>,<szam>,<szam>, )"); }
else { Serial.println("hiba a proba.txt megynitasa soran.");} } }
void initSD() {Serial.print("SD kartya elerese...");
if (!SD.begin(10)) { Serial.println("elreres sikertelen!"); return;}
Serial.println("eleres kesz."); delay(1000); Serial.println("Irja be az adatokat ( helyes formatum: <szam>,<szam>,<szam>, )"); }
Kód 2
#include <UTFTGLUE.h>
#include <SD.h>
String szam; File fajl; UTFTGLUE myGLCD(0,A2,A1,A3,A4,A0); int val = 0; int rgb[3];
void setup() {Serial.begin(9600); pinMode(10,OUTPUT);myGLCD.InitLCD();}
void loop() { if(!SD.begin(10)){ Serial.println("kartya megnyitasa sikertelen"); return;}
Serial.println("kartya elerheto:");fajl = SD.open("test.txt");
if(fajl) { Serial.println("test.txt megnyitasa:");
while(fajl.available()) { szam = fajl.readStringUntil(','); rgb[val]=szam.toInt();
if(val==2){ for(int i=0;i<3;i++){Serial.print(rgb[i]);} Serial.println(); myGLCD.setColor(rgb[0],rgb[1],rgb[2]); myGLCD.fillRect(0, 0, 320, 240); delay(3000);val=0; }
else{delay(100); val++; }}
fajl.close();} else {Serial.println("hiba a fajl megnyitasa soran");} }