Ich habe folgendes Problem: Ich messe Neigungswinkel mit einer MPU6050. Das funktioniert super, aber nun möchte ich diese Daten auf einer SD-Karte speichern. Leider klappt irgendetwas nicht und ich komme bei der Meldung "Error writing to file !“ raus.
Hat irgendjemand Ahnung was schief läuft?
//
#include <SD.h>
#include<SPI.h>
#include<Wire.h>
//
const int MPU_addr=0x68;
double AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
uint32_t timer;
double compAngleX, compAngleY;
#define degconvert 57.2957786
String dataString ="";
File data;
//
//
void setup()
{
// Set up MPU 6050:
Wire.begin();
#if ARDUINO >= 157
Wire.setClock(400000UL);
#else
TWBR = ((F_CPU / 400000UL) - 16) / 2;
#endif
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
// Open serial communications
Serial.begin(9600);
Serial.print("Initializing SD card...");
pinMode(4, OUTPUT);
//
// see if the card is present and can be initialized:
if (!SD.begin(4)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
//setup starting angle
//1) collect the data
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read();
AcY=Wire.read()<<8|Wire.read();
AcZ=Wire.read()<<8|Wire.read();
Tmp=Wire.read()<<8|Wire.read();
GyX=Wire.read()<<8|Wire.read();
GyY=Wire.read()<<8|Wire.read();
GyZ=Wire.read()<<8|Wire.read();
double roll = atan2(AcY, AcZ)*degconvert;
double pitch = atan2(-AcX, AcZ)*degconvert;
double gyroXangle = roll;
double gyroYangle = pitch;
double compAngleX = roll;
double compAngleY = pitch;
//start a timer
timer = micros();
}
//
void loop(){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read();
AcY=Wire.read()<<8|Wire.read();
AcZ=Wire.read()<<8|Wire.read();
Tmp=Wire.read()<<8|Wire.read();
GyX=Wire.read()<<8|Wire.read();
GyY=Wire.read()<<8|Wire.read();
GyZ=Wire.read()<<8|Wire.read();
double dt = (double)(micros() - timer) / 1000000;
timer = micros();
double roll = atan2(AcY, AcZ)*degconvert;
double pitch = atan2(-AcX, AcZ)*degconvert;
double gyroXrate = GyX/131.0;
double gyroYrate = GyY/131.0;
compAngleX = 0.99 * (compAngleX + gyroXrate * dt) + 0.01 * roll;
compAngleY = 0.99 * (compAngleY + gyroYrate * dt) + 0.01 * pitch;
dataString = String(compAngleX) + "," + String(compAngleY); // convert to CSV
saveData(); // save to SD card
delay(60000); // delay before next write to SD Card, adjust as required
}
//
void saveData(){
if(SD.exists("data.csv")){ // check the card is still there
// now append new data file
Serial.println("Creating data.csv...");
if (data){
File data = SD.open("data.csv", FILE_WRITE);
data.println(dataString);
data.close(); // close the file
}
}
else{
Serial.println("Error writing to file !");
}
}
Lösch einfach die globale Variable, rücke richtig ein und vereinfache deine Funktion:
if(SD.exists("data.csv")){ // check the card is still there ?
// now append new data file
Serial.println("Creating data.csv...");
File data = SD.open("data.csv", FILE_WRITE);
if (data) {
data.println(dataString);
data.close(); // close the file
}
else {
Serial.println("Error writing to file !");
}
else {
Serial.println("data.csv existiert nicht !");
}
Bin übrigens nicht sicher, ob SD.exists richtig erkennt, ob die Karte noch oder wieder drin ist. Gab mindestens mal eine Version, da war nach SD-Kartenwechsel ein SD.begin() erforderlich.
Lösch einfach die globale Variable, rücke richtig ein und vereinfache deine Funktion:
Hallo michael_x,
schon mal Danke fuer die schnelle Antwort!
File data habe ich nun raus.
Jetzt bekomme ich die Fehlermeldung das ich den input abschliessen soll. Treibt mich zum Wahnsinn, da ich den Fehler nicht finde.
sketch_aug17a:121: error: expected '}' at end of input
}
^
sketch_aug17a:121: error: expected '}' at end of input
sketch_aug17a:121: error: expected '}' at end of input
treehugger:
Hallo michael_x,
schon mal Danke fuer die schnelle Antwort!
File data habe ich nun raus.
Jetzt bekomme ich die Fehlermeldung das ich den input abschliessen soll. Treibt mich zum Wahnsinn, da ich den Fehler nicht finde.
Bitte geänderten Sketch richtig eingerückt wieder hier reinstellen. Wir wissen nicht was wo geändert wurde und was jetzt fehlt.
mratix:
um es auch verstehen zu können... das letzte else wäre überflüssig? oder?
Nein, mir ging es nur ums Einrücken.
Verhaut wird man, wenn man deswegen eine falsche Klammer-anzahl hat und im Forum fragt.
Wenn man Fehlerbehandlung einbaut, auch wenn hinterher keiner guckt, sollte man eher gelobt werden.
@treehugger Einrücken ist mit Ctrl+T (Menüleiste: Werkzeuge/Automatische Formatierung/Klick) schnell erledigt.
Aber die Schleife funktioniert so nicht.
Die erste if muss negiert werden. Außerdem ist es total verwurschtelt und unübersichtlich.
Ich würde das ganze so herunterkürzen:
void saveData() {
if (!SD.exists("data.csv")) { // check the file is still there ?
Serial.println(F("data.csv does not exist !"));
Serial.println(F("Creating data.csv..."));
File data = SD.open("data.csv", FILE_WRITE); // create file through open
data.close(); // close the file
Serial.println(F("data.csv created..."));
}
else
{
File data = SD.open("data.csv", FILE_WRITE); // open file for write
data.println(dataString); // write datastring
data.close(); // close the file
}
michael_x:
Verhaut wird man, wenn man deswegen eine falsche Klammer-anzahl hat und im Forum fragt.
Nun ist leider ein neus Problem aufgetreten. Die Daten welche ich auf der SD Karte bekomme stimmen nicht mit denen vom 'Serial Monitor" ueberein (also mit denen vom urspruenglichen sketch, bevor ich versucht hatte das auf Sd zu speichen).
Anbei eine schnelle Grafik zum Vergleich. Woran kann es liegen?
michael_x:
Tja, die zwei haben nicht viel miteinander zu tun. Ausser, du erklärst uns den Zusammenhang.
Der Zusammenhang: Eigentlich sollte bei beiden das gleiche raus kommen. Der Sketch welcher denke ich die richtigen Daten ausgibt kommt im Original von dieser Seite:
Das funktioniert super und man bekommt sehr genau die beiden Winkel wenn man die MPU6050 an einem Onjekt befestigt.
Bei der zweiten Datenreihe habe ich im Sketch rumgepfuscht (deswegen war der auch so schlecht eingerueckt) und versucht die Daten auf die SD Karte zu schreiben. Nun ja eigentlich sollten aehnliche Werte raus kommen. Aber das tut es eben nicht.
Koennte ich eventuell die MPU Rohdaten anders als mit einem String auf die SD Karte schreiben?
Oder kommt das vom delay(), im Tutorial heisst es ja so schoen: "An analogy would be warming up a pizza in your microwave, and also waiting some important email. You put the pizza in the microwave and set it for 10 minutes. The analogy to using delay() would be to sit in front of the microwave watching the timer count down from 10 minutes until the timer reaches zero. If the important email arrives during this time you will miss it."
Nun gut, den string ahbe ich jetzt ersetzt und ich lass mir die Daten zusaetzlich ueber den Serial Monitor geben. Jetzt liegen die nur noch etwa 20 Grad daneben. Auch habe ich versucht von dem delay() weg zu kommen, hatte erhofft weniger Daten auf zu zeichenen. Leider Fehlanzeige das sprudelt immer noch so raus.
saveData();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;}
}
//
void saveData(){
if(SD.exists("data.csv")){ // check the card is still there ?
Serial.println("Creating data.csv...");
File data = SD.open("data.csv", FILE_WRITE);
if (data) {
Serial.print(compAngleX); Serial.print(compAngleY);
data.print(compAngleX); data.println(compAngleY);
data.close();
}
else {
Serial.println("Error writing to file !");
}}
else {
Serial.println("data.csv does not exist !");
}
}
SkobyMobil:
hier hast Du einen "Intervall"
vielleicht hilft es Dir ja...
Dann noch durch eine logische Funktion nur einmal speichern.
Hallo Freunde der leichten Unterhaltung!
Jetzt habe ich den Vorschlag von Andreas eingebaut (schon mal vielen dank fuer die Idee). Der count funktioniert, ABER ich weiss nicht ob ich durch dieses if ( count = 12) auch wirklich nur jeden zwoelften Wert auf zeichen. Ohne dieses if wird immer von 1 bis 12 gezaehlt und alle Werte ausgedruckt. Stellt der Sketch so wirklich die Beziehung zu dem interval = 5000 her?
Hier mein Werk von heute und das was auf der SD-Karte landet (.txt da ich ja .csv nicht hochladen kann). Erste Reihe ist der count mit 12 und dann die beiden Winkel (haben immernoch diesen dummen Offset).