Liebe Arduinonutzer,
ich stoße gegen ein Problem, das mich schon wegen Schlafentzug kaputt gemacht hat.
Grundsätzlich möchte ich einen Datalogger entwickeln, der Daten aus meiner Platine mit Sensoren im exakten Intervallen auf einer SD Karte abspeichert.
Gut...das Problem liegt nun darin, dass die "Geschwindigkeit" der SD Bibliothek definitiv zu langsam ist. In meinem Programm werden die Sensoren aus der Platine mit einer Abtastfrequenz von 200 Hz, währenddessen die SD Bibliothek mindestens 10 Millisekunden benötigt, um Daten auf der Karte abzuspeichern.
Hiermit mein grobes Programm und noch weiter die aufgerufene Funktion
*+++++++++++++++++++++++++++++++++++++++++++++++++
*
* Diese Version verwendet PORTD, um den Empfänger einzulesen.
*
* Einsatz: Razor 6DOF + Arduino 2009
*
* Diese Version ist bereits zum fliegen...
*
*************************************************/
#include <avr/interrupt.h>
#include <avr/io.h>
#include <SD.h>
#include "define_AP6.h"
/***********************************
* Definitions for analog sampling
***********************************/
const int xx_pin = A1; // Acceleremoter X output pin, ratiometric
const int yy_pin = A0; // Accelerometer Y output pin, ratiometric
const int zz_pin = A2; // Accelerometer Z output pin, ratiometric
const int pitch_pin = A5; // Gyro Output, pin not ratiometric
const int roll_pin = A4; // Gyro Output, pin not ratiometric
const int yaw_pin = A3; // Gyro Output, pin not ratiometric
/******************************
* Aus dem Datalogger Programm
The circuit:
* analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
******************************/
// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;
/***************************************************************
* Variablen, die durch den ausgeführten Interrupt gelesen werden
***************************************************************/
volatile unsigned int radioIn[NUM_CHANNEL];
unsigned int servoOut[NUM_CHANNEL];
volatile unsigned int aileronSignalLength, aileronSignalDiff, elevatorSignalLength, elevatorSignalDiff, throttleSignalLength, throttleSignalDiff, rudderSignalLength, rudderSignalDiff, autopilotSignalLength, autopilotSignalDiff;
volatile unsigned int cnt;
volatile char CH = 1; // Erster Kanal, der aus dem Empfänger eingelesen wird
volatile char FLAG_ail = 0, FLAG_elv = 0, FLAG_thr = 0, FLAG_rud = 0, FLAG_aut = 0;
int autoPilot = 0;
/********************************************************
* Variable to space every loop routine exactly of x mSec
********************************************************/
unsigned long timeFastLoop, timeSlowLoop, prevTimeFastLoop = 0, prevTimeSlowLoop = 0;
/******************************************************
* Definition von Variablen, die den Autopilot ansteuern
******************************************************/
unsigned long id = 1; // #id
unsigned int file_index = 1; // #id File
char filename[12];
char task = 1;
/***************************
* Output chars and variables
***************************/
const int ledRed = 9; // Nicht 13, da der Pin schon für die SPI eingesetzt ist
const int ledGreen = 8;
//###########################################################################################
/**************
*
* Initial Setup
*
**************/
void setup(){
analogReference(EXTERNAL);
Serial.begin(BAUDRATE); // Serial communication with the pc
Serial.flush();
// set_interrupt(); // Erforderlich. Durch diese Funktion werden die einzelnen Interrupts angeschaltet
//************************************************************//
delay(4000);
Serial.println("******************FILTER 6**********************");
pinMode(ledRed, OUTPUT); // Led on digital pin 13 is used as indicator to show that the calibration is on the way...
pinMode(ledGreen, OUTPUT);
digitalWrite(ledRed, HIGH);
digitalWrite(ledGreen, HIGH);
pinMode(chipSelect, OUTPUT);
delay(2000);
digitalWrite(ledRed, LOW);
digitalWrite(ledGreen, LOW);
delay(2000);
Serial.println("Initializing the SD Card...");
// see if the card is present and can be initialized:
if(SD.begin(chipSelect)){
Serial.println("card initialized!");
Serial.println("creating files...");
createFile(file_index);
for(int i = 0; i < 3; i++){
digitalWrite(ledGreen, HIGH);
delay(150);
digitalWrite(ledGreen, LOW);
delay(150);
}
}else{
Serial.println("Card failed, or not present");
for(int i = 0; i < 200; i++){
digitalWrite(ledRed, HIGH);
delay(1000);
digitalWrite(ledRed, LOW);
delay(1000);
}
}
}
void loop(){
timeFastLoop = millis();
timeSlowLoop = timeFastLoop;
if(((timeFastLoop - prevTimeFastLoop) > 4)){
prevTimeFastLoop = timeFastLoop;
sensors(filename);
}
}
/*****************************
*
* Interrupt Routine
*
*****************************/
void set_interrupt(void){
DDRD &= ~((1 << PIND2) | (1 << PIND3) | (1 << PIND4) | (1 << PIND5) | (1 << PIND6)); // Input Pin
PORTB &= ~((1 << PIND2) | (1 << PIND3) | (1 << PIND4) | (1 << PIND5) | (1 << PIND6)); // Pull - up disabled
// Configure external interrupts on PCINT2 (from PD0 to PD7)
PCMSK2 = 0; // Disable interrupts on over a single port
PCMSK2 |= ((1 << PCINT18)); // At the moment only PD2 enabled
PCICR |= (1 << PCIE2); // Enabled interrupts on PCINT23-16
}
und hier die aufgerufene Funktion:
/*
Diese Funktion nimmt die Fileindex als Argument und öffnet der entsprechenden Datei
*/
void sensors(char* file){
// Definition
int x_out = analogRead(xx_pin);
int y_out = analogRead(yy_pin);
int z_out = analogRead(zz_pin);
int p_out = analogRead(pitch_pin);
int r_out = analogRead(roll_pin);
int w_out = analogRead(yaw_pin);
char data[34];
sprintf(data, "%u, %u, %u, %u, %u, %u, %u", prevTimeFastLoop, x_out, y_out, z_out, p_out, r_out, w_out);
// sprintf(data, "%u", prevTimeFastLoop);
File log_file = SD.open(file, O_WRITE);
// if the file is available, write to it:
if (log_file) {
log_file.println(data);
log_file.flush();
log_file.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening flugXX.dat");
}
}
Obwohl ich schon im ganzen Forum durchgesucht habe, wie man die SD Library beschluenigen kann und die Parameter: O_CREAT und O_WRITE verwendet habe, habe ich leider meine gewünschte Abtastrate noch nicht erzielt.
Hier ist eine Probe, in der das obige Programm geändert wurde und statt die Messung aus den Sensoren die milli() Funktion in ersten Spalte abgepeichert wird.
9037, 0, 504, 517, 616, 368, 368
9060, 0, 504, 517, 616, 368, 367
9070, 0, 504, 517, 616, 368, 367
9079, 0, 504, 517, 616, 369, 369
9090, 0, 504, 516, 615, 369, 368
9100, 0, 504, 516, 615, 369, 368
9109, 0, 504, 517, 616, 369, 368
9119, 0, 504, 517, 616, 369, 368
9129, 0, 504, 516, 616, 368, 368
9140, 0, 504, 517, 615, 369, 368
9149, 0, 504, 517, 616, 369, 368
9159, 0, 504, 517, 616, 369, 368
9169, 0, 504, 517, 616, 369, 368
...............
es ist sofort ersichtlich, dass die Abtastfrequenz beträgt durchschnittlich zirka 10 Millisekunden und das ist für meine Apllikation zu hoch.
Wie kann die Bibliothek modifizieren? Gibt es eine Möglichkeit, Daten mit höherer Datenrate in der Karte abzuspeichern????
Ich danke euch herzlich
Gruß und schönen Abend noch
D.