Update:
Output-Data-Rate (ODR) vom Sensor auf 6664 Hz, Daten werden mit 2 Buffern abwechselnd auf die SD Karte geschrieben.
Abtasten erfolgt durch den Code mit einem Delay von 127 micros (150 micros [6664 Hz] - 23 micros [get.event-Dauer]).
Ein Buffer nimmt 6664 Werte auf, Zeitstempel gibt ca. 1 Sekunde fürs Füllen eines Buffers aus. Das sieht also gut aus!
Messung stoppt wenn eine bestimmte Anzahl an daten gesammelt wurde. Hier 66640 Werte, also 10s Messung.
Der Plot deutet darauf hin, dass ein TP-Filter bei ODR/2 (3332 Hz) aktiv ist.
Plot:
Hier der aktuelle Code:
#include <Adafruit_LSM6DSOX.h>
#include <SD.h> // SD Speicherung
// For SPI mode, we need a CS pin
#define LSM_CS 10
#define LSM_SCK 13
#define LSM_MISO 12
#define LSM_MOSI 11
const size_t BUFFER_SIZE = 6664; // Anzahl Messreihen pro Buffer
const size_t TOTAL_MEASUREMENTS = 66640; // Gesamtanzahl Messreihen
Adafruit_LSM6DSOX sox;
// Zwei Puffer für Double Buffering
float buffer1[BUFFER_SIZE][7]; // 7 Werte: Temp, Accel X/Y/Z, Gyro X/Y/Z
float buffer2[BUFFER_SIZE][7];
bool useBuffer1 = true; // Aktiver Puffer
size_t bufferIndex = 0; // Aktueller Index im aktiven Puffer
size_t totalMeasurements = 0;
bool measurementActive = false; // Messung aktiv?
String input = ""; // Eingabe speichern
unsigned long startTime = 0; // Startzeit speichern
unsigned long fillStartTime = 0; // Zeitstempel vor dem Füllen des Buffers
unsigned long fillEndTime = 0; // Zeitstempel nach dem Füllen des Buffers
unsigned long fillDuration = 0; // Dauer in Mikrosekunden, um den Buffer zu füllen
unsigned long totalStartTime = 0; // Gesamtstartzeit der Messung
unsigned long totalEndTime = 0; // Gesamtendzeit der Messung
unsigned long totalDuration = 0; // Gesamtzeit der Messung
size_t measurementIndex = 0; // Messindex
File dataFile; // Dateiobjekt für SD-Karte
String filename = "Messdaten.csv"; // SD Speicherdatei, initialer Standardname
void requestFilename() {
Serial.println("Bitte Dateinamen eingeben und mit ENTER bestaetigen:");
while (true) {
if (Serial.available()) {
char receivedChar = Serial.read();
if (receivedChar == '\n') { // Wenn Enter gedrückt wurde
input.trim(); // Eingabe trimmen (Leerzeichen und Steuerzeichen entfernen)
// Falls keine Endung angegeben, ".csv" anhängen
if (!input.endsWith(".csv")) {
input += ".csv";
}
// Eingabe anzeigen
Serial.print("Dateiname: '");
Serial.print(input);
Serial.println("'");
filename = input; // Dateiname setzen
input = ""; // Eingabe zurücksetzen
break; // Schleife beenden
} else {
input += receivedChar; // Eingabe dynamisch anzeigen
Serial.print(receivedChar); // Zeigt den eingegebenen Buchstaben an
}
}
}
}
void waitForStartCommand() {
Serial.println("Bitte 'start' eingeben und mit 'ENTER' bestaetigen um Messung zu starten!");
while (!measurementActive) {
if (Serial.available()) {
char receivedChar = Serial.read(); // Einzelnen Buchstaben einlesen
if (receivedChar == '\n') { // Wenn Enter gedrückt wurde
input.trim(); // Eingabe trimmen (Leerzeichen und Steuerzeichen entfernen)
// Eingabe anzeigen
Serial.print("Eingabe: '");
Serial.print(input);
Serial.println("'");
// Vergleiche die Eingabe mit "start"
if (input.equals("start")) {
measurementActive = true;
measurementIndex = 0; // Reset Index für neue Messung
startTime = micros(); // Startzeit speichern
totalStartTime = micros(); // Gesamtstartzeit speichern
Serial.println("Messung gestartet...");
} else {
Serial.println("Ungueltige Eingabe. Geben Sie 'start' ein und druecken Sie Enter.");
}
input = ""; // Eingabe zurücksetzen
} else {
input += receivedChar; // Eingabe dynamisch anzeigen
Serial.print(receivedChar); // Zeigt den eingegebenen Buchstaben an
}
}
}
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Adafruit LSM6DSOX test!");
Serial.println("SD-Karten-Test");
// Sensor initialisieren
if (!sox.begin_SPI(LSM_CS, LSM_SCK, LSM_MISO, LSM_MOSI)) {
Serial.println("Failed to find LSM6DSOX chip");
while (1) delay(10);
}
Serial.println("LSM6DSOX Found!");
// SD-Karte initialisieren
if (!SD.begin(BUILTIN_SDCARD)) {
Serial.println("SD-Karte nicht erkannt!");
while (1);
}
Serial.println("SD-Karte erfolgreich erkannt!");
// Benutzer auffordern, einen Dateinamen einzugeben
requestFilename();
// Datei öffnen oder erstellen
dataFile = SD.open(filename.c_str(), FILE_WRITE);
if (!dataFile) {
Serial.println("Fehler beim Oeffnen der Datei!");
while (1);
}
// Spaltenüberschriften in die Datei schreiben
dataFile.println("Temp,Accel_X,Accel_Y,Accel_Z,Gyro_X,Gyro_Y,Gyro_Z");
dataFile.flush();
// Sensoreinstellungen
sox.setAccelRange(LSM6DS_ACCEL_RANGE_4_G);
sox.setGyroRange(LSM6DS_GYRO_RANGE_2000_DPS);
sox.setAccelDataRate(LSM6DS_RATE_6_66K_HZ);
sox.setGyroDataRate(LSM6DS_RATE_6_66K_HZ);
// Warten, bis der Benutzer "start" eingibt
waitForStartCommand();
Serial.println("Messung beginnt...");
}
void loop() {
if (measurementActive) {
sensors_event_t accel, gyro, temp;
// Startzeit vor dem Füllen des Buffers
if (bufferIndex == 0) {
fillStartTime = micros();
}
sox.getEvent(&accel, &gyro, &temp);
// Daten in den aktiven Puffer schreiben
float (*currentBuffer)[7] = useBuffer1 ? buffer1 : buffer2;
currentBuffer[bufferIndex][0] = temp.temperature;
currentBuffer[bufferIndex][1] = accel.acceleration.x;
currentBuffer[bufferIndex][2] = accel.acceleration.y;
currentBuffer[bufferIndex][3] = accel.acceleration.z;
currentBuffer[bufferIndex][4] = gyro.gyro.x;
currentBuffer[bufferIndex][5] = gyro.gyro.y;
currentBuffer[bufferIndex][6] = gyro.gyro.z;
bufferIndex++;
totalMeasurements++;
// Buffer voll? In SD-Karte schreiben und Puffer wechseln
if (bufferIndex >= BUFFER_SIZE || totalMeasurements >= TOTAL_MEASUREMENTS) {
// Zeitstempel nach dem Füllen des Buffers
fillEndTime = micros();
fillDuration = fillEndTime - fillStartTime; // Berechnung der Zeit, um den Buffer zu füllen
// Ausgabe der Zeit im seriellen Monitor
Serial.print("Zeit zum Fuellen des Buffers (in Mikrosekunden): ");
Serial.println(fillDuration);
float (*writeBuffer)[7] = useBuffer1 ? buffer1 : buffer2;
useBuffer1 = !useBuffer1; // Puffer wechseln
bufferIndex = 0;
Serial.println("Messung aktiv ...");
for (size_t i = 0; i < BUFFER_SIZE && totalMeasurements <= TOTAL_MEASUREMENTS; i++) {
dataFile.print(writeBuffer[i][0], 4); dataFile.print(",");
dataFile.print(writeBuffer[i][1], 4); dataFile.print(",");
dataFile.print(writeBuffer[i][2], 4); dataFile.print(",");
dataFile.print(writeBuffer[i][3], 4); dataFile.print(",");
dataFile.print(writeBuffer[i][4], 4); dataFile.print(",");
dataFile.print(writeBuffer[i][5], 4); dataFile.print(",");
dataFile.println(writeBuffer[i][6], 4); // 4 Nachkommastellen für alle Werte
}
dataFile.flush(); // Daten in Datei schreiben
}
// Messung stoppen, wenn alle Messreihen gesammelt
if (totalMeasurements >= TOTAL_MEASUREMENTS) {
totalEndTime = micros(); // Gesamtendzeit speichern
totalDuration = totalEndTime - totalStartTime; // Berechnung der Gesamtzeit
Serial.print("Gesamtzeit der Messung (in Mikrosekunden): ");
Serial.println(totalDuration);
Serial.println("Messung beendet");
dataFile.close(); // Datei schließen
while (1); // Endlosschleife
}
// Verzögerung, um die Abtastrate von 6664 Hz zu erreichen (0.127 ms), 0.15 ms abzüglich get.event delay von 23 Micros
delayMicroseconds(127); // ca. 0.127 Millisekunden
}
}
Ich taste also mit 6664 Hz ab, was auch der Output-Data-Rate meines Sensors entspricht und habe laut Zeitstempel einen Fehler von ca. 2000 micros auf eine Sekunde (0,2 %).
Keine Ahnung ob ich hier noch irgendwo einen Denkfehler habe, aber es scheint im ersten Moment gut zu funktionieren.