SD-Logger III. - Mit is mentsünk?

Az adatgyűjtő rendszerek kritikus pontja az adatmentés helye. Erre jelen esetben az SD kártya a legalkalmasabb, hiszen az egységnyi adatra jutó ára ennek a tárolótípusnak a legkedvezőbb. Összehasonlítva az egyéb memóriákkal:

Memóriakép Típus Ár
Belső EEPROM
128 byte ... 4096 byte
Chip árában beépítve
I2C EEPROM
1 kbit (128 byte) ... 1024 kbit (128 kbyte)
150..1.000 Ft/db
128 MByte .. 128 GByte 1.000 .. 16.000 Ft


Hát, az ilyen összehasonlítás nem vezet sehova :(. A mentendő adat oldaláról egyszerűbb megközelíteni. Itt sok adatot mentenénk és PC-re átvinnénk. Így az SD kártyára esett a választás. Az adatgyűjtőn egyszerű SD kártyafoglalat került kialakításra. Így átalakítóval akár uSD is illeszthető a rendszerhez.
Az SD-kártya nagyon nagy előnye - amit itt ki is használunk, -  hogy olyan adathordozó, ami mind mikrokontrolleres környezetben, mind PC-s világban használható.

A háttértárunk mikrokontrollerrel írható-olvasható, míg a PC oldalon az adatok kinyerésére két lehetőségünk van:

  • soros/usb porton át letöltve,
  • kártyaolvasóval közvetlenül.

A soros letöltés során az adatátvitel 115.200 bps, azaz kb. 15 kbyte/sec. Az SD kártyáról közvetlenül olvasva ez 1-10 Mbyte/sec! Azaz 1 Mbye adat esetén közvetlenül néhány sec alatt, sorosporton jónéhány perc alatt lehetséges a letöltés. Így lehetőségként felmerül, hogy az Arduino a PC felé kártyaolvasóként jelentkezzen be. Azonban ez más processzort és más környezetet igényelne (pl. AT90USB128 chippel ez megvalósítható). Így inkább a kártyaolvasóra lenne szükség. Természetesen, - ha van beépített olvasónk a laptopunkban, - akkor az is használható.

Az Arduino oldalán az SD alapú adatgyűjtőhöz minimum ATMega328 chipre van szükség. Ez lehet a Mega panelek ATMega1280 vagy ATMega256 chipje is. Az ATMega168 illetve ATMega8 chippel az SD kártya - a kis belső memória miatt - nem kezelhető! A kisebb chipes rendszerek chipcserével egyszerűen feljeszthetőek (link). Az SD kezelés önmagában kb. 1kbyte SRAM-ot igényel!

Kártyaelőkészítés

A frissen vásárolt SD kárytát le kell formázni. Ennek során kerül létrehozásra az a logikai adattárolási rendszer, ami a mentett adatok olvashatóságát biztosítja a PC illetve a mikrokontrolleres környezetben. Előfordul, hogy a kártyánk már gyárilag formázott. Ebben viszont sosem lehet megbízni, hogy milyen logikai rendszerben sikerült a gyárban elvégezni. Az SD kártyákat FAT16 vagy FAT32 rendszerben tudjuk használni. Fontos! A 32 MB-nál kisebb kártyák FAT12-ben kerülnek formázásra, azaz ezen a módon formázott kártyák mikrokontrolleres környezetben nem használhatóak!
A formázásnál a kártya tartalma elveszik, így ha fényképek vagy MP3 gyűjtemény van rajta, akkor előtte menteni kell!
Fontos! Az SD kártyán nem lehet fizikai vagy logikai hiba (ún. Bad sector). A PC-s világgal ellentétben, nincs hibajavító-hibakezelő algoritmus!

A formázásra több lehetőség is kínálkozik. A legegyszerűbb az operációs rendszerbe beépítettet használni - igaz itt sokminden nem állítható, de nem is szükséges. Ha tudni akarjuk, mi van a háttérben, akkor hardware-közeli megoldásokat is találhatunk a gyártók oldalán vagy az sdcard.org oldalon. Például: https://www.sdcard.org/downloads/formatter_3/

Beszélgessünk a kártyával

Az SD kártyák kezelésére számos függvénykönyvtárat találhatunk az interneten szétszórva. Azonban a legegyszerűbb az Arduino eredetileg már beépített eljárásgyűjteményét használni. Az Arduinoban az 1.x kiadásokban ez a Library-SD - Examples alatt található. A régebbi (Arduino-00xx) rendszerek esetén ezeket még külön kellett összeszedegetni.
Ha ilyen külön fellelhető letölthető függvénykönytárat keresünk, akkor ezek a github oldalán, az vagy az adafruit lapjain is megtalálhatóak. Ezen eljárások használata azonban csak akkor javasolt, ha valamely program külön igényli! Sok inkompatibilis, verziófüggő kiadás kering mindenfelé, - melyek során a keretrendszer verziószáma, a fordítandó mintaprogram és járulékos függvénykönyvtárak kölcsönös függőségei is problémát okozhatnak.
Az Arduino Mega rendszerek esetén az SPI busz kezelése (amin át a kártya csatlakozik) eltérő. Ennek oka, hogy a korai rendszerek hardware kimenetei csak részben feleltethetőek meg az új rendszerekkel. Míg a soros kommunikáció, analóg kivezetések a helyükre kerülhettek, addig az SPI busz, az I2C/wire nincs fedésben. Ilyen "áthelyezett" esetekben van mód pl. szoftveres emulációra.
Az SPI esetén a paraméterek közt az SDCard.h állományban lehet ezt beállítani.

Arduino alatt a kártyák megszólítása az SDCardInfo programmal a legegyszerübb. Ez a minta semmit sem ír a kártyára, csak megpróbálja a kapott válaszokat értelmezni és a képernyőre kiirni. Előnye, hogy bármilyen SD kártyával együttműködik.

/*
  SD card test
  (c) TavIR http://www.tavir.hu
 
 This example shows how use the utility libraries on which the''
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you''re not sure whether
 its working or not.
     
 The circuit:
 ** SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module. (Pin 8)

 Tested via Arduino 1.0.2
 
  Founded at arduino.cc forum
  Modified 12 March 2013
  by TavIR / Robert Cseh
 
  This example code is in the public domain.
 */

 // include the SD library:
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// SDLogger shield: pin 10
const int chipSelect = 10;    

void setup()
{
  Serial.begin(9600);

  Serial.print("\\nInitializing SD card...");
  // On the SD Logger shield, CS is pin 10.
  pinMode(10, OUTPUT);     // change this to 53 on a mega

  // we''ll use the initialization code from the utility libraries
  // since we''re just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is inserted?");
    Serial.println("* Is your wiring correct?");
    Serial.println("* did you change the chipSelect pin?");
    return;
  } else {
   Serial.println("Wiring is correct and a card is present.");
  }
  // print the type of card
  Serial.print("\\nCard type: ");
  switch(card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }
  // Now we will try to open the ''volume''/''partition''
  // - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.");
    Serial.println("Make sure you''ve formatted the card");
    return;
  }

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
 
  volumesize = volume.blocksPerCluster();
    // clusters are collections of blocks
  volumesize *= volume.clusterCount();
    // we''ll have a lot of clusters
  volumesize *= 512;
    // SD card blocks are always 512 bytes
  Serial.print("Volume size (bytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
 
  Serial.println("\\nFiles found on the card: ");
  root.openRoot(volume);
 
  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}

