0

Trinket MO, #include <EEPROM.h>?
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Trinket MO, #include <EEPROM.h>?

by jim_lee on Mon Aug 05, 2019 3:55 am

I'd like to store some data in my EEPROM. I -do- have some EEPROM to store things in don't I? Because the compiler is telling me that there is no such file EEPROM.h.

Is there some different way to do this that I missed? Anyone?

-jim lee

jim_lee
 
Posts: 546
Joined: Thu May 24, 2012 8:24 pm

Re: Trinket MO, #include <EEPROM.h>?

by franklin97355 on Mon Aug 05, 2019 4:03 am

The EEPROM library does not seem to have been ported for SAMD boards.

franklin97355
 
Posts: 21105
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: Trinket MO, #include <EEPROM.h>?

by jim_lee on Mon Aug 05, 2019 5:44 am

Err.. Is there any option? I'm in deep if there's no way to store some parameters.

-jim lee

jim_lee
 
Posts: 546
Joined: Thu May 24, 2012 8:24 pm

Re: Trinket MO, #include <EEPROM.h>?

by franklin97355 on Mon Aug 05, 2019 12:20 pm


franklin97355
 
Posts: 21105
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: Trinket MO, #include <EEPROM.h>?

by jim_lee on Mon Aug 05, 2019 4:34 pm

Ugh!! I guess I'm not alone with this issue. That solution might work. 10,000 cycles might be more than the product's lifespan? Maybe? Probably?

Another idea.. Would this work on the same pins as a moisture sensor? I'm completely out of pins. I've used all 5 of them already.

https://www.adafruit.com/product/1895

-jim lee

jim_lee
 
Posts: 546
Joined: Thu May 24, 2012 8:24 pm

Re: Trinket MO, #include <EEPROM.h>?

by jim_lee on Tue Aug 06, 2019 1:40 am

Well that was a bit depressing. I set it up and ran it. Never even tried to write any params. It just killed my Trinket MO. Double clicking the reset lets me burn programs into it, but they don't run anymore. (Not even blink) And then it complains about loosing its port. Looking at the menu, there is no longer any port to choose. Now its stuck like this until you double click the reset again. And do it all over again.

-jim lee

jim_lee
 
Posts: 546
Joined: Thu May 24, 2012 8:24 pm

Re: Trinket MO, #include <EEPROM.h>?

by XRAD on Wed Aug 07, 2019 10:42 am

here is some base EEPROM code which I have used and works on adafruit feathers, may be of use on a trinket M0 (adapt to your needs):
Code: Select all | TOGGLE FULL SIZE
#include <EEPROM.h>
 
#define SAMPLE_TIME 2000  //The time between each EEPROM write function call in ms
 
int tempPin = 0;      //the ADC pin
int printPin = 2;     //the print button pin
int erasePin = 4;    //the erase button pin
 
int address = 0;      //EEPROM address counter
 
unsigned long timer;
 
float conv_coeff = 0.0;   //coefficient for converting from 0-1024 to 0-5 range
 
void printTemp();
void clearEEPROM();
void writeTemp();
 
void setup(){
  Serial.begin(115200);     //start the serial connection as always
  conv_coeff = 5.0/1024.0;  //find the coefficient to do the conversion
  timer = millis();         //millis() returns the time since program start in ms
}
 
void loop(){
  if(millis()-timer > SAMPLE_TIME)  //check if it's time to do a temp sensor sample
  {
    writeTemp();
    timer = millis();
  }
 
  if(!digitalRead(printPin))  //check if print button is pressed
  {
    printTemp();
    delay(500);
  }
 
  if(!digitalRead(erasePin)) //check if erase button is pressed
  {
    clearEEPROM();
    delay(500);
  }
   
  delay(1);
}
 
void printTemp()
{
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    byte value = EEPROM.read(i);                //read EEPROM data at address i
    if(value != 0)                              //skip "empty" addresses
    {
      float temp = value*conv_coeff;            //convert ADC values to temperature
      temp = (temp - 0.5)*100;                  //take care of the offset
 
      Serial.println(temp);
    }
  }
}
 
void clearEEPROM()
{
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    if(EEPROM.read(i) != 0)                     //skip already "empty" addresses
    {
      EEPROM.write(i, 0);                       //write 0 to address i
    }
  }
  Serial.println("EEPROM erased");
  address = 0;                                  //reset address counter
}
 
void writeTemp()
{
  byte value = analogRead(tempPin);     //read sensor value
   
  EEPROM.write(address, value);         //write value to current address counter address
 
  Serial.print("Sensor value stored at address ");
  Serial.println(address);
   
  address++;                      //increment address counter
  if(address == EEPROM.length())  //check if address counter has reached the end of EEPROM
  {
    address = 0;              //if yes: reset address counter
  }
}


