semaver
New member
İzler Bırak – Arduino ile Verilerin Kaydı
Sadece sensörler kullandığınızda değil, bazı Arduino projeleri veri kalıcı olarak kaydetmek ister. Ölçülen değerlere ve diğer verilere ek olarak, kayıtlar tarih ve saat damgaları içermelidir. Zamanın kaydı gerçek saatlerle gerçekleşebilir. Boyut nedeniyle, (mikro) SD kartlar kalıcı koruma için uygundur. Bu makale projelerinizin nasıl eklenebileceğini göstermektedir.
Adafruit Datologger-Child
Arduino için gerçek zamanlı ayrı SD kartlar ve RTC/Saat saati vardır. Okuyucunun aşağıda gösterdiği gibi SD kartlar, üreticiyi çevrimiçi ticarette birkaç avro için alıyor. Örneğin, fotoğraftaki okuyucu yaklaşık 3.68 Euro'dur. Genel olarak, SPI kartları Arduino kartlarıyla iletişim sunar ve maksimum 2 GB kapasiteli Micro SD'yi destekler.
SD kart okuyucusu 3.3 V mantık gerektirdiğinden, karşılık gelen 5V/3.2 V seviye değişikliği zaten kartlarda.
SD kartları FAT16 veya FAT32 formatında bulunmalıdır. Ayrıca, bu konudaki dosyalar ve klasörler 8.3 formatına uymalıdır (örneğin: logfile1.txt). Dikkat: Dosya adları söz konusu olduğunda, sistem dosyası küçük sermaye ve yazı arasında ayrım yapamaz. Üretici, geliştirme hesap makinesinde ilgili bir biçimlendirme programı aracılığıyla bir SD kartın biçimlendirmesini gerçekleştirebilir. SD Derneği, indirmek için çeşitli işletim sistemleri için böyle bir program sunar.

Logic 3.3V ile mikro SDS için bir SD kart
(Resim: Eckstein-Shop.de)
Zaman damgalarını kullanıma sunmak için Maker'ın gerçek bir zamanlamaya ihtiyacı vardır (rtc = gerçek zaman saati). Arduino kartı Arduino kartının enerjisinde başarısız olsa bile, yıllarca çalışacak bir düğme hücresindeki Arduino'dan bağımsızdırlar. İllüstrasyon i ile bir koparma tablosu gösterir2C Yaygın destek ve DS3231 veya DS1307'yi bloke edin.

Kraliyet Saat Kartı
(Resim: Smart-Prototyyping.com)
Bu sekme, 6-7 Euro düğmesinin hücresi de dahil olmak üzere dahildir. Buna ek olarak, perakendeciler ayrıca PCF8523 gibi diğer tuğlalarla yönetmenler panoları sunar.
SD kartların eşzamanlı kullanımı ve veri kaydı için gerçek zamanlı bir izleme çok mantıklı olduğundan, şimdi SD ve RTC kartı okuyucu da dahil olmak üzere birleşik verioggerlerden kalkanlar da var. Bu bölümdeki örnek proje için, örneğin, Adafruit Dataggger-Child kullanılır (illüstrasyona bakınız).
Kart ayrı RTC/SD kartlarından/SD kartlardan daha büyüktür, ancak Birleşmiş Milletler, Mega, Leonardo veya ikide bir kalkan olarak yükseltilebilir. Ayrıca daha büyük SD kartları da destekler. Tabii ki, mikro-SD'ler adaptörlerle de kullanılabilir. Yazar, daha küçük devrelere izin veren kalkandaki prototipleme alanını seviyor.
Adofrude çevrimiçi mağazasında, kalkan 13,95 $ karşılığında satın alınabilir. Pahalı kalkanlar eBay'de yaklaşık 8 Euro maliyeti. Çin'de sipariş vermeye cesaret ederseniz, 3 Euro'dan daha az bir süre bulabilirsiniz.
Adafruit tarafından PDF formatında sağlanan talimatlara ek olarak, çevrimiçi bir öğretici de vardır.

Gerçek Zamanlı İzleme ve SD Kartlar Okuyucu ile Datologger-Sludo
(Resim: adafruit.com)
Logger verilerinin kalkanına sahip devre
Bir uygulama örneğinde, bir TMP36 sıcaklık sensörü Arduino-un'a veya veri kutusunun kalkanına bağlanır. Bu örnekte, sıcaklık ölçümü periyodik olarak yapılmalıdır. Ölçümler arasındaki süre kodda tanımlanabilir.
Fritzing diyagramı, izleyicinin düz tarafına sahip sensörü gösterir. Sensör, 5 V güç voltajı (solda) ve bir tane toprak (sağ) için bir girişe sahiptir. Buna ek olarak, ortada kullanıcının Birleşmiş Milletler örneğinde Aalogo A0'a bağlandığı bir veri çıktısı.

Adofrude Veri Logger ve TMP36-TEMPATE sensörünün kalkanıyla kolay devre
Program açısından, SD kartlara ve gerçek zamanlı saatlere doğrudan erişim mümkün olacaktır, ancak oldukça hata ve karmaşık olacaktır. Bunun yerine, çeşitli kütüphaneler bir alternatiftir. Mevcut kütüphanelerin miktarı oldukça çekici.
Zaman ölçümü için rtclll
Gerçek saatlere erişim için mükemmel bir kütüphane var Rtclll. Bu zaten Arduino fikrine kuruldu. Bunları gerçekten kurmak için, geliştiriciler Arduino-Aid Kütüphane İdaresi'ni arıyor Rtclll:
- Eskiz | Kütüphaneyi ekleyin | Kütüphaneleri yönetin …
Programlarımızda kütüphaneyi aşağıdaki ifadelerle kullanıyoruz.
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc; // Zugriff auf RTC
Hiçbir saat bağlı değilse, taslak sorunu tedavi etmelidir.
if (! rtc.begin()) { // Keine Uhr entdeckt
Serial.println("Echtzeituhr fehlt");
// Fehlerbehandlung
}
Saat mevcutsa, ancak henüz tarih ve saatle başlatılmamışsa, program bilgileri buna göre belirtir. Örnek parçasında, saat ve tarih, eskizin aktarılan süresinin yardımıyla belirlenir. Tabii ki, her şey dolaylı olarak veya bir NTP sunucusuna bir istek de olabilir.
if (! rtc.isrunning()) { // Uhr schon gesetzt?
Serial.println("RTC bisher noch nicht gesetzt!");
// => Initialisiere Zeit und Datum auf Datum/Zeit des Host-PCs
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
Şimdi gerçek saat istediğiniz zaman sorgulanabilir:
DateTime jetzt = rtc.now();
Serial.print(jetzt.year(), DEC);
Serial.print('/');
Serial.print(jetzt.month(), DEC);
Serial.print('/');
Serial.print(jetzt.day(), DEC);
Serial.print(" ");
Serial.print(jetzt.hour(), DEC);
Serial.print(':');
Serial.print(jetzt.minute(), DEC);
Serial.print(':');
Serial.print(jetzt.second(), DEC);
Serial.println();
SD kartlarda veri kaydı için SDFAT
Arduino fikrinde SD kartlar için zaten entegre bir kütüphane var ( SD). Ancak yazar, kütüphaneyle ilgili bazı sorunlarla karşılaştı ve alternatif olarak kütüphaneyi kullandı Sdfat.
Geliştiriciler bu kütüphaneyi .zip dosyası gibi bir GitHub web sitesinden indirir. İşte onların URL'leri.
Öyleyse IDE'yi duyuralım:
- Eskiz | Kütüphaneyi ekleyin | .Zip kitaplığını ekleyin
Kütüphaneyi kullanmak için çeşitli anlaşmalar gereklidir:
#include <SPI.h>
#include "SdFat.h"
// Chip Selector auf Arduino Board
const uint8_t chipSelect = SS;
// Separatorzeichen für Dateiausgabe
const String SEP = ";";
// Zugriff auf Dateisystem der SD Card
SdFat sd;
// Log-Datei
SdFile datei;
// Fehlermeldungen im Flash ablegen.
#define error(msg) sd.errorHalt(F(msg))
Aşağıdaki kodda, kart dosya sistemine erişmek için bir nesne başlatırız. Yarı hızda çalışıyorum (Sp_half_speed), aynı zamanda içinde Spi_full_speed Sonunda sorun yoksa değişebilir.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { // Zugriff auf SD
sd.initErrorHalt();
}
Örneğin, yeni veya mevcut bir dosya aşağıdaki gibi oluşturulabilir ve açılabilir:
if (datei.open(dateiName, O_CREAT | O_WRITE | O_EXCL)) {
// alles ok => Daten schreiben
}
Şimdi program açık dosyaya bir veri kaydı yazabilir:
datei.print("Die Antwort lautet ");
datei.print(42);
datei.println("!!!");
Veri kayıplarından kaçınmak için, özellikle yazma işlemleri hızlı bir şekilde izliyorsa, aşağıdaki kod bir yazma işleminin sonunda idealdir:
if (!datei.sync() || datei.getWriteError()) {
error("Schreibfehler!");
}
Dosya bloğu aşağıdaki kodları kullanarak çalışır:
datei.close();
eskiz
Örnek proje için aşağıdaki program üç özellik içerir:
- TMP36 sensörü üzerinden sıcaklık ölçümü
- Gerçek Saat
- SD kart okuyucu
Her yinelemede, sıcaklık ilk olarak okunur (temperaturInCMessen()), zaman ve tarihin yakalanması (DateTime jetzt = rtc.now()) ve kayıt dosyasına bir veri kaydı yazın: schreibeMessung(temperaturInC, "C", jetzt)
Veri yazımı CSV formatında (virgülden ayrılmış değer) gerçekleştirilir, çünkü bu dosyalar daha sonra elektronik tablolarla okunabilir ve değerlendirilebilir.
Ölçüm ve kayıt, rastgele bir sayı 1'e karşılık gelene kadar gerçekleşir. Uygulamada, elbette, farklı bir dönem koşul devreye girer, pin 2 veya 3 için harici kesintilerin nasıl tetikleneceği.
Verilerin satın alınması tamamlanır tamamlanmaz, kullanıcı SD kartı kaldırabilir ve bir Windows/macOS/Linux bilgisayarında değerlendirebilir. Aşağıdaki şekilde bir örnek bulunabilir.

Eskiz tarafından oluşturulan CSV dosyası, hesaplama sayfası yazılımında kolayca değerlendirilebilir
Basılı program örneğini projeleriniz için temel olarak da kullanabilirsiniz.
/////////////////////////////////////////////////////////////////
//
// Datalogger Demo (c) Michael Stal, 2016
//
// Messung der Temperatur an einem TMP36
// Zeitverarbeitung mit RTClib (Chip DS1307, über IIC)
// SD Card Zugriff mit SdFat (über SPI MISO/MOSI)
// RTC und SD Card entweder separat angeschlossen
// oder über Adafruit Datalogger Shield
//
/////////////////////////////////////////////////////////////////
// ******************** DEKLARATIONEN ***************************
/////////////////////////////////////////////////////////////////
// DEKLARATIONEN RTC (Echtzeituhr)
/////////////////////////////////////////////////////////////////
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc; // Zugriff auf RTC
char WochenTage[7][12] = {"Sonntag",
"Montag",
"Dienstag",
"Mittwoch",
"Donnerstag",
"Freitag",
"Samstag"};
/////////////////////////////////////////////////////////////////
// DEKLARATIONEN SD Card
/////////////////////////////////////////////////////////////////
#define LOGDATEI "TMP36"
#include <SPI.h>
#include "SdFat.h"
// Chip Selector auf Arduino Board
const uint8_t chipSelect = SS;
// Separatorzeichen für Dateiausgabe
const String SEP = ";";
// Zugriff auf Dateisystem der SD Card
SdFat sd;
// Log-Datei
SdFile datei;
// Fehlermeldungen im Flash ablegen.
#define error(msg) sd.errorHalt(F(msg))
/////////////////////////////////////////////////////////////////
// DEKLARATIONEN TemperaturSensor
/////////////////////////////////////////////////////////////////
const int TMP36Pin = A0;
const float VersorgungsSpannung = 5.0; // ändern für 3.3V
const int ZeitZwischenMessungen = 5; // in Sekunden
// ********************** METHODEN ******************************
/////////////////////////////////////////////////////////////////
//
// initRTC()
// Echtzeituhr initialisieren
//
/////////////////////////////////////////////////////////////////
void initRTC()
{
if (! rtc.begin()) { // ist eine Uhr angeschlossen?
Serial.println("Echtzeituhr fehlt");
while(1); // Fehlerschleife
}
if (! rtc.isrunning()) { // Uhr schon gesetzt?
Serial.println("RTC bisher noch nicht gesetzt!");
// => Initialisiere Zeit und Datum auf Datum/Zeit des Host-PCs
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
/////////////////////////////////////////////////////////////////
//
// initSDCardReader()
// Kartenleser initialisieren
//
/////////////////////////////////////////////////////////////////
void initSDCardReader()
{
const uint8_t NAMENSLAENGE= sizeof(LOGDATEI) - 1;
char dateiName[13] = LOGDATEI "00.csv"; // Z.B. TMP3604.csv
delay(1000);
// SD Card mit SPI_HALF_SPEED initialisieren, um Fehler
// bei Breadboardnutzung zu vermeiden. Sonst => SPI_FULL_SPEED
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { // Zugriff auf SD?
sd.initErrorHalt();
}
// Dateiformat 8.3
if (NAMENSLAENGE > 6) {
error("Dateipräfix zu lang");
}
// Standarddateiname LOGDATEI + laufende Nummer, z.B.
// TMP3603.csv
// Sobald alle Suffixe 00..09 verbraucht sind,
// geht es von vorne los: round robin
while (sd.exists(dateiName)) {
if (dateiName[NAMENSLAENGE + 1] != '9') {
dateiName[NAMENSLAENGE + 1]++;
}
else if (dateiName[NAMENSLAENGE] != '9') {
dateiName[NAMENSLAENGE + 1] = '0';
dateiName[NAMENSLAENGE]++;
}
else {
error("Kann Datei nicht erzeugen");
}
}
// Jetzt öffnen:
if (!datei.open(dateiName, O_CREAT | O_WRITE | O_EXCL)) {
error("Datei öffnen misslungen!");
}
Serial.print(F("Logging auf: "));
Serial.println(dateiName);
// Header schreiben
schreibeHeader();
}
/////////////////////////////////////////////////////////////////
//
// setup()
// Echtzeituhr und SD Card Leser initialisieren
//
/////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600); // Serielle Kommunikation an
initRTC(); // Echtzeituhr initialisieren
initSDCardReader(); // SD Card initialisieren
}
/////////////////////////////////////////////////////////////////
//
// temperaturInCMessen()
// Temperatur vom TMP36 über Analogeingang lesen
//
/////////////////////////////////////////////////////////////////
float temperaturInCMessen()
{
int digitalWertTmp36 = analogRead(TMP36Pin); // A0 einlesen
float messwertSpannung = digitalWertTmp36 * VersorgungsSpannung / 1024.0;
Serial.print("Spannung gemessen an Analogeingang ");
Serial.print(TMP36Pin);
Serial.print(" => ");
Serial.println(messwertSpannung);
// Wir berücksichtigen ausschließlich Celsius
float temperaturInC = (messwertSpannung - 0.5) * 100;
Serial.print("Temperatur in C = ");
Serial.println(temperaturInC);
return temperaturInC;
}
/////////////////////////////////////////////////////////////////
//
// ausgebenZeit()
// Zeitausgabe zur Diagnose
//
/////////////////////////////////////////////////////////////////
void ausgebenZeit(DateTime jetzt) // easy Code
{
Serial.print(jetzt.year(), DEC);
Serial.print('/');
Serial.print(jetzt.month(), DEC);
Serial.print('/');
Serial.print(jetzt.day(), DEC);
Serial.print(" (");
Serial.print(WochenTage[jetzt.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(jetzt.hour(), DEC);
Serial.print(':');
Serial.print(jetzt.minute(), DEC);
Serial.print(':');
Serial.print(jetzt.second(), DEC);
Serial.println();
}
/////////////////////////////////////////////////////////////////
//
// loop()
// In jeder Iteration
// Temperatur messen
// Zeit erfassen
// Daten auf SC Card schreiben
// Terminierungsbedingung prüfen und ggf. stoppen
// inkl. Dateischließen!
//
/////////////////////////////////////////////////////////////////
void loop()
{
// Messwert am TMP36 auslesen
float temperaturInC = temperaturInCMessen();
// Vorgegebene Zeit warten
delay(ZeitZwischenMessungen * 1000);
// Datum & Zeit holen:
DateTime jetzt = rtc.now();
ausgebenZeit(jetzt); // und schreiben am seriellen Monitor
// Jetzt Daten schreiben:
schreibeMessung(temperaturInC, "C", jetzt);
// Zufallsmechanismus für Stopp der Messungen
if (random(7) == 1) {
dateiSchliessen();
}
}
/////////////////////////////////////////////////////////////////
// Statt in einer .csv-Datei könnte man z.B. auch im JSON Format
// speichern !!!
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
//
// schreibeHeader
// Schreiben von Header Information in Datei
//
/////////////////////////////////////////////////////////////////
void schreibeHeader() {
datei.println(F("Temperaturmessungen mit TMP36 mit Nutzung eines Dataloggers"));
datei.print(F("Datum"));
datei.print(SEP);
datei.print(F("Zeit"));
datei.print(SEP);
datei.print(F("Temperatur (Einheit Celsius)"));
datei.println();
}
/////////////////////////////////////////////////////////////////
//
// schreibeMessung()
// messwert nehmen und in gewählter Einheit ausgeben
// und zusammen mit Datum und Uhrzeit in Datei schreiben
//
/////////////////////////////////////////////////////////////////
void schreibeMessung(float messwert,
String einheit,
DateTime jetzt)
{
datei.print(jetzt.day());
datei.print(".");
datei.print(jetzt.month());
datei.print(".");
datei.print(jetzt.year());
datei.print(SEP);
datei.print(jetzt.hour());
datei.print(":");
datei.print(jetzt.minute());
datei.print(":");
datei.print(jetzt.second());
datei.print(SEP);
datei.print(messwert);
datei.print(einheit);
datei.println();
// Dateisync, um Datenverlust zu vermeiden:
if (!datei.sync() || datei.getWriteError()) {
error("Schreibfehler!");
}
}
/////////////////////////////////////////////////////////////////
//
// dateiSchliessen()
// Datei wieder schließen
//
/////////////////////////////////////////////////////////////////
void dateiSchliessen()
{
datei.close();
Serial.println(F("Datei steht bereit!"));
SysCall::halt();
}
// ********************** DATEIENDE *****************************
Özet
Herhangi bir önemsiz proje, herhangi bir geçici kayıt veya kalıcı depolama veya protokol biçimi gerektirir. Bu, bir okuyucu tablosu (Micro) SD kart okuyucu ve gerçek zamanlı bir saat kartı gerektirir. Veya alternatif olarak her ikisini de birleştiren bir kalkan. Bu donanım küçük teklife karşı satın alınabilir. İlgili kütüphanelerin kullanımı, programlama çabalarını kısıtlı sınırlar içinde de sürdürür. 2 GB SD kartla sık sık sınırlamanın uygulanması kolaydır. Yani hiçbir şey projelerinizi genişletmek için engellemiyor.
()