A programkód elején találjuk meg a chipselect kezelését. Ez az a jelzőláb, amivel az adott eszköz felé jelezhetjük, hogy vele akarunk beszélgetni. Az SPI buszon az értékes kommunikációs csatornán nem történik eszközkiválasztás. - ott csak az adatcsere zajlik! (Az I2C/TWI buszon az adatcsere és az eszközkiválasztás is közös felületen történik - csökkentve a sávszélességet). Az SD Logger kártyán a kiválasztásra a D10-es kivezetést használja a shield, míg ha ethernet kártyát használunk, akkor az SD kiválasztása a D4 kivezetésen át zajlik.

Ha a programkódot megnéztük és átmásoltuk az Arduino keretrendszerbe, akkor a fedpanelbe helyezve az SD-kártyát, majd feltöltve a kódot - ellenőrihetjük a működést. Megnyitva a terminálablakot (jobb felső ikon) a sebességet jobbra lenn át kell állítani 9600 bps-re. A mintakód ilyen gyorsan küldi az adatokat. A képernyőn valami ilyesmit kell látnunk:


A FAT16 és FAT32 is szépen látszik. (Amin teszteltem, az egy 2 GB-s Kingston és egy 8 GB-s Samsung volt.)
Ha hibás vagy nem FAT16/FAT32 formázott kártyát sikerül tesztelni, akkor erre a program hibaüzenetet ad (Próbáld ki: vedd ki a kártyát és úgy tesztelj!).

A kártyák minden esetben válaszolnak a megszólításra: kivéve, ha hibásak vagy a chipselect kiválasztása nem a megfelelő lábon történik. Az alap megszólítás a kártya gyártójának lekérdezése. Ez a kártyákban fixen "drótozott", és még a logikai filerendszer alatti szinten mozog. Így lehet a kártya akár ext2/3, NTFS formázott is.
A legtöbb kártyahiba egyszerűen orvosolható egy formázással. Első kísérletként az operácós rendszer beépített formázójával érdemes megpróbálni. Ha nem sikerül, akkor a cikk elején emlegetett speciális formázóprogramokkal kell megpróbálni a "kezelését".

Bascom-AVR

A Bascom-AVR keretrendszerben a követlmények azonosak, mint az Arduino esetén: ATMega328, ATMega1280 vagy ATMega2560 chip. A szoftver oldala azonban már kérdéses...

Bascom-AVR alatt kétféle SD kártya kezelési megoldás létezik: az AVR-DOS és a KokkeKat FAT. Az AVR-DOS a klasszikus és a kiforrottabb. Fontos! Ha a szoftverrel pénzt keresünk, akkor az AVR-DOS könyvtárrendszer jogdíjköteles!

A kártya előkészítése az Arduinonál megismert módon történik és FAT16 vagy FAT32 szerkezetű lehet. A Bascom-AVR hardware-közeli megoldása miatt programkódban is több beállítási lehetőségünk van. A részleteket a bascom súgó illetve az eredeti forráskód is szépen körbejárja. Itt most lássuk a könyvtárszerkezet kilistázását:

''*********************************************
''* Title:      Test_DOS_Drive                *
''* About:      Tesing filesystem via AVR-DOS *
''*             and ATMega chips              *
''* Filename:   Test_DOS_Drive.bas            *
''* Compiler:   Bascom-AVR 2.0.7.5            *
''*                                           *
''* Author:     Robert Cseh                   *
''* E-mail:     avr /kukac/ tavir /pont/ hu   *
''* Homepage:   http://www.tavir.hu           *
''*********************************************

$regfile = "m328pdef.dat"
$crystal = 16000000

'' Adjust HW Stack, Soft-Stack and Frame size to 128 minimum each!!!

$baud = 9600
Open "Com1:" As Binary As #1
Config Clock = Soft
Enable Interrupts
Config Date = Mdy , Separator = .
Dim Btemp1 As Byte

Print #1 , "Wait for Drive"

''Include here you driver for Compactflash/HardDisk or other
''$include "Config_MMCSD_HC.bas"
$include "Config_MMC.bas"

If Gbdriveerror = 0 Then

  '' Include AVR-DOS Configuration and library
$include "Config_AVR-DOS.BAS"

  Print #1 , "Init File System ... ";
  Btemp1 = Initfilesystem(1)
     '' Partition 1
     '' use 0 for drive without Master boot record
  If Btemp1 <> 0 Then
     Print #1 , "Error: " ; Btemp1 ; " at Init file system"
  Else
     Print #1 , " OK"
     Print #1 , "Filesystem: " ; Gbfilesystem
     Print #1 , "FAT Start Sector: " ; Glfatfirstsector
     Print #1 , "Root Start Sector: " ; Glrootfirstsector
     Print #1 , "Data First Sector: " ; Gldatafirstsector
     Print #1 , "Max. Cluster Nummber: " ; Glmaxclusternumber
     Print #1 , "Sectors per Cluster: " ; Gbsectorspercluster
     Print #1 , "Root Entries: " ; Gwrootentries
     Print #1 , "Sectors per FAT: " ; Glsectorsperfat
     Print #1 , "Number of FATs: " ; Gbnumberoffats
  End If
Else
   Print #1 , "Error during Drive Init: " ; Gbdriveerror
End If

End

A feltöltés után a program futni kezd és megmutatja a kártya tartalmát:

Fontos! A Bascom-AVR alatt, ha nagyméretű kártyát akarunk kezelni (>2GB), akkor a program elején a $include "Config_MMCSD_HC.bas" sort kell engedélyezni. A teljes mintakódot a feltelepített Bascom-AVR: Samples és AVRDOS könyvtárában találjuk.

Kapcsolódó leírások:

Kapcsolódó áramkörök:

 

TavIR-Facebook