and this is a longer code which I used the above and adapted to use the above(you can tease out what you need):

Code: Select all | TOGGLE FULL SIZE

//my best touch keypadlock arduino


#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <Adafruit_STMPE610.h>
#include <EEPROM.h>



#if defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__) || \
    defined(ARDUINO_SAMD_ZERO) || defined(__SAMD51__) || defined(__SAM3X8E__) || defined(ARDUINO_NRF52840_FEATHER)
#define STMPE_CS 6
#define TFT_CS   9
#define TFT_DC   10
#define SD_CS    5
#endif

#ifdef TEENSYDUINO
#define TFT_DC   10
#define TFT_CS   4
#define STMPE_CS 3
#define SD_CS    8
#endif

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

// The STMPE610 uses hardware SPI on the shield,
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);

// This is calibration data for the raw touch data to the screen coordinates 320x240 feather
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 3750

/******************* UI details */
#define BUTTON_X 40
#define BUTTON_Y 100
#define BUTTON_W 60
#define BUTTON_H 30
#define BUTTON_SPACING_X 20
#define BUTTON_SPACING_Y 20
#define BUTTON_TEXTSIZE 2

// text box where numbers go
#define TEXT_X 10
#define TEXT_Y 10
#define TEXT_W 220
#define TEXT_H 50
#define TEXT_TSIZE 3
#define TEXT_TCOLOR ILI9341_MAGENTA

// the data (code #) we store in the textfield
#define TEXT_LEN 12
char textfield[TEXT_LEN + 1] = "";
uint8_t textfield_i = 0;

//int tempPin = 0;      //the ADC pin
//int printPin = 2;     //the print button pin
//int erasePin = 1;    //the erase button pin

int address = 0;      //EEPROM address counter

void printTextfield();
void clearEEPROM();
void writeTextfield();

float conv_coeff = 0.0;   //coefficient for converting from 0-1024 to 0-5 range




//  status txt line
#define STATUS_X 10
#define STATUS_Y 65

#define STATUS_BOOT_X 18
#define STATUS_BOOT_Y 25

/* create 15 buttons, in classic candybar phone style */
char buttonlabels[15][5] = {"ENTR", "CLR1", "VOID", "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#" };
uint16_t buttoncolors[15] = {ILI9341_DARKGREEN, ILI9341_RED, ILI9341_RED,
                             ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE,
                             ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE,
                             ILI9341_BLUE, ILI9341_BLUE, ILI9341_BLUE,
                             ILI9341_DARKGREY, ILI9341_BLUE, ILI9341_DARKGREY
                            };
Adafruit_GFX_Button buttons[15];

// Print something in the mini status bar with either flashstring
void status(const __FlashStringHelper *msg) {
  tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK);
  tft.setCursor(STATUS_X, STATUS_Y);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(1);
  tft.print(msg);
}
// or charstring
void status(char *msg) {
  tft.fillRect(STATUS_X, STATUS_Y, 240, 8, ILI9341_BLACK);
  tft.setCursor(STATUS_X, STATUS_Y);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(1);
  tft.print(msg);
}


void statusBoot(const __FlashStringHelper *msg) {
  tft.fillRect(STATUS_BOOT_X, STATUS_BOOT_Y, 205, 20, ILI9341_BLACK);
  tft.setCursor(STATUS_BOOT_X, STATUS_BOOT_Y);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.print(msg);
}

void statusBoot(char *msg) {
  tft.fillRect( STATUS_BOOT_X, STATUS_BOOT_Y, 205, 20, ILI9341_BLACK);
  tft.setCursor(STATUS_BOOT_X, STATUS_BOOT_Y);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.print(msg);
}



String password = "0000"; //Variable to store the current password
String tempPassword = ""; //Variable to store the input password
//int doublecheck;    //Check twice the new passoword
//boolean armed = false;  //Variable for system state (armed:true / unarmed:false)
//boolean input_pass;   //Variable for input password (correct:true / wrong:false)
//boolean storedPassword = true;
//boolean changedPassword = false;
//boolean checkPassword = false;
//int i = 1; //variable to index an array




void setup() {
  Serial.begin(115200);
  Serial.println("KEYPADLOCK");

  // clear the screen
  tft.begin();

  //tft.setRotation(0);
  tft.fillScreen(ILI9341_BLACK);

  // eep touchscreen not found?
  if (!ts.begin()) {
    Serial.println("Couldn't start touchscreen controller");
    while (1);
  }
  Serial.println("Touchscreen started");

  // create buttons
  for (uint8_t row = 0; row < 5; row++) {
    for (uint8_t col = 0; col < 3; col++) {
      buttons[col + row * 3].initButton(&tft, BUTTON_X + col * (BUTTON_W + BUTTON_SPACING_X),
                                        BUTTON_Y + row * (BUTTON_H + BUTTON_SPACING_Y), // x, y, w, h, outline, fill, text
                                        BUTTON_W, BUTTON_H, ILI9341_WHITE, buttoncolors[col + row * 3], ILI9341_WHITE,
                                        buttonlabels[col + row * 3], BUTTON_TEXTSIZE);
      buttons[col + row * 3].drawButton();
    }
  }

  // create 'text field'
  tft.drawRect(TEXT_X, TEXT_Y, TEXT_W, TEXT_H, ILI9341_WHITE);



  for (int i = 0; i < 5; i++) {
    statusBoot(F("RESTRICTED ACCESS"));
    delay(500);
    clearText();
    delay(100);
  }

  conv_coeff = 5.0 / 1024.0;
  //conv_coeff = 1;//find the coefficient to do the conversion
}


void loop(void) {
  TS_Point p;

  if (ts.bufferSize()) {
    p = ts.getPoint();
  } else {
    // this is our way of tracking touch 'release'!
    p.x = p.y = p.z = -1;
  }

  // Scale from ~0->4000 to tft.width using the calibration #'s
  if (p.z != -1) {
    p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
    p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
    Serial.print("("); Serial.print(p.x); Serial.print(", ");
    Serial.print(p.y); Serial.print(", ");
    Serial.print(p.z); Serial.println(") ");
  }

  // go thru all the buttons, checking if they were pressed
  for (uint8_t b = 0; b < 15; b++) {
    if (buttons[b].contains(p.x, p.y)) {
      //Serial.print("Pressing: "); Serial.println(b);
      buttons[b].press(true);  // tell the button it is pressed
    } else {
      buttons[b].press(false);  // tell the button it is NOT pressed
    }
  }

  // now we can ask the buttons if their state has changed
  for (uint8_t b = 0; b < 15; b++) {
    if (buttons[b].justReleased()) {
      // Serial.print("Released: "); Serial.println(b);
      buttons[b].drawButton();  // draw normal
    }

    if (buttons[b].justPressed()) {
      clearText();
      buttons[b].drawButton(true);  // draw invert!

      // if a numberpad button, append the relevant # to the textfield
      if (b >= 3) {
        if (textfield_i < TEXT_LEN) {
          textfield[textfield_i] = buttonlabels[b][0];
          textfield_i++;
          textfield[textfield_i] = 0; // zero terminate

        }
      }

      if (b == 12) {
        clearEEPROM();
        delay(2000);
      }



      if (b == 14) {
        printTextfield();
        delay(2000);
      }



      // clr button! delete char
      if (b == 1) {
        status(F("CLEARING LAST DIGIT..."));
        textfield[textfield_i] = 0;
        if ( textfield_i <= 0) {
          textfield_i = 0;
        }
        else {
          if (textfield > 0) {
            textfield_i--;
            textfield[textfield_i] = ' ';
          }
        }
      }


      // update the current text field
      Serial.println(textfield);
      tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
      tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
      tft.setTextSize(TEXT_TSIZE);
      tft.print(textfield);

      //clear all characters
      if ((b == 2) && (textfield > 0))  {
        status(F("CLEARING FULL CODE..."));
        for (int i = 0; i < 13 ; i++) {
          if ( textfield_i <= 0) {
            textfield_i = 0;
          }
          else {
            textfield_i-- ;
            textfield[textfield_i] = ' ';
          }
        }
      }

      // update the current text field
      Serial.println(textfield);
      tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
      tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
      tft.setTextSize(TEXT_TSIZE);
      tft.print(textfield);

      // enter code for verification
      if (b == 0) {

        tempPassword = textfield;


        if (tempPassword == password) {
          status(F("ACCESS GRANTED..."));
          Serial.print("ACCESS GRANTED   CODE: "); Serial.print(textfield);
          tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
          tft.setTextColor( ILI9341_BLUE, ILI9341_BLACK);
          tft.setTextSize(TEXT_TSIZE);
          tft.print(textfield);

          writeTextfield();////eeprom

          delay(250);




          if (textfield > 0)  {
            for (int i = 0; i < 13 ; i++) {
              if ( textfield_i <= 0) {
                textfield_i = 0;
              }
              else {
                textfield_i-- ;
                textfield[textfield_i] = ' ';
              }
            }
          }
          Serial.print(textfield);
          tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
          tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
          tft.setTextSize(TEXT_TSIZE);
          tft.print(textfield);


          for (int i = 0; i < 5; i++) {
            clearText();
            delay(100);
            statusBoot(F(" LIDAR ACTIVATED"));
            delay(500);
          }
        }

        else {

          status(F("CONFIRMING CODE....ACCESS DENIED"));
          Serial.print("CONFIRMING CODE....ACCESS DENIED");
          delay(500);
          //clear all characters
          if (textfield > 0)  {
            status(F("CLEARING FULL CODE..."));
            for (int i = 0; i < 13 ; i++) {
              if ( textfield_i <= 0) {
                textfield_i = 0;
              }
              else {
                textfield_i-- ;
                textfield[textfield_i] = ' ';
              }
            }
          }
          Serial.print(textfield);
          tft.setCursor(TEXT_X + 2, TEXT_Y + 10);
          tft.setTextColor(TEXT_TCOLOR, ILI9341_BLACK);
          tft.setTextSize(TEXT_TSIZE);
          tft.print(textfield);
        }
      }

      delay(100); // UI debouncing
    }
  }
}


void clearText() {
  tft.fillRect( STATUS_BOOT_X, STATUS_BOOT_Y, 205, 20, ILI9341_BLACK);
}





void printTextfield()
{
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    byte value = EEPROM.read(i);                //read EEPROM data at address i
    if (value != 0)                             //skip "empty" addresses
    {

      float newCode = value;

      Serial.println(newCode);
    }
  }
}


void clearEEPROM()
{
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    if (EEPROM.read(i) != 0)                    //skip already "empty" addresses
    {
      EEPROM.write(i, 0);                       //write 0 to address i
    }
  }
  Serial.println("EEPROM erased");
  address = 0;                                  //reset address counter
}

void writeTextfield()
{
 
  byte value = textfield;

  EEPROM.write(address, value);//write value to current address counter address, like string to int?

  Serial.println();
  Serial.print("Code value stored at address ");
  Serial.print(address); Serial.print(": ");
  Serial.println(value);

  address++;                      //increment address counter
  if (address == EEPROM.length()) //check if address counter has reached the end of EEPROM
  {
    address = 0;              //if yes: reset address counter
  }
}



check out:
https://www.arduino.cc/en/Reference/EEPROM

you other option which works GREAT is a feather adalogger using SD to store data. I know it's not the Trinket but may work for you.... or you could store the data through the trinket to a separate SD reader......

XRAD
 
Posts: 507
Joined: Sat Nov 19, 2016 3:28 pm

Re: Trinket MO, #include <EEPROM.h>?

by jim_lee on Wed Aug 07, 2019 1:09 pm

@XRAD

The base issue is that EEPROM.h library was never ported to the MO processors. I'm not sure if it even has any of that flavor of EEPROM to port it to. That's why some have worked on stuffing parameters into the EEPROM of your code. (Or that's what I understood when I looked at it.).

Anyway, I'm just going to swap out for my usual goto, the Teensy 3.2. Its sad, because the Trinket MO is such a neat little machine. Lots of horsepower, tiny package and cost less than dirt.

-jim lee

jim_lee
 
Posts: 546
Joined: Thu May 24, 2012 8:24 pm

Re: Trinket MO, #include <EEPROM.h>?

by oesterle on Wed Aug 07, 2019 3:42 pm

Hi, jim_lee!

I love the Trinket M0. But I hear you on the pins and rewritable storage.

I'd consider the Adafruit ItsyBitsy M0 Express, or the Adafruit ItsyBitsy M4 Express, both of which have many more pins.

While similar in size to the venerable Teensy 3.2, they also add 2 MB of onboard, separate SPI flash storage. That should be much more usable/reusable for logging than EEPROM.

Ladyada shows how to use SPI flash in Arduino in the ItsyBitsy M0's primary product guide, and Kattni Remblor shows how it works with CircuitPython's storage module.

What are you making?

Cheers,

Eric

oesterle
 
Posts: 648
Joined: Tue Sep 17, 2013 11:32 pm

Re: Trinket MO, #include <EEPROM.h>?

by jim_lee on Thu Aug 08, 2019 4:28 am

Well.. Next time. I like the look of the m4 Express. But I already have #1 robot gardener out watching my plants running on a Teensy 3.2 as we type. I've used these chips for all sorts of projects, so that was the path of least resistance. It was a squeeze fitting the Teensy into a case that was designed around a Trinket though.

-jim lee

jim_lee
 
Posts: 546
Joined: Thu May 24, 2012 8:24 pm

Re: Trinket MO, #include <EEPROM.h>?

by XRAD on Sun Aug 11, 2019 10:51 am

Jim_lee: Yes you are correct. Tried my code and no provision for EEPROM on the SAMD21, my error. However, several options:

https://forum.arduino.cc/index.php?topic=358648.0

https://github.com/cmaglie/FlashStorage

external storage small chip or EEPROM emulation.....

XRAD
 
Posts: 507
Joined: Sat Nov 19, 2016 3:28 pm

Please be positive and constructive with your questions and comments.