Datenloggen mit 2KHz

Hi,

ich möchte mit einen Arduino Mega2560 und einen adafruit SD Shield Sensordaten aufzeichnen. Idealer Weise würde ich von 4 Drucksensoren über den I2C Bus alle 0.5ms Werte aufnehmen und auf die SD Karte speichern wollen. Leider benötigt das schreiben der Werte auf die SD Karte schon mindestens 3ms. Für das Schreiben auf die SD Karte habe ich die SD.h Bibliothek verwendet. Welche möglichkeiten gibt es, das Schreiben auf die Karte zu beschleunigen? Die Aufzeichnungsdauer sollte so bei ca. 10s bis 1min betragen.

Grüße
Frank

Im Interrupt die Sensoren lesen.
Die Daten in einen Ringpuffer schreiben.
Von da aus auf die SD Karte schreiben.
(KA, ob das geht, denn die Schnittstelle zu den Sensoren ist geheim)

Ob da der Mega langt, KA.
Das musst du selber probieren.
evtl. wäre ein µC besser, welcher die erweiterten Modi einer SD-Karte nutzen kann, und nicht nur den SPI Modus.

Das ist nicht so einfach. Mit der SdFat Bibliothek kann man Binär-Daten in ganzen Blöcken schreiben. Und auch das kann zu langsam für dich sein:

  • Samples are logged at regular intervals. The maximum logging rate
  • depends on the quality of your SD card and the time required to
  • read sensor data. This example has been tested at 500 Hz with
  • good SD card on an Uno. 4000 HZ is possible on a Due.
  • If your SD card has a long write latency, it may be necessary to use
  • slower sample rates. Using a Mega Arduino helps overcome latency
  • problems since 12 512 byte buffers will be used.

Hi

4 Sensoren alle 500ns - Die wirst Du wohl einzeln abfragen müssen, was die Geschwindigkeit wieder 'etwas' erhöht.
Wie viele Byte umfasst eine Messung?
Die SD-Karte hängt an SPI, oder? Wie sieht's hier mit der möglichen Geschwindigkeit aus?
Da sollte jedenfalls mehr möglich sein, als auf I²C-Seite.
Wenn sich die Geschwindigkeit hier nicht erhöhen lässt, Du aber nur die Hälfte der Zeit, Die Du pro 'Runde' hast, für das Einlesen per I²C verbrauchst, kannst Du die Daten auch auf einem FRam zwischenspeichern - Die sind (weit) schneller, als der Arduino, gibt's auch als SPI (dort noch Mal um Einiges flotter), selber aber nur I²C-FRam in den Händen gehabt (und bisher nicht wirklich sinnvolles Zeug drauf gespeichert ...).
Tommy56 hat dazu eine Lib gebaut, sollte sich finden lassen, ist im Nachbar-Universum, aber auch von hier verlinkt.

Schreib Bitte Mal genauer, was Du vor hast.

MfG

combie:
Im Interrupt die Sensoren lesen.

Habe ich noch nie gemacht, muss mich dazu erst mal einlesen.

combie:
(KA, ob das geht, denn die Schnittstelle zu den Sensoren ist geheim)

Was meinst du mit geheim? Von den Sensorhersteller habe ich eine Bibliothek zum Auslesen der Sensoren (Amsys AMS 6915) und eine Dokumentation dazu.

combie:
evtl. wäre ein µC besser, welcher die erweiterten Modi einer SD-Karte nutzen kann, und nicht nur den SPI Modus.

Wenn ich die zu schreibenden Daten mal überschlage: Zeit (Long, 2Byte), 2x Werte (Float, 4Byte) und das ganze bei 4 Sensoren und 2KHz komme ich auf ca. 80kB/s das sollte doch eigentlich zu schaffen sein.

Serenifly:
Das ist nicht so einfach. Mit der SdFat Bibliothek kann man Binär-Daten in ganzen Blöcken schreiben. Und auch das kann zu langsam für dich sein:

Ok, Schaue ich mir mal an.

postmaster-ino:
4 Sensoren alle 500ns - Die wirst Du wohl einzeln abfragen müssen, was die Geschwindigkeit wieder 'etwas' erhöht.
Wie viele Byte umfasst eine Messung?
Schreib Bitte Mal genauer, was Du vor hast.
MfG

Also es sind bis zu 4 Sensoren die ca. alle 500µs-1000µs ausgelesen werden sollen (1-2KHz). Das auslesen erfolgt mit der folgenden Routine:

void AMS::ReadFromWire(int address, int &pressureM, int &pressureL, int &tempM, int &tempL) {
	int data = Wire.requestFrom(address, 4); //request for bytes of data from the given address
	pressureM = Wire.read(); //read the first byte
	pressureL = Wire.read(); //read the second byte
	tempM = Wire.read(); //read the third byte
	tempL = Wire.read(); //read the fourth byte

float AMS::readSensor(float &pressure, float &temperature) {
	switch (_type) {
		case 5812:
			ReadFromWire(_address, _pressureMSB, _pressureLSB, _tempMSB, _tempLSB);	
			pressure = ((256*_pressureMSB+_pressureLSB)-3277.0)*(_pmax-_pmin)/26214+_pmin;
			temperature = (((256*_tempMSB+_tempLSB)-3277.0)/238.309)-25; //convert the temperature data into temperature in degree celsius
			break;
		case 5915:
			ReadFromWire(_address, _pressureMSB, _pressureLSB, _tempMSB, _tempLSB);
			pressure = (((256*(_pressureMSB&0x3F)+_pressureLSB)-1638.0)*(_pmax-_pmin)/13107)+_pmin; //convert the pressure data into pressure in mbar, see AMS 5812 datasheet
			temperature = (((256.0*_tempMSB+_tempLSB)*200.0)/65536)-50; //convert the temperature data into temperature in degree celsius
			break;
		case 6915:
			ReadFromWire(_address, _pressureMSB, _pressureLSB, _tempMSB, _tempLSB);
			pressure = (((256*(_pressureMSB&0x3F)+_pressureLSB)-1638.0)*(_pmax-_pmin)/13107)+_pmin; //convert the pressure data into pressure in mbar, see AMS 5812 datasheet
			temperature = (((256.0*_tempMSB+_tempLSB)*200.0)/65536)-50; //convert the temperature data into temperature in degree celsius
			break;
		default:
			pressure = NAN;
			temperature = NAN;
			break;
	}

Das kann man bestimmt noch etwas vereinfachen. Eventuell speichere ich erst mal die Rohdaten und berechne den tatsächlichen Messwert erst später. Auch die Temperaturabfrage könnte man weglassen wenn es zu Lange dauert.
Bei mir dauert aber schon das schreiben auf die SD Karte zu lange und da habe ich noch keinen Sensor ausgelesen.