EEPROM.put() - execution time

Hi! I am trying to write data into my uno's EEPROM with EEPROM.put() but get a little bit confused relating to the execution time the command needs to be done.

My general plan is to save positions from stepper motors so that I would know the absolute positions of last run when the Arduino gets powered (in the following example I am trying just to save the "step status" of 8 possible steps for the moment). So I have to store values after every step my motor does.

So if I write the data with low time rates (such as every second) into the EEPROM everything is fine. The command then takes 5-12 microseconds.
After that I try to put the data into the EEPROM witch higher rates (every millisecond) and expected the execution time for the EEPROM.put() command would be similar to that few microseconds before. But in this case the command takes suddenly 3.2ms which means huge limitation for the application of the steppers.

If anyone could explain me this behaviour or could even show me a working way to save data with higher rates I would be really thankful.
A possible workaround would be to save data only once as effect after a button input evertime I plan to switch off the arduino. But I hope I can avoid that because its not really a nice solution for me..

Thanks for any help

  • Tim

Following the code:

#include "EEPROM.h"
 
#define STEPPER_PIN_1 10
#define STEPPER_PIN_2 11
#define STEPPER_PIN_3 12
#define STEPPER_PIN_4 13

#define STEPPER2_PIN_1 6
#define STEPPER2_PIN_2 7
#define STEPPER2_PIN_3 8
#define STEPPER2_PIN_4 9

#define LED_TEST_PIN A2
#define SPEED_INPUT_PIN A5

bool ledState = false;
bool rotDirection = true; // clockwise


unsigned long previousMicros = 0;        // will store last time step was done
long interval = 1000000;           // interval at which to do a (half)step (microseconds); absolute Minimum are 750us!
                                // should be >1000 to avoid problems (missed steps)

unsigned long t1 = 0;
unsigned long t2 = 0;

int8_t step_number1 = 0;
int8_t step_number2 = 0;

int inputSpeed = 0;

// Storage of current step numbers
unsigned int eeAdress1 = 0;
unsigned int eeAdress2 = eeAdress1 + 1;
unsigned int eeAdress3 = eeAdress2 + 1;


unsigned long k = 0;

void setup() {
  Serial.begin(115200);         // debug reasons..


  if (interval < 750) {
    interval = 750;     // absolute minimum are 750us for a half step!
  }

  pinMode(STEPPER_PIN_1, OUTPUT);
  pinMode(STEPPER_PIN_2, OUTPUT);
  pinMode(STEPPER_PIN_3, OUTPUT);
  pinMode(STEPPER_PIN_4, OUTPUT);

  pinMode(STEPPER2_PIN_1, OUTPUT);
  pinMode(STEPPER2_PIN_2, OUTPUT);
  pinMode(STEPPER2_PIN_3, OUTPUT);
  pinMode(STEPPER2_PIN_4, OUTPUT);
  
  pinMode(LED_TEST_PIN, OUTPUT);

  EEPROM.get(eeAdress1, step_number1);
  EEPROM.get(eeAdress2, step_number2);

  //step_number1 = 0;
  //step_number2 = 0;

  /*
  Serial.print("Letzter Schritt: ");
  Serial.println(step_number1);
  */
  
}

void loop() {
  /*
  int val = analogRead(SPEED_INPUT_PIN);  // delay between 0...512ms
  if (val < 512) {
    rotDirection = false;
    interval = val;
  } else {
    rotDirection = true;
    interval = 1023 - val;
  }
  interval = interval*1000;  // ms --> us
  */

  if (k<4096) {
    unsigned long currentMicros = micros();
    if (currentMicros - previousMicros >= interval) {
      previousMicros = currentMicros;
      if (ledState == true){
        ledState = false;
      } else {
        ledState = true;
      }
      digitalWrite(LED_TEST_PIN, ledState);

      step_number2 = HalfStep(2,rotDirection);
      step_number1 = HalfStep(1,rotDirection);
      
	  // measure time the uno needs to write 1 byte to EEPROM
      t1 = micros();
      EEPROM.put(eeAdress1, step_number1);
      t2 = micros();
      Serial.println(t2-t1);
      k++;
    }
  }

}

int HalfStep(int stepper, bool dir) {
  int pin1 = 99;
  int pin2 = 99;
  int pin3 = 99;
  int pin4 = 99;
  int8_t stepNumber = 0;
  unsigned int eeAdress = 0;
  switch (stepper) {
    case 1:
      pin1 = STEPPER_PIN_1;
      pin2 = STEPPER_PIN_2;
      pin3 = STEPPER_PIN_3;
      pin4 = STEPPER_PIN_4;
      stepNumber = step_number1;
      eeAdress = eeAdress1;
      break;
    case 2:
      pin1 = STEPPER2_PIN_1;
      pin2 = STEPPER2_PIN_2;
      pin3 = STEPPER2_PIN_3;
      pin4 = STEPPER2_PIN_4;
      stepNumber = step_number2;
      eeAdress = eeAdress2;
      break;
  }
  // calculate nextStep to be done
  if (dir) {
    stepNumber++;
  } else {
    stepNumber--;
  }
  if (stepNumber > 7) {
    stepNumber = 0;
  } else if (stepNumber < 0) {
    stepNumber = 7;
  }
    switch (stepNumber) {
      case 0:
        digitalWrite(pin1, true);
        digitalWrite(pin2, false);
        digitalWrite(pin3, false);
        digitalWrite(pin4, false);
        break;
      case 1:
        digitalWrite(pin1, true);
        digitalWrite(pin2, true);
        digitalWrite(pin3, false);
        digitalWrite(pin4, false);
        break;
      case 2:
        digitalWrite(pin1, false);
        digitalWrite(pin2, true);
        digitalWrite(pin3, false);
        digitalWrite(pin4, false);
        break;
      case 3:
        digitalWrite(pin1, false);
        digitalWrite(pin2, true);
        digitalWrite(pin3, true);
        digitalWrite(pin4, false);
        break;
      case 4:
        digitalWrite(pin1, false);
        digitalWrite(pin2, false);
        digitalWrite(pin3, true);
        digitalWrite(pin4, false);
        break;
      case 5:
        digitalWrite(pin1, false);
        digitalWrite(pin2, false);
        digitalWrite(pin3, true);
        digitalWrite(pin4, true);
        break;
      case 6:
        digitalWrite(pin1, false);
        digitalWrite(pin2, false);
        digitalWrite(pin3, false);
        digitalWrite(pin4, true);
        break;
      case 7:
        digitalWrite(pin1, true);
        digitalWrite(pin2, false);
        digitalWrite(pin3, false);
        digitalWrite(pin4, true);
        break;  
    }
  /*
  t1 = micros();
  EEPROM.put(eeAdress, stepNumber);
  t2 = micros();
  Serial.println(t2-t1);
  */
  return stepNumber;
}

Are you aware that on a UNO that the endurance (the number of times you can write to) the EEPROM is limited to 100,000 writes ?

At a write every mS the limt is reached fairly quickly .......................

he command then takes 5-12 microseconds.
After that I try to put the data into the EEPROM witch higher rates (every millisecond) and expected the execution time for the EEPROM.put() command would be similar to that few microseconds before. But in this case the command takes suddenly 3.2ms which means huge limitation for the application of the steppers.

The 5-12 microsecond value is an artifact of your measurement code. The physical write has not been completed.

Refer to the data sheet for your processor. The typical speeds are the 3.2 -3.4 ms range.

Google "avr eeprom write speed".

srnet:
Are you aware that on a UNO that the endurance (the number of times you can write to) the EEPROM is limited to 100,000 writes ?

At a write every mS the limt is reached fairly quickly .......................

No, I did not even know that, it's a useful information.. So I should use the command rare, such as one time in a session I use the uno.

@OP

1. An EEPROM location takes about 3ms - 5ms time for a data byte to get written into its location.

2. Because the internal EEPROM does not support page writing, the data writing time will be just proportional to the number of bytes you are about to write.

3. The data writing time could be improved by employing register level instructions with polling strategy rather than interrupt strategy as has been used in the EEPROM.h Library.