Esp32 cant keep a i2c 10hz communication

hello everyone
So I have a project in which esp32 receive data from a gnss receiver at 5hz via i2c comunication and its actually running smooth, but when a change to 7hz it just dont work as smooth, is it because i2c have a default speed that isnt compatible with the one I want? or is it because esp32 takes too long to run the entire "void loop" part of the code, since it collect the data and save some of it on a sd card before collecting it again?

Probably your code... but hard to say unless you post it so we can have a look.

void loop(){
if(digitalRead(but) == HIGH) //funcitons based off of button pulling input pin HIGH
   {
      if(run == 0)
      {
          run = 255;
      }
      else
      {
          run = 0;
      }
   }

   if(run > 0)
   {

  digitalWrite(yellow, LOW);
  digitalWrite(green, HIGH);  

  myGNSS.checkUblox(); // Check for the arrival of new data and process it.

  myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.

  while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer
  {
    myFile = sd.open("testFolder/RXM_RAWX.ubx", FILE_WRITE);

    digitalWrite(LED, HIGH); // Flash LED_BUILTIN each time we write to the SD card

    myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer

    //myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card
    myFile.write(myBuffer, sdWriteSize);

    // In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data
    myGNSS.checkUblox(); // Check for the arrival of new data and process it.
    myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.

    digitalWrite(LED, LOW); // Turn LED_BUILTIN off again
  }
   }
  

  if (millis() > (lastPrint + 1000)) // Print the message count once per second
  {
    Serial.print(F("Number of message groups received: SFRBX: ")); // Print how many message groups have been received (see note above)
    Serial.print(numSFRBX);
    Serial.print(F(" RAWX: "));
    Serial.println(numRAWX);

    uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now)

    Serial.print(F("The maximum number of bytes which the file buffer has contained is: ")); // It is a fun thing to watch how full the buffer gets
    Serial.println(maxBufferBytes);

    if (maxBufferBytes > ((fileBufferSize / 5) * 4)) // Warn the user if fileBufferSize was more than 80% full
    {
      Serial.println(F("Warning: the file buffer has been over 80% full. Some data may have been lost."));
    }

    lastPrint = millis(); // Update lastPrint
  }
  
  
  if (digitalRead(Button) == HIGH) // Check if the user wants to stop logging
  {
    uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer

    while (remainingBytes > 0) // While there is still data in the file buffer
    {
      digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card

      uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time
      if (bytesToWrite > sdWriteSize)
      {
        bytesToWrite = sdWriteSize;
      }

      myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer

      myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card

      remainingBytes -= bytesToWrite; // Decrement remainingBytes
    }

    digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off

    myFile.close(); // Close the data file

    Serial.println(F("Logging stopped. Freezing..."));
    digitalWrite(yellow, LOW);
    digitalWrite(green, LOW);
    delay(200);
    digitalWrite(LED, HIGH);
    digitalWrite(yellow, HIGH);
    digitalWrite(green, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    digitalWrite(yellow, LOW);
    digitalWrite(green, LOW);
    delay(500);
    digitalWrite(LED, HIGH);
    digitalWrite(yellow, HIGH);
    digitalWrite(green, HIGH);
    delay(500);
    digitalWrite(LED, LOW);
    digitalWrite(yellow, LOW);
    digitalWrite(green, LOW);
    while(1);// Do nothing more
  } 
  
  }

the code is writing 1024 bytes into sd card every loop
the gnss module that is sending the data to the esp32 should be working at 7hz
I also have a buffer keeping the data and it looks like the writing speed of the sd card is prettly good since the buffer is not getting full at all

Why do you do this every time you write to the card, rather than once?

This is not a good way to handle millis as it doesn't handle rollover correctly. Better to do as below...

if (millis() - lastPrint > 1000)
1 Like

now that you mention it, it does look weird. thanks for the letting me know ill do some changes

damn, although the changes a made did affect the quality of the data written in the sd card, it didnt help with the frequency problem. I am thankfull anyway.
maybe its the i2c speed that is blocking the data.
here is a image from serial monitor at 7hz:

and here its at 5hz:

I should be receiving way more RAWX data, it did happen before, that time a fixed it by soldering a shorter and better wire as i2c connection.

Can you show a schematic of your setup? Are you using pull up resistors?

The maximum speed of the ESP32's I2C module is 4Mhz.

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html

The bottleneck is probably the SD card.

im not using pull up resistors

do you mean the actual SD card? or the code for the SD card?
I am using a sandisk ultra 32GB, formated exfat
maybe the SPI speed? mine is set to 12mhz, I know that esp32 is capable of reaching 80 mhz, but for some reason 12 mhz is the max I was able to set without sd card fail to initialize

void initSDCard() {

  uint32_t t = millis();

  // Initialize at the highest speed supported by the board that is
  // not over 50 MHz. Try a lower speed if SPI errors occur.
  if (!sd.begin(SD_CHIP_SELECT_PIN, SD_SCK_MHZ(12))) {
    
    Serial.println("sd.begin failed");
    return;
  }

  t = millis() - t;
  cardSize = sd.card()->sectorCount();
  
  if (cardSize == 0) {
  
    Serial.println("cardSize failed");
    return;
  }
  
  Serial.print(F("\ninit time: "));
  Serial.print(t);
  Serial.println(" ms");
}

If you are still opening the SD file, writing a bit of data, then closing it again, STOP DOING THAT. That slows I/O to a crawl and vastly increases the SD card error rate.

Open the file once in setup() and close it again when you are all done collecting data. During long term data collection, update file pointers and protect yourself from power failures by calling SD.flush() every hour or so.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.