Schreiben auf SD Karte, Buffer auffüllen

Hi Freaks,

Ich habe den datalogger mit dem adafruit Loggershield im Einsatz. Mittlerweile habe ich auch dort ein wenig ‘rumgespielt’ und bin im Sketch des ‘fridgeloggers’ auf die ’ << ’ beim Befüllen des Buffers gestoßen.

Verstehe ich dies richtig:

mit den ’ << ’ wird der buffer wie mit der FiLo Eimerkette befüllt und dann auf die SD Karte geschoben?

Leider ist im Sketch vieles mit den kompakten Einzeilern in For-next-Schleifen gelöst, dort muss ich mich noch tiefer hinein arbeiten.

Für das tiefere Verständnis möchte ich solch einen Buffer erstellen, füllen und dann auf die Serial und (später) auf die SD schreiben.

Geht so etwas? Kann ich dazu einfach den Buffer definieren, die Werte nacheinander hineinschieben? Wie bekomme ich die Daten dann auf die Serial?

Ich habe dazu momentan (zuviel) gelesen, mir fehlt da der Grundansatz, kann mir bitte einer von Euch die Denk/ Funktionsweise näher bringen?

Danke, Greetz, Linpotec

Naja, wenn Du den Sketch oder wenigstens einen Link posten würdest, könnte sich das jemand ansehen und Dir evtl. einen Tipp geben.
Mario.

Danke Mario,

Sorry, ich dachte das Shield, welches hier im Forum erwähnt wurde, ist ‘Standard’ und bekannt…

Also:

Das Shield:

Dieses Sketch habe ich ursprünglich verwendet:

// A simple data logger for the Adafruit Data Logging shield on a mega
// You must edit SdFatConfig.h and set MEGA_SOFT_SPI nonzero
#include <SdFat.h>
#include <SdFatUtil.h> // define FreeRam()
#include <I2cMaster.h>
#include <SoftRTClib.h>
#define CHIP_SELECT 10 // SD chip select pin
#define LOG_INTERVAL 1000 // mills between entries
#define SENSOR_COUNT 3 // number of analog pins to log
#define ECHO_TO_SERIAL 1 // echo data to serial port if nonzero
#define WAIT_TO_START 1 // Wait for serial input in setup()
#define ADC_DELAY 10 // ADC delay for high impedence sensors

#if defined(AVR_ATmega1280) || defined(AVR_ATmega2560)
#if !MEGA_SOFT_SPI
#error set MEGA_SOFT_SPI nonzero in libraries/SdFat/SdFatConfig.h
#endif // MEGA_SOFT_SPI
// Is a Mega use analog pins 4, 5 for software I2C
const uint8_t RTC_SCL_PIN = 59;
const uint8_t RTC_SDA_PIN = 58;
SoftI2cMaster i2c(RTC_SDA_PIN, RTC_SCL_PIN);

#elif defined(AVR_ATmega32U4)
#if !LEONARDO_SOFT_SPI
#error set LEONARDO_SOFT_SPI nonzero in libraries/SdFat/SdFatConfig.h
#endif // LEONARDO_SOFT_SPI
// Is a Leonardo use analog pins 4, 5 for software I2C
const uint8_t RTC_SCL_PIN = 23;
const uint8_t RTC_SDA_PIN = 22;
SoftI2cMaster i2c(RTC_SDA_PIN, RTC_SCL_PIN);

#else // defined(AVR_ATmega1280) || defined(AVR_ATmega2560)
// Not Mega use hardware I2C
// enable pull-ups on SDA/SCL
TwiMaster i2c(true);
#endif // defined(AVR_ATmega1280) || defined(AVR_ATmega2560)

RTC_DS1307 RTC(&i2c); // define the Real Time Clock object
// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];
//------------------------------------------------------------------------------
#if SENSOR_COUNT > 6
#error SENSOR_COUNT too large
#endif // SENSOR_COUNT
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
//------------------------------------------------------------------------------
// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
DateTime now = RTC.now();

// return date using FAT_DATE macro to format fields
*date = FAT_DATE(now.year(), now.month(), now.day());

// return time using FAT_TIME macro to format fields
*time = FAT_TIME(now.hour(), now.minute(), now.second());
}
//------------------------------------------------------------------------------
// format date/time
ostream& operator << (ostream& os, DateTime& dt) {
os << dt.year() << ‘/’ << int(dt.month()) << ‘/’ << int(dt.day()) << ‘,’;
os << int(dt.hour()) << ‘:’ << setfill(‘0’) << setw(2) << int(dt.minute());
os << ‘:’ << setw(2) << int(dt.second()) << setfill(’ ');
return os;
}
//------------------------------------------------------------------------------
void setup() {
// For Leonardo
while (!Serial) {}
Serial.begin(9600);

// pstr stores strings in flash to save RAM
cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

#if WAIT_TO_START
cout << pstr(“Type any character to start\n”);
while (Serial.read() < 0) {}
#endif // WAIT_TO_START

// connect to RTC
if (!RTC.begin()) error(“RTC failed”);

// set date time callback function
SdFile::dateTimeCallback(dateTime);
DateTime now = RTC.now();
cout << now << endl;

// initialize the SD card
if (!sd.begin(CHIP_SELECT)) sd.initErrorHalt();

// create a new file in root, the current working directory
char name = “LOGGER00.CSV”;

for (uint8_t i = 0; i < 100; i++) {
name[6] = i/10 + ‘0’;
name[7] = i%10 + ‘0’;
if (sd.exists(name)) continue;
logfile.open(name);
break;
}
if (!logfile.is_open()) error(“file.open”);

cout << pstr("Logging to: ") << name << endl;

// format header in buffer
obufstream bout(buf, sizeof(buf));

bout << pstr(“millis”);

bout << pstr(",date,time");

for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
bout << pstr(",sens") << int(i);
}
logfile << buf << endl;

#if ECHO_TO_SERIAL
cout << buf << endl;
#endif // ECHO_TO_SERIAL
}
//------------------------------------------------------------------------------
void loop() {
uint32_t m;

// wait for time to be a multiple of interval
do {
m = millis();
} while (m % LOG_INTERVAL);

// use buffer stream to format line
obufstream bout(buf, sizeof(buf));

// start with time in millis
bout << m;

DateTime now = RTC.now();
bout << ‘,’ << now;

// read analog pins and format data
for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) {
#if ADC_DELAY
analogRead(ia);
delay(ADC_DELAY);
#endif // ADC_DELAY
bout << ‘,’ << analogRead(ia);
}
bout << endl;

// log data and flush to SD
logfile << buf << flush;

// check for error
if (!logfile) error(“write data failed”);

#if ECHO_TO_SERIAL
cout << buf;
#endif // ECHO_TO_SERIAL

// don’t log two points in the same millis
if (m == millis()) delay(1);
}

Die Variablen bout und cout werden nach meinem Verständnis mit den Daten ‘gefüttert’

Greetz, Linpotec

Stimmt.

cout << "Hello World" << endl;
ist Standard c++.
Damit es auf dem Arduino läuft, wird

ArduinoOutStream cout(Serial);

definiert. Der Operator << mit einem ArduinoOutStream auf der linken Seite macht ein print mit dem Ausdruck rechts und liefert die Referenz auf den ArduinoOutStream zurück, so dass man das Ganze hübsch verketten kann. ( So wie im “richtigen” c++ eben )

Siehe auch die Definition des
** **operator <<** **
für DateTime -Variable im Beispielcode…
Hübsch, nicht wahr ? ( Und leicht individuell anpassbar, wenn man ein anderes Datumsformat mag. )

Das gleiche gilt für

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];
obufstream bout(buf, sizeof(buf));
// pstr stores strings in flash to save RAM
bout << pstr("Hello ");

Leider ist im Sketch vieles mit den kompakten Einzeilern in For-next-Schleifen gelöst, dort muss ich mich noch tiefer hinein arbeiten.
Für das tiefere Verständnis möchte ich solch einen Buffer erstellen, füllen und dann auf die Serial und (später) auf die SD schreiben.
Geht so etwas? Kann ich dazu einfach den Buffer definieren, die Werte nacheinander hineinschieben? Wie bekomme ich die Daten dann auf die Serial?
Ich habe dazu momentan (zuviel) gelesen, mir fehlt da der Grundansatz, kann mir bitte einer von Euch die Denk/ Funktionsweise näher bringen?

Lies mal Standard c++ Tutorials zu ostream und dem << operator, oder über die Tatsache dass man in c++ generell Operatoren für Klassen definieren kann.

Zu deiner konkreten Frage " Geht so was ?" ist bei Software die Antwort immer “ja”, in diesem Fall sogar ohne heftige Einschränkungen.

Ein obufstream ist nur ein Objekt um das eigentliche char Array, um den << Operator zu ermöglichen, der den gewünschten Text im Puffer zusammenbaut. Den Text kannst du dann nach Belieben auf die klassische Art und Weise:
Serial.print(buf);
oder auch mit cout << buf; ausgeben.

** **cout << bout; // könnte evtl auch gehen** **
muss isch mal ausprobieren.

PUHHHH...

Erstmal Vielen Dank für diesen tiefen Einblick !!

und auch danke für noch mehr Suchbegriffe .... ;)

das hilft mir schon gut weiter...

Greetz, Linpo