SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
#245377
I'm working on a project with the Artemis ATP. Its job is to turn a DC motor in a specific direction based on a schedule it receives via BLE and saves to its memory via emulated EEPROM.

I don't know why, but when the device is left alone and powered on for somewhere between 5 and 15 minutes, the EEPROM memory resets to 0xFF and I'm not sure why. Below are the relevant sections of EEPROM in terms of DEFINES, variables and functions called in order.
Code: Select all
#define BLE_DATA_LENGTH 505
#define BLE_DATA_BUFFER 505

#define LASTSTATEADDRESS     540
#define REFERENCEDAY_01       541
#define REFERENCEDAY_02       542

#define LASTJULIANDATE_01    545
#define LASTJULIANDATE_02    546
#define LASTOPRHOUR                547

void getSchedule(BLEDevice central, BLECharacteristic characteristic);

void setup() {
  scheduleGet.setEventHandler(BLEWritten, getSchedule);
  EEPROM.init();
  EEPROM.setLength(1024 * 1);
  initialize();
}

void loop() {
  // put your main code here, to run repeatedly:
  BLEDevice central = BLE.central();
  DateTime now = rtc.now();
  unsigned int Minute = now.minute();
  unsigned int Second = now.second();
  unsigned int currentHour = now.hour();
  unsigned int slotCheck = scheduleSlotGet();
  if(CheckHour != Hour)
  {
    CheckHour = now.hour();
    setLastDateHour();
  }
  if(CheckMinute != Minute)
  {
    CheckMinute = now.minute();
    updateTime();   
    batScanner();
  }
  switch(numberOfWeeks)
  {
    case(1):
    {
      if((Minute == 0 || Minute == 30) && (Second <= 5))
      {
        updateDoorPosition(slotCheck);
      }
      break;
    }
    case(2):
    {
      if((Minute == 0) && (Second <= 5))
      {
        updateDoorPosition(slotCheck);
      }
      break;
    }
    case(3):
    {
      if((Minute == 0) && (Second <= 5))
      {
        updateDoorPosition(slotCheck);
      }
      break;
    }
    case(4):
    {
      if((currentHour % 2 == 0) &&(Minute == 0) && (Second <= 5))
      {
        updateDoorPosition(slotCheck);
      }
      break;
    }
    case(5):
    {
      if((currentHour % 2 == 0) && (Minute == 0) && (Second <= 5))
      {
        updateDoorPosition(slotCheck);
      }
      break;
    }
    default:
      numberOfWeeks = 1;
      break;
  } 
}

void initialize()
{
  initializeSchedule();
  delay(5);
  checkLastDateHour();
  delay(5);
  initializeDCPosition();
}

void initializeSchedule()
{
  char scheduleChar[505];
  scheduleChar[0] = EEPROM.read(0);
  if(scheduleChar[0] == 0xFF)
  {
    numberOfWeeks = 1;
    scheduleChar[0] = char(numberOfWeeks);
  }
  else
  {
    numberOfWeeks = (int)scheduleChar[0];
  }
  for(int i=1; i < 505 ; i++)
  {
    scheduleChar[i]=EEPROM.read(i);
    weeklySchedule[i-1] = scheduleChar[i];
    if(weeklySchedule[i-1] != '0' && weeklySchedule[i-1] != '1') 
    {
      weeklySchedule[i-1] = '1';
      scheduleChar[i] = weeklySchedule[i-1];
    }
    else
    {
      delay(10);
    }
  }
 
  scheduleGet.writeValue(scheduleChar);
}

void checkLastDateHour()
{
  DateTime now = rtc.now();
  unsigned int currentJulianDate = getDayOfYear(now.year(), now.month(), now.day());
  byte currentOperationalHour = now.hour();
  byte LastSavedJulianDate_01 = EEPROM.read(LASTJULIANDATE_01);
  byte LastSavedJulianDate_02 = EEPROM.read(LASTJULIANDATE_02); 
  byte LastSavedOperationalHour = EEPROM.read(LASTOPRHOUR);
  unsigned int lastJulianDate = ((unsigned int)LastSavedJulianDate_01 << 8) +((unsigned int)(LastSavedJulianDate_02));

  if(currentJulianDate == lastJulianDate && (currentOperationalHour - LastSavedOperationalHour) < 2)
  {
    getReferenceDay();
  }
  else
  {
    updateReferenceDay();
  }
  setLastDateHour();
}

void setLastDateHour()
{
  DateTime now = rtc.now();
  byte LastSavedJulianDate_01 = 0;
  byte LastSavedJulianDate_02 = 0;
  byte LastSavedOperationalHour = now.hour();
  
  unsigned int currentJulianDate = getDayOfYear(now.year(), now.month(), now.day());

  LastSavedJulianDate_01 = (currentJulianDate >> 8);
  LastSavedJulianDate_02 = (currentJulianDate);

  EEPROM.write(LASTJULIANDATE_01, LastSavedJulianDate_01);
  EEPROM.write(LASTJULIANDATE_02, LastSavedJulianDate_02);
  EEPROM.write(LASTOPRHOUR, LastSavedOperationalHour);
  JulianDate.writeValue(referenceDay);
}

void getReferenceDay()
{
  byte referenceDayByte1 = EEPROM.read(541);
  byte referenceDayByte2 = EEPROM.read(542);
  referenceDay = (referenceDayByte1 << 8) + referenceDayByte2;
  JulianDate.writeValue(referenceDay);
}

void updateReferenceDay()
{
  byte referenceDayByte1 = 0;
  byte referenceDayByte2 = 0;
  DateTime now = rtc.now();
  unsigned int dayOfWeek = now.dayOfTheWeek();
  unsigned int dayOfYear = getDayOfYear(now.year(), now.month(), now.day());
  referenceDay = dayOfYear - dayOfWeek;

  referenceDayByte1 = (referenceDay >> 8);
  referenceDayByte2 = (referenceDay);
  EEPROM.write(541, referenceDayByte1);
  EEPROM.write(542, referenceDayByte2);
  JulianDate.writeValue(referenceDay);
}

void initializeDCPosition()
{
  unsigned int ScheduleSlot;
  bool CheckState;
  bool CurrentState;
  
  ScheduleSlot = scheduleSlotGet();
  CheckState = doorControl(ScheduleSlot);
  CurrentState = false;
  if(CurrentState != CheckState)
  {
    openDC();
    DoorOpened = true;
    DoorClosed = false;
  }
  EEPROM.write(LASTSTATEADDRESS, CheckState);
  cageState.writeValue(CheckState);
}


void getSchedule(BLEDevice central, BLECharacteristic characteristic){
  char scheduleChar[505];
  int dataLength = scheduleGet.readValue(scheduleChar, 505);
  numberOfWeeks = (int)scheduleChar[0];
  EEPROM.write(0, scheduleChar[0]);
  for(int i = 0; i < 504; i++)
  {
    weeklySchedule[i] = scheduleChar[i+1];
    EEPROM.write((i+1),weeklySchedule[i]);
    delay(5);
  }
  scheduleGet.writeValue(scheduleChar);
  updateReferenceDay();
}
The problem shows up when initialize() calls initializeSchedule(), which should go into the EEPROM and retrieve the schedule last received when the scheduleGet characteristic was written to by another device. As soon as that characteristic is written to, the device collects the new schedule and writes it to the Artemis' flash memory. If I turn off the device then and there and turn it back on, then check with nRF connect, the characteristic will have the right schedule. If I leave the device running for several minutes, I can check the characteristic again and find the schedule STILL there. However, if I then turn it off and on again, I will see a blank schedule as the memory reverted to all 0xFFs, and was then adjusted to all 1s by the initialize function.

What's weird to me is that if I upload a new schedule, turn off the device and leave it for a while, this problem doesn't occur.
This only happens if I leave the device on and unattended for several minutes. I'm still testing to see if leaving it connected to BLE affects this or not, but for now just assume a BLE connection isn't relevant.

Does anyone know what might be happening?
#245465
It seems like there might be an issue with the stability of the EEPROM on the Artemis ATP board, possibly related to power or clock management. Here are a few suggestions to troubleshoot and address the issue:

Power Supply Stability:

Ensure that the power supply to the Artemis ATP is stable. Fluctuations in power could affect EEPROM operations.
Check if there are any voltage drops or spikes during operation.
Clock Configuration:

Verify that the clock configuration for the EEPROM is appropriate. EEPROM operations depend on stable clock signals.
Ensure that the clock settings are compatible with the EEPROM datasheet.
Delay After EEPROM Write:

Add a delay after writing to the EEPROM to allow sufficient time for the write operation to complete.
Experiment with different delay times to find the optimal value.
Verify EEPROM Initialization:

Implement additional checks to verify the EEPROM content during the initialization process.
Log or print the EEPROM content at different stages of the program to identify when the data gets corrupted.
Update Firmware/Arduino Core:

Ensure that you are using the latest firmware for the Artemis ATP and the latest Arduino core for Ambiq Apollo3.
Check for any known issues or bug fixes related to EEPROM operations in the release notes.
Investigate Sleep Modes:

If the Artemis ATP has sleep modes or power-saving features, investigate whether they are affecting EEPROM stability.
Experiment with disabling certain features to see if it resolves the issue.
Temperature Considerations:

Extreme temperatures can sometimes affect EEPROM performance. Ensure that the operating temperature is within the specified range.
Contact Manufacturer/Community:

Reach out to the manufacturer or community forums for the Artemis ATP board to see if others have experienced similar issues.
Check for any errata or known issues with the Artemis ATP EEPROM.
By systematically addressing these aspects, you may be able to identify the root cause of the EEPROM data corruption issue.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum