1

I am a noob and i am from civil engineer, I apologize in advance.

I have a MPU6050 connected to my Arduino Uno and I write the data on an SD. I can write at a sample rate of 20millis.

Why i have this default frequency?

This is part of the code

// Main:
  void loop()
  {
    // Body of main/loop
    // Check status:
    Time0 = millis();
    Read_Write();
   // LED off and continue:
      digitalWrite(LEDpin, LOW);
      
       }

  void Read_Write()
  // function that reads the MPU and writes the data to the SD.
  {
   // Local variables:
    int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; // Variables read from MPU6050

    // Read data:
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
    AcX = Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
    AcY = Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ = Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    
    GyX = Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ = Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
    
    Serial.print(AcX);
    Serial.print(',');
    Serial.print(AcY);
    Serial.print(',');
    Serial.print(AcZ);
    Serial.print(',');
    Serial.print(GyX);
    Serial.print(',');
    Serial.print(GyY);
    Serial.print(',');
    Serial.print(GyZ);
    Serial.print(',');
    
    Serial.println();
    
    
    // Data preparation for file saving:
    String dataString = ""; // string for assembling the data to log:

    // Add time tag:
    dataString += String(Time0); dataString += ",";

    // Append the MPU6050 data to the string:
    dataString += String(AcX); dataString += ",";
    dataString += String(AcY); dataString += ",";
    dataString += String(AcZ); dataString += ",";
    dataString += String(GyX); dataString += ",";
    dataString += String(GyY); dataString += ",";
    dataString += String(GyZ);
    
    // Open the file in append mode:
    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    // If the file is available, write to it:
    if (dataFile) 
    {
    dataFile.println(dataString);
    dataFile.close();
    if (Serial_plus_SD)
      Serial.println(dataString);
    }
    // if the file does not open, pop up an error:
    else 
    errorFW();
    
    return;
  }

Why is not constant the logging time but sometimes is 40millisecond (see the image)? enter image description here

For me is important because my goal is to have a costant frequency to apply an FFT to study the noise and identify the best low pass filter.

How can I modify the frequency? I though to put a delay() on my code.

 void loop()
      {
        // Body of main/loop
        // Check status:
        Time0 = millis();
        Read_Write();
       // LED off and continue:
          digitalWrite(LEDpin, LOW);
          delay(80)
           }
Community
  • 1
  • 1
Andrea Ciufo
  • 359
  • 1
  • 3
  • 19
  • Even though *Arduino* adopts the *single-task* model, there is absolutely no guarantee that your code will execute on a constant *"speed"*. For instance, *interrupts* may occur, and in such a case the execution of their *ISR* might take precedence. Other issues might factor in, for example *memory accesses* and *memory handling*. And so on.. why do you keep `open()/close()` the *sd file*, wouldn't it be cheaper to leave it open? Also, all those `String` manipulations are quite slow. Adding *active* delays would actually accomplish nothing but slow down the entire sampling. – Patrick Trentin Feb 20 '17 at 19:56
  • If you are content with a lower sampling rate, you can *schedule* your read-write at *fixed* intervals of time, large enough to take into account possible slow downs due to other factors. Otherwise I would optimise as much as possible the code and simply use post-processing to transform the data into an 'acceptable' data rate. – Patrick Trentin Feb 20 '17 at 19:58
  • I found this material to study the Interruption related to the ISR [link](https://www.google.it/url?sa=t&rct=j&q=&esrc=s&source=web&cd=6&cad=rja&uact=8&ved=0ahUKEwiM68rB3KDSAhWBQBoKHV1CBrAQFghGMAU&url=http%3A%2F%2Fwww.dauniv.ac.in%2Fdownloads%2FEmbsysRevEd_PPTs%2FChap_4Lesson02EmsysNewInterruptBasedIOs.pdf&usg=AFQjCNGC8DjtFwx5-zTq_yDp2s0IQroGhA&sig2=2UfAN_T7gjoi4KYAH94s9A) Can you suggest me other referenced resources to go deep to the heart of the subject? How can i optimize the code changing the String Manipulation? – Andrea Ciufo Feb 21 '17 at 08:32
  • Slides are rarely a good source of information on their own, especially when taken out of their context (the class) and without reading all other preceding slides building up necessary basic knowledge. I think that [this](http://gammon.com.au/interrupts) is more to the point with respect to your needs: still a bit too technical, but self contained and of practical use. You could write *directly* on the `dataFile` just like you do on `Serial`. An improvement over this would be to write everything to a large enough `char[]` buffer first, and then dump it on both outputs. – Patrick Trentin Feb 21 '17 at 19:39
  • This would avoid translating each number to its string representation twice, and it would also avoid continuous dynamic memory allocation and free, consequences of your repeated use of `+=` among `Strings`. Your buffer needs space for 6 `int16_t` + 6 `,` and a final `\0` to close the *string*. An `int16_t` can be represented using at most `5` digits plus an optional *sign* symbol in case of negative value, that means that your buffer needs to be `6 * 6 + 6 + 1 = 43`. It is likely that you can *drop the last comma*, [continues] – Patrick Trentin Feb 21 '17 at 19:52
  • [continues] and also that you don't really need `int16_t` but you can deal with `uint16_t` instead: in this case you would spare an additional symbol for each value because no sign is required.. so the buffer would be *squeezed down* to `36` bytes. Then it would suffice to write `Serial.println(buffer); dataFile.println(buffer);`, and be done with it. Since `println()` is called only once for each output, the number of interrupts generated by these instructions is also minimised. – Patrick Trentin Feb 21 '17 at 19:56
  • I forgot to say that you can use a single call to `sprintf()` (see: [docs](http://www.cplusplus.com/reference/cstdio/sprintf/)) to dump the values in the buffer. – Patrick Trentin Feb 22 '17 at 04:42
  • Thanks for all the suggestions :) – Andrea Ciufo Feb 22 '17 at 18:06

0 Answers0