ذخیره دیتا شتاب سنج adxl345 با سمپل ریت 800 هرتز در sd-card با esp 32 به وسیله پروتکل spi بدون از دست دادن دیتا

سلام وقت همه دوستان بخیر
من می خوام از سنسور adxl345 با سمپل ریت 800 هرتز دیتا بخونم و در sd-card ذخیره کنم بدون اینکه دیتایی رو از دست بدم . اما یه مشکلی هست اونم اینکه esp32 یدونه spi داره و من باید مشترکا از اون برای sd و هم برای adxl345 استفاده کنم .
این کد من هست . من اومدم از پایه اینتراپت شتاب سنج استفاده کردم .

#include "FS.h"
#include "SD.h"
#include <SPI.h>
String dataMessage;
//Assign the Chip Select signal to pin 10.
int status = 15;
int CS1 = 9;
int led = 17;
int inter = 18;
int a = 0; 
//This is a list of some of the registers available on the ADXL345.
//To learn more about these and the rest of the registers on the ADXL345, read the datasheet!
char POWER_CTL = 0x2D;	//Power Control Register
char DATA_FORMAT = 0x31;
char Interrupt_Enable = 0x2E;
char Interrupt_Mapping = 0x2F;
char DATAX0 = 0x32;	//X-Axis Data 0
char DATAX1 = 0x33;	//X-Axis Data 1
char DATAY0 = 0x34;	//Y-Axis Data 0
char DATAY1 = 0x35;	//Y-Axis Data 1
char DATAZ0 = 0x36;	//Z-Axis Data 0
char DATAZ1 = 0x37;	//Z-Axis Data 1
char sample = 0x2C; //Sample rate
//This buffer will hold values read from the ADXL345 registers.
char values[10];
//These variables will be used to hold the x,y and z axis accelerometer values.
int16_t x,y,z;
File file;
void setup() {
  //Initiate an SPI communication instance.
  //Serial.begin(115200);
  initSDCard();
  SPI.begin();
  file=SD.open("/data.txt", FILE_APPEND);
  //Configure the SPI connection for the ADXL345.
  SPI.setDataMode(SPI_MODE3);
  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS1, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  pinMode(status, OUTPUT);
  pinMode(inter, INPUT);
  pinMode(led, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(status, LOW);
  digitalWrite(CS1, HIGH);
  digitalWrite(led, LOW);
  
  //Put the ADXL345 into +/- 8G range by writing the value 0x01 to the DATA_FORMAT register.
  writeRegister(DATA_FORMAT, 0x02);
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeRegister(POWER_CTL, 0x08);  //Measurement mode
  writeRegister(sample, 0x0D);
  writeRegister(Interrupt_Enable, 0x80);
  writeRegister(Interrupt_Mapping, 0x80);  

}

void loop() 
{   
    
    while (digitalRead(inter)==0);
    SPI.setDataMode(SPI_MODE3);
    

  readRegister(DATAX0, 6, values);
  /*/Set the Chip select pin low to start an SPI packet.
  digitalWrite(CS1, LOW);
  //Transfer the starting register address that needs to be read.
  SPI.transfer(0xF2);
  //Continue to read registers until we've read the number specified, storing the results to the input buffer.
  for(int i=0; i<6; i++){
    values[i] = SPI.transfer(0x00);
  }
  //Set the Chips Select pin high to end the SPI packet.
  digitalWrite(CS1, HIGH);
*/
    x = ((int)values[1]<<8)|(int)values[0];
    y = ((int)values[3]<<8)|(int)values[2];
    z = ((int)values[5]<<8)|(int)values[4];
    dataMessage = String(x) + "," + String(y) + "," + String(z)+ "\r\n";
    //dataMessage = "-00,-00,-00";
    //Serial.print(dataMessage);
    a++;
    digitalWrite(status,LOW);
    file.print(dataMessage);
    digitalWrite(status,HIGH);
    while(a>7999){
    file.close();
    digitalWrite(led,HIGH);

    }
}
//This function will write a value to a register on the ADXL345.
//Parameters:
//  char registerAddress - The register to write a value to
//  char value - The value to be written to the specified register.
void writeRegister(char registerAddress, char value){
  //Set Chip Select pin low to signal the beginning of an SPI packet.
  digitalWrite(CS1, LOW);
  //Transfer the register address over SPI.
  SPI.transfer(registerAddress);
  //Transfer the desired register value over SPI.
  SPI.transfer(value);
  //Set the Chip Select pin high to signal the end of an SPI packet.
  digitalWrite(CS1, HIGH);
}

//This function will read a certain number of registers starting from a specified address and store their values in a buffer.
//Parameters:
//  char registerAddress - The register addresse to start the read sequence from.
//  int numBytes - The number of registers that should be read.
//  char * values - A pointer to a buffer where the results of the operation should be stored.
void readRegister(char registerAddress, int numBytes, char * values){
  //Since we're performing a read operation, the most significant bit of the register address should be set.
  char address = 0x80 | registerAddress;
  //If we're doing a multi-byte read, bit 6 needs to be set as well.
  if(numBytes > 1)address = address | 0x40;
  
  //Set the Chip select pin low to start an SPI packet.
  digitalWrite(CS1, LOW);
  //Transfer the starting register address that needs to be read.
  SPI.transfer(address);
  //Continue to read registers until we've read the number specified, storing the results to the input buffer.
  for(int i=0; i<numBytes; i++){
    values[i] = SPI.transfer(0x00);
  }
  //Set the Chips Select pin high to end the SPI packet.
  digitalWrite(CS1, HIGH);
}
void initSDCard(){
   if (!SD.begin()) {
    return;
  }
  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    return;
  }
  if(cardType == CARD_MMC){
  } else if(cardType == CARD_SD){
  } else if(cardType == CARD_SDHC){
  } else {
  }
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
}

ممنون از وقتیکه می ذارید :pray: :rose:

سلام
خب نمیتونید برای ارتباط با adx از I2C استفاده کنید؟
که اینطوری مشترک نباشه.
الان هم چقدر دیتا از دست میدید؟ آیا تا به حال چک کردید؟
به نظرم کدتون میتونه بهینه تر بشه. مخصوصا اون قسمت ترکیب اعداد و تبدیلش به متن و نوشتن روی کارت حافظه.

سلام
ممنون از وقتی که در اختیارم گذاشتید
برای دیتا ریت های بالا تو دیتا شیت گفته شده از spi استفاده بشه
من روشی که برای فهمیدن از دست دادن دیتا استفاده می کنم اینکه یه پایه ی status تعریف کردم و در هر نوشتن میام و اون و 0 و 1 می کنم بعد در لاجیک نگاه می کنم الان در کد بالا ما در دیتا ریت 800 تنظیم کردیم و قاعدتا 800 هرتز باید در 10 ثانیه به ما 8000 تا دیتا بده در حال اینکه در حدود 10.6 ثانیه 8000 تا دیتا نوشته میشه .یعنی در حدود 480 تا دیتا از ذست میره چیزی حدود 6 درصد که می بایست این درصد خطا چیزی در حدود 1 درصد باشه و یه مورد دیگه که بررسی کردم این بود وقتی زمان بیشتری برای دیتالاگینگ استفاده میشه درصد خطا بیشتر هم میشه! یعنی درصد خطا ثابت نیست!
اون تغییراتی رو هم که فرمودید رو اعمال کردم ولی تاثیر چندانی نداشت.
در این دو روز اخیر اولا فرکانس spi رو افزایش دادم در ثانی همین تغییری رو که فرمودید انجام دادم و زمان به 10.45 اینا رسیده ولی از اون کمتر نشد.
سعی کردم از freertos استفاده کنم که اونم عمل کرد خوبی نداشت و واچ داگ فعال می شد .
اومدم و یک بافر تعرریف کردم و ابتدا دیتا رو در بافر می ریختم بعد در SD می نوشتم ولی باز همین مشکل وجود داشت .واقعا نمی دونم چیکار باید بکنم! این تغییراتی رو هم که خدمتتون عرض کردم از این لینک استفاده کردم.

سلام
ریت رایت مدنظر شما اصلا ریتی نیست که سیستم بخواد باهاش مشکلی داشته باشه ولی روش شما برای انجام این کار اشتباهه :confused:
عکس زیر در واقع بنچ مارک سرعت خواندن و نوشتن روی حافظه SD و MMC هست :

دقت کنید وقتی که به شکل بایت به بایت دیتا رو مینویسیم چقدر سرعت نوشتن پاینه ولی وقتی به شکل بافر مثلا ۵۱۲ بایت این کار رو انجام بدیم سرعت به مراتب بیشتر میشه!

کاری که شما باید انجام بدید دو تا بافر مثلا یک کیلو بایتی درست کنید، دیتا رو داخل بافر اول قرار بدید وقتی بافر اول پر شد، شروع کنید دیتا رو توی بافر دوم بذارید و بافر اول رو همزمان توی یک روال دیگه (تسک) بنویسید توی MMC و این کار به شکل چرخشی انجام بدید

با این روش فکر میکنم مشکل شما حل بشه و داده ای رو از دست ندید :slight_smile: