Flashee-EEPROM not working [SOLVED]

I have tried to incorporate this into my program as I need to have a value stored in NVM just in case the power goes out. with the code I have as of right now it makes the core gets stuck in some sort of weird boot loop (I think the problem is in setup() ) but i don’t really know. I basically am coming into this whole NVM thing without a clue of how to use it so some help would be appreciated. And yes I already look here: https://github.com/m-mcgowan/spark-flashee-eeprom . That is where I got my code from,

// This #include statement was automatically added by the Spark IDE.
#include "flashee-eeprom/flashee-eeprom.h"
 using namespace Flashee;

//declare variables for the motor pins
int turnD = D3; // turn DOWN
int turnU = D2; // Turn UP
int sensor = D6; // Hall Effect sensor input
bool isUp = false; // If up or not
int upcounter = 0;
int maxSteps = 1980;
int ONE_DAY_MILLIS = 86400000; // number of Milliseconds in one day
int lastSync = 0;
int month = 1;
int day = 1;
int weekday = 1;
bool partWayDownGoUp = false;
bool partWayGoDown = false;
int downTime = 1980;
String alarmTime = "";
String currentTime = "";
bool alarmEnabled = true;
String PassCommand = "";
String semi = ":";
String AM = "AM";
String PM = "PM";
char buff[50];
FlashDevice* device = Devices::createWearLevelErase();
FlashWriter writer(device);
FlashReader reader(device);

//////////////////////////////////////////////////////////////////////////////
void setup() {
    // setup function to act on Spark API calls
    Spark.function("Blind", BlindControl);
    Spark.function("SetTime", setTimer);
    Spark.function("isTimerEnabl", checkTimerState);
    
    //Get date then check if we should put time zone to Daylight Savings Time or not
    int unixStampTime = Time.now(); //Returns Unix Time (Seconds)
    month = Time.month(unixStampTime);
    day = Time.day(unixStampTime);
    weekday = Time.weekday(unixStampTime);
    if(month < 3 && weekday == 7 && day > 7 || month >= 11 && weekday == 7 && day > 7){
        Time.zone(-5);//Set to est zone
    }
    else{
        Time.zone(-4);//set to est DST time zone
    }
    Spark.syncTime();//sync time just in case
    //declare the motor pins as outputs
    pinMode(sensor, INPUT);
    pinMode(turnU, OUTPUT);
    pinMode(turnD, OUTPUT);
    digitalWrite(turnU, HIGH);
    digitalWrite(turnD, HIGH);
    
    reader.readString(buff);
    alarmTime = buff;
    if(digitalRead(sensor) == LOW){
        goDown();
    }
    //setBlindsUp();//set blinds to up position
}

//////////////////////////////////////////////////////////////////////////////

void loop(){
    getCurrentTime();//Get time to compare to alarm time below
    if(alarmTime.equals(currentTime) && alarmEnabled == true){
        PassCommand = "Open";
        BlindControl(PassCommand);  
    }
    //Check if we need to compensate for DST
    getDate();
    if(month < 3 && weekday == 7 && day > 7 || month >= 11 && weekday == 7 && day < 7){
        Time.zone(-5);
    }
    else{
        Time.zone(-4);
    }
    // Request time synchronization from the Spark Cloud once per day
    if (millis() - lastSync > ONE_DAY_MILLIS) {
        Spark.syncTime();
        lastSync = millis();
    }
    delay(100);//just delay a bit because we can :)
}

//////////////////////////////////////////////////////////////////////////////

int BlindControl(String command){
   if (command=="Open") {
       while(isUp == false){
            goUp();
            delay(100);
       }
       digitalWrite(turnU, HIGH);
   }
   if (command=="Close" && isUp == true) {
       goDown();
   }
   return 1;
}

///////////////////////////////////////////////////////////////////////////////

int setTimer(String alarmSetTime){
    alarmTime = "";
    alarmTime = alarmSetTime;
    writer.writeString("hello");
    return 1;
}

///////////////////////////////////////////////////////////////////////////////

int checkTimerState(String state){
    if(state == "On"){
        alarmEnabled = true;
    }
    else if(state == "Off"){
        alarmEnabled = false;
    }
    return 1;
}

//////////////////////////////////////////////////////////////////////////////

void goUp(){
    digitalWrite(turnU, LOW);
    isUp = checkPosition();
    delay(100);
    upcounter += 100;
}

//////////////////////////////////////////////////////////////////////////////

void goDown(){//find out why this is fireing twice
    digitalWrite(turnD, LOW);
    if(partWayGoDown = true){
        downTime = 198000 - upcounter;
    }
    for (int i = 0; i < 4; i++){
        delay(downTime/4);
    }
    digitalWrite(turnD, HIGH);
    isUp = false;
    downTime = 198000;
    partWayGoDown = false;
}

//////////////////////////////////////////////////////////////////////////////

bool checkPosition(){
    bool isUpOrNot = false;
    if(digitalRead(sensor) == LOW){
        isUpOrNot = true;
    }
    else if(digitalRead(sensor) == HIGH){
        isUpOrNot = false;
    }
    return isUpOrNot;
}

//////////////////////////////////////////////////////////////////////////////

void setBlindsUp(){
    while(digitalRead(sensor) == HIGH){
        digitalWrite(turnU, LOW);
    }
    digitalWrite(turnU, HIGH);
    isUp = true;
}

//////////////////////////////////////////////////////////////////////////////

void getCurrentTime(){
    //Gets Current time
    currentTime = "";
    int unixTime = Time.now(); //Returns Unix Time (Seconds)
    int hour = Time.hourFormat12(unixTime);
    String hourSTR = String(hour);
    int min = Time.minute(unixTime);
    String minSTR = String(min);
    int sec = Time.second(unixTime);
    String secSTR = String(sec);
    bool isAm = Time.isAM();
    
    if(isAm == true){
        currentTime.concat(hourSTR);
        currentTime.concat(semi);
        currentTime.concat(minSTR);
        currentTime.concat(semi);
        currentTime.concat(secSTR);
        currentTime.concat(AM);
    }
    else{
        currentTime.concat(hourSTR);
        currentTime.concat(semi);
        currentTime.concat(minSTR);
        currentTime.concat(semi);
        currentTime.concat(secSTR);
        currentTime.concat(PM);
    }
}

//////////////////////////////////////////////////////////////////////////////

void getDate(){
    //Gets Current date
    int unixStamp = Time.now(); //Returns Unix Time (Seconds)
    month = Time.month(unixStamp);
    day = Time.day(unixStamp);
    weekday = Time.weekday(unixStamp);
} 

I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~Jordy

This is @mdma Matt’s code but I seem to recall that you need to allocate at least three pages when you create the device with Devices::createWearLevelErase();. It needs room to do the wear-leveling work and I don’t think the default constructor gives it that.

not that its your issue, but FYI, a little function for you…

void setup()
{
}
void loop()
{
   bool daylightSavings = IsDST(Time.day(), Time.month(), Time.weekday());
  Time.zone(daylightSavings? -4 : -5);
  // your other stuff that may depend on the time...
}

bool IsDST(int dayOfMonth, int month, int dayOfWeek)
{
  if (month < 3 || month > 11)
  {
    return false;
  }
  if (month > 3 && month < 11)
  {
    return true;
  }
  int previousSunday = dayOfMonth - (dayOfWeek - 1); // Spark Sunday = 1
  //In march, we are DST if our previous sunday was on or after the 8th.
  if (month == 3)
  {
    return previousSunday >= 8;
  }
  //In November we must be before the first sunday to be dst.
  //That means the previous sunday must be before the 1st.
  return previousSunday <= 0;
}

So what should I add/change?

Well, it is not my code but the tests do this:

Devices::createWearLevelErase(0, 4096*256, 256-32)

now the other problem is this:

writer.writeString(alarmTimeChar);

the writer does not let me use a string value it says I need a const char*. What should I do?

That is not in your code above so I can't say for sure.

I would bet that you declared that as a String alarmTimeChar; and not char alarmTimeChar[32];. If I am right then you need to do this:

writer.writeString(alarmTimeChar.c_str());

String means different tings in this case and the library does not use Arduino String objects.

1 Like

Yeah sorry about not showing the whole function

int setTimer(String alarmSetTime){
    int len;
    alarmTime = "";
    alarmTime = alarmSetTime;
    len = alarmTime.length();
    writer.writeString(alarmTime);
    return 1;
}

That is the entire function, and I am trying to figure out how I can write the alarmTime string. And I always get these Errors:

motortesting2.cpp: In function 'int setTimer(String)':
motortesting2.cpp:113:33: error: no matching function for call to 'Flashee::FlashWriter::writeString(String&)'
}
^
motortesting2.cpp:113:33: note: candidate is:
In file included from motortesting2.cpp:2:0:
flashee-eeprom/flashee-eeprom.h:382:10: note: void Flashee::FlashWriter::writeString(const char*)
void writeString(const char* s) {
^
flashee-eeprom/flashee-eeprom.h:382:10: note: no known conversion for argument 1 from 'String' to 'const char*'

Have you tried adding the .c_str() method as i showed above?

I just did and it literally just worked thank-you so much :smile:

3 Likes

I recommend initializing the FlashDevice in your setup() code rather than initializing as a global variable. The problem is that with C++ modules are initialized in an arbitrary order, so there’s no guarantee the globals in flashee are initialized before your own program globals.

So the code becomes:

FlashDevice* flash;

void setup() {
   flash = Devices::createAddressErase();
}

I recommend the address erase scheme since it allows the most rewrites.

1 Like