#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <NewPing.h>
#include <SoftwareSerial.h>
#include <Keypad.h>
#include "I2CKeyPad.h"
#define SIMULATION true // IMPRTANT! COMMENT FOR ACTUAL
#ifdef SIMULATION
bool simulation = true;
#else
bool simulation = false;
#endif
#ifdef SIMULATION
// >>>> ACTUAL >>>>
#define COIN_SIG_PIN 2
#define COIN_INH_PIN 3
#define PARCEL_SENS_ECHO_PIN 4
#define PARCEL_SENS_TRIG_PIN 5
#define PARCEL_LOCK_PIN 8
#define DRAWER_LOCK_PIN 9
#define PARCEL_LOCK_SENS_PIN 10
#define DRAWER_LOCK_SENS_PIN 11
#define GSM_RX_PIN 12
#define GSM_TX_PIN 13
// <<<< ACTUAL <<<<
#else
// >>>> SIMULATION >>>>
#define COIN_SIG_PIN 2
#define COIN_INH_PIN 3
#define PARCEL_SENS_ECHO_PIN 8
#define PARCEL_SENS_TRIG_PIN 9
#define PARCEL_LOCK_PIN 10
#define DRAWER_LOCK_PIN 11
#define PARCEL_LOCK_SENS_PIN 12
#define DRAWER_LOCK_SENS_PIN 13
#define GSM_RX_PIN 99
#define GSM_TX_PIN 99
// <<<< SIMULATION <<<<
#endif
SoftwareSerial sim(GSM_TX_PIN, GSM_RX_PIN);
// >>>> SIMULATION >>>>
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { A3, A2, A1, A0 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 7, 6, 5, 4 }; // Pins connected to R1, R2, R3, R4
Keypad keyPad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// <<<< SIMULATION <<<<
// >>>> ACTUAL >>>>
const uint8_t KEYPAD_ADDRESS = 0x20;
char keymap[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
I2CKeyPad keyPadI2C(KEYPAD_ADDRESS);
// <<<< ACTUAL >>>>
LiquidCrystal_I2C lcd(0x27, 16, 2);
NewPing sonar(PARCEL_SENS_TRIG_PIN, PARCEL_SENS_ECHO_PIN, 200);
// Set variables
int SONAR_NORMAL_DISTANCE = 25;
// EEPROM address
const int eeprom_addr_first = 0;
const int eeprom_addr_change = 10;
const int eeprom_addr_pin = 15;
const int eeprom_addr_state = 50;
const int eeprom_addr_phone = 100;
// GSM Variables
int _timeout;
String _buffer;
// Stored Variables
bool isFirstLaunch = true;
String phone = "+639999999999";
String pin = "0000";
String state = "empty";
int change = 0;
// Input Variables
String otpInput = "";
String pinInput = "";
String phoneInput = "";
// Generated Variables
String otp = "";
// State Variables
int buttonLastState = HIGH;
int credit = 0;
// Coin Slot Variables
unsigned long lastAction = 0; //When last action was made
unsigned long lastPulse = 0; //When last pulse was send
int pulseCount = 0; //How many pulses we got
bool coinEnabled = false;
const int pulseTimeout = 300;
const int actionTimeout = 5000;
unsigned long tempAction;
unsigned long tempPulse;
void coinInterrupt() {
lastAction = millis();
lastPulse = millis();
pulseCount++;
}
void setup() {
pinMode(PARCEL_LOCK_PIN, OUTPUT);
pinMode(DRAWER_LOCK_PIN, OUTPUT);
pinMode(PARCEL_SENS_TRIG_PIN, OUTPUT);
pinMode(PARCEL_SENS_ECHO_PIN, INPUT);
pinMode(PARCEL_LOCK_SENS_PIN, INPUT);
pinMode(DRAWER_LOCK_SENS_PIN, INPUT);
pinMode(COIN_INH_PIN, OUTPUT);
pinMode(COIN_SIG_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(COIN_SIG_PIN), coinInterrupt, RISING);
digitalWrite(COIN_INH_PIN, LOW);
digitalWrite(PARCEL_LOCK_PIN, HIGH);
digitalWrite(DRAWER_LOCK_PIN, HIGH);
Serial.begin(115200);
Serial.println(F("[SYS] BEGIN"));
Serial.print(F("[SYS] Environment: "));
if (simulation) Serial.println(F("Simulation"));
else Serial.println(F("Hardware"));
Serial.println(F("[EEPROM] Checking..."));
Serial.print(F("[EEPROM] Length: "));
Serial.println(EEPROM.length());
Serial.print(F("[EEPROM] First launch: "));
Serial.println(EEPROM.read(eeprom_addr_first));
if (EEPROM.read(eeprom_addr_first) == 255) {
Serial.println(F("[EEPROM] System first launch. Setting inital values."));
EEPROM.put(eeprom_addr_first, isFirstLaunch);
EEPROM.put(eeprom_addr_change, change);
writeStringToEEPROM(eeprom_addr_pin, pin);
writeStringToEEPROM(eeprom_addr_state, state);
writeStringToEEPROM(eeprom_addr_phone, phone);
Serial.println(F("[EEPROM] Inital values set. Proceeding..."));
}
delay(500);
Serial.println(F("[EEPROM] Loading values..."));
EEPROM.get(eeprom_addr_change, change);
readStringFromEEPROM(eeprom_addr_pin, &pin);
readStringFromEEPROM(eeprom_addr_state, &state);
readStringFromEEPROM(eeprom_addr_phone, &phone);
Serial.print(F("[EEPROM] Pin: "));
Serial.println(pin);
Serial.print(F("[EEPROM] Phone: "));
Serial.println(phone);
Serial.print(F("[EEPROM] State: "));
Serial.println(state);
Serial.print(F("[EEPROM] Change: ") );
Serial.println(String(change));
randomSeed(analogRead(A5));
#ifndef SIMULATION
// >>>> ACTUAL >>>>
if (keyPadI2C.begin() == false) {
Serial.println("\nERROR: cannot communicate to keypad.\nPlease reboot.\n");
while (1)
;
} else {
Serial.println("Keypad Loaded.");
}
keyPadI2C.loadKeyMap(keymap);
Serial.println("[GSM] Loading...");
delay(7000);
sim.begin(9600);
sim.println("AT");
Serial.println("[GSM] Loaded.");
// <<<< ACTUAL <<<<
#endif
lcd.init();
lcd.backlight();
delay(1000);
}
int mode = 0;
const int menuSize = 4;
String menuStringList[menuSize] = {
"Deliver Parcel",
"Receive Parcel",
"Set Phone Number",
"Set Pin Code"
};
int menuCursor = 0;
String menuString = menuStringList[0];
unsigned long previousMillis = 0;
unsigned int interval = 500;
int iMenu = 0;
char key;
void loop() {
if (simulation) char key = keyPad.getKey();
else char key = keyPadI2C.getChar();
switch (mode) {
case 0:
lcd.setCursor(0, 0);
lcd.print(F("Parcel Depository"));
if (millis() - previousMillis >= interval) {
previousMillis = millis();
if (iMenu < menuString.length() - 3) {
lcd.setCursor(0, 1);
lcd.print("< >");
lcd.setCursor(2, 1);
String displayText = menuString.substring(iMenu, iMenu + 12);
lcd.print(displayText);
iMenu++;
} else {
iMenu = 0;
}
}
Serial.println(key);
if (key != NO_KEY) {
switch (key) {
lcd.clear();
case '*':
if (menuCursor == 0) {
menuCursor = menuSize - 1;
} else {
menuCursor--;
}
iMenu = 0;
menuString = menuStringList[menuCursor];
break;
case '#':
if (menuCursor == menuSize - 1) {
menuCursor = 0;
} else {
menuCursor++;
}
iMenu = 0;
menuString = menuStringList[menuCursor];
break;
case 'D':
switch (menuCursor) {
case 0:
showDeliverParcel();
break;
case 1:
showReceiveParcel();
break;
case 2:
showSetPhone();
break;
case 3:
showSetPin();
break;
}
break;
}
}
break;
}
delay(10); // REMOVE for actual
}
int showReceiveParcel() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("STATUS: " + state);
lcd.setCursor(0, 1);
lcd.print("Press [D]");
bool loopConfirm = true;
while (loopConfirm) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'D':
loopConfirm = false;
if (state == "pending") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Receive Pending");
lcd.setCursor(0, 1);
lcd.print("Cancel? [D]");
bool loopReceive = true;
while (loopReceive) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'D':
loopReceive = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Get Payment");
digitalWrite(DRAWER_LOCK_PIN, LOW);
bool drawerOpen = false;
while (!drawerOpen) {
if (digitalRead(PARCEL_LOCK_SENS_PIN) == LOW) {
drawerOpen = true;
lcd.setCursor(0, 1);
lcd.print("Drawer Opened");
}
}
delay(1000);
while (drawerOpen) {
if (digitalRead(PARCEL_LOCK_SENS_PIN) == HIGH) {
drawerOpen = false;
lcd.setCursor(0, 1);
lcd.print("Drawer Closed");
}
}
delay(1000);
lcd.print("Locking...");
digitalWrite(DRAWER_LOCK_PIN, HIGH);
saveState("empty");
break;
case 'A':
loopReceive = false;
return 0;
break;
}
}
}
}
if (state == "received") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Parcel Received");
bool detect = true;
while (detect) {
int distance;
if (distance > 25) {
lcd.setCursor(0, 1);
lcd.print("Parcel Retrieved.");
delay(3000);
saveState("empty");
}
}
}
break;
case 'A':
loopConfirm = false;
return 0;
break;
}
}
}
return 0;
}
int showDeliverParcel() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Press [D] to");
lcd.setCursor(0, 1);
lcd.print("send OTP code.");
bool loopConfirm = true;
while (loopConfirm) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'D':
sendOTP();
showSMSSentStatus();
loopConfirm = false;
break;
case 'A':
loopConfirm = false;
return 0;
break;
}
}
}
return 0;
}
int showSetPhone() {
lcd.clear();
lcd.setCursor(0, 0);
bool loopPin = true;
bool authorized = authorize();
if (!authorized) {
return 0;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F(" Set Phone No."));
lcd.setCursor(0, 1);
lcd.print(F(" ------------- "));
int phoneCursor = 1;
if (phone) {
phoneInput = phone;
lcd.setCursor(phoneCursor, 1);
lcd.print(phoneInput);
phoneCursor += phoneInput.length();
}
lcd.setCursor(phoneCursor, 1);
lcd.blink();
bool loop = true;
while (loop) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'A':
lcd.noBlink();
phoneInput = "";
return 0;
break;
case 'B':
break;
case 'C':
if (phoneInput.length() > 3) {
lcd.setCursor(phoneCursor - 1, 1);
lcd.print("-");
phoneCursor -= 1;
lcd.setCursor(phoneCursor, 1);
phoneInput = phoneInput.substring(0, phoneInput.length() - 1);
lcd.blink();
}
break;
case 'D':
if (phoneInput.length() == 13) {
loop = false;
phone = phoneInput;
savePhone(phone);
phoneInput = "";
lcd.noBlink();
return 0;
}
break;
case '*':
break;
case '#':
break;
default:
if (phoneInput.length() < 13) {
phoneInput += key;
lcd.setCursor(phoneCursor, 1);
phoneCursor += 1;
lcd.print(key);
}
break;
}
}
if (phone.length() == 13) {
lcd.noBlink();
}
}
lcd.noBlink();
return 0;
}
int showSetPin() {
lcd.clear();
lcd.setCursor(0, 0);
bool loopPin = true;
bool authorized = authorize();
if (!authorized) {
return 0;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F(" Set Pin Code"));
lcd.setCursor(0, 1);
lcd.print(F(" ---- "));
int pinCursor = 6;
if (pin) {
pinInput = pin;
lcd.setCursor(pinCursor, 1);
lcd.print(pinInput);
pinCursor += pinInput.length();
}
lcd.setCursor(pinCursor, 1);
lcd.blink();
bool loop = true;
while (loop) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'A':
lcd.noBlink();
return 0;
break;
case 'B':
break;
case 'C':
if (pinInput.length() > 0) {
lcd.setCursor(pinCursor - 1, 1);
lcd.print("-");
pinCursor -= 1;
lcd.setCursor(pinCursor, 1);
pinInput = pinInput.substring(0, pinInput.length() - 1);
lcd.blink();
}
break;
case 'D':
lcd.noBlink();
if (pinInput.length() == 4) {
loop = false;
pin = pinInput;
savePin(pin);
return 0;
} else {
return 0;
}
break;
case '*':
break;
case '#':
break;
default:
if (pinInput.length() < 4) {
pinInput += key;
lcd.setCursor(pinCursor, 1);
pinCursor += 1;
lcd.print(key);
}
break;
}
}
if (phone.length() == 11) {
lcd.noBlink();
}
}
return 0;
}
bool authorize() {
pinInput = "";
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Enter PIN");
lcd.setCursor(0, 1);
lcd.print(F(" ---- "));
int pinCursor = 6;
lcd.setCursor(pinCursor, 1);
lcd.blink();
bool loop = true;
while (loop) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'A':
lcd.noBlink();
return false;
case 'B':
break;
case 'C':
if (pinInput.length() > 0) {
lcd.setCursor(pinCursor - 1, 1);
lcd.print("-");
pinCursor -= 1;
lcd.setCursor(pinCursor, 1);
pinInput = pinInput.substring(0, pinInput.length() - 1);
lcd.blink();
}
break;
case 'D':
lcd.noBlink();
if (pin == pinInput) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Authorized");
lcd.setCursor(0, 1);
lcd.print(" Correct PIN");
delay(2000);
pinInput = "";
return true;
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Access Denied");
lcd.setCursor(0, 1);
lcd.print(" Invalid PIN");
delay(2000);
lcd.clear();
pinInput = "";
return false;
}
case '*': break;
case '#': break;
default:
if (pinInput.length() < 4) {
pinInput += key;
lcd.setCursor(pinCursor, 1);
pinCursor += 1;
lcd.print(key);
}
break;
}
}
if (pinInput.length() == 4) {
lcd.noBlink();
}
}
}
int showSMSSentStatus() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" SUCCESS");
lcd.setCursor(0, 1);
lcd.print(" OTP Sent");
delay(2000);
lcd.clear();
String instructionTop = F("Ask receiver for the code.");
String instructionBottom = F("Press [D] to Proceed.");
unsigned long previousMillis = 0;
int i = 0;
lcd.print(F("Press [D] to Proceed."));
delay(1000);
bool loop = true;
while (loop) {
if (millis() - previousMillis >= 500) {
previousMillis = millis();
if (i < instructionTop.length() - 15) {
lcd.setCursor(0, 0);
String displayTextTop = instructionTop.substring(i, i + 16);
lcd.print(displayTextTop);
lcd.setCursor(0, 1);
String displayTextBot = instructionBottom.substring(i, i + 16);
lcd.print(displayTextBot);
i++;
} else {
i = 0;
}
}
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'A':
lcd.noBlink();
return 0;
break;
case 'B':
break;
case 'C':
break;
case 'D':
showOTPInputScreen();
break;
case '*':
break;
case '#':
break;
}
}
}
return 0;
}
int showOTPInputScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F(" INPUT OTP CODE"));
lcd.setCursor(0, 1);
lcd.print(F(" - - - - - -"));
int pinCursor = 2;
lcd.setCursor(pinCursor, 1);
lcd.blink();
bool loop = true;
while (loop) {
char key = keyPad.getKey();
if (key != NO_KEY) {
switch (key) {
case 'A':
lcd.noBlink();
return 0;
break;
case 'B':
break;
case 'C':
break;
case 'D':
break;
case '*':
break;
case '#':
break;
}
showParcelInputScreen();
// if (otpInput.length() < 6) {
// otpInput += key;
// lcd.print(key);
// lcd.print(" ");
// if (otpInput.length() == 6 && otpInput == otp) {
// showCorrectCodeScreen();
// } else if (otpInput.length() == 6 && otpInput != otp) {
// showIncorrectCodeScreen();
// }
// }
}
}
return 0;
}
int showCorrectCodeScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Code Correct");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("Openning...");
digitalWrite(PARCEL_LOCK_PIN, LOW); // open
delay(1000);
lcd.setCursor(0, 1);
lcd.print("Box Opened!");
delay(2000);
showParcelInputScreen();
return 0;
}
int showIncorrectCodeScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F(" Incorrect Code"));
lcd.setCursor(0, 1);
lcd.print(F(" Try Again"));
delay(2000);
otpInput = "";
showOTPInputScreen();
return 0;
}
unsigned int detectElapsed = 0;
unsigned long elapsedMillis = 0;
int showParcelInputScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Waiting for ");
lcd.setCursor(0, 1);
lcd.print("parcel...");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
bool parcelWaiting = true;
while (parcelWaiting) {
unsigned int uS = sonar.ping();
int distance = uS / US_ROUNDTRIP_CM;
Serial.println(distance);
if (distance < 25) {
if (millis() - elapsedMillis > 1000) {
elapsedMillis = millis();
detectElapsed += 1000;
if (detectElapsed == 3000) {
parcelWaiting = false;
}
}
}
}
lcd.print("Parcel Detected");
lcd.setCursor(0, 1);
delay(1000);
lcd.print("Please close the box.");
bool boxCloseWaiting = true;
if (boxCloseWaiting) {
if (digitalRead(PARCEL_LOCK_SENS_PIN) == HIGH) {
boxCloseWaiting = false;
}
}
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Box closed, locking...");
digitalWrite(PARCEL_LOCK_PIN, HIGH);
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Box Locked.");
lcd.setCursor( 0, 1);
lcd.print("Releasing Payment...");
digitalWrite(DRAWER_LOCK_PIN, HIGH);
delay(1000);
// STAGE: OPEN DRAWER
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Please claim the payment");
lcd.setCursor(0, 1);
lcd.print("Then close the drawer.");
bool drawerOpen = false;
while (!drawerOpen) {
if (digitalRead(PARCEL_LOCK_SENS_PIN) == LOW) {
drawerOpen = true;
delay(2000);
}
}
while (drawerOpen) {
if (digitalRead(PARCEL_LOCK_SENS_PIN) == HIGH) {
drawerOpen = false;
}
}
// STAGE: CLOSE DRAWER
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Drawer Closed.");
lcd.setCursor(0, 1);
lcd.print("Receiving Change...");
delay(2000);
// STAGE: CHANGE
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Insert change.");
bool receiveChange = true;
coinEnabled = true;
while (receiveChange) {
lcd.setCursor(0, 1);
lcd.print("Change: 0/35");
tempAction = lastAction;
tempPulse = lastPulse;
digitalWrite(COIN_INH_PIN, coinEnabled);
if (pulseCount > 0) coinEnabled = false;
else coinEnabled = true;
if (millis() - lastPulse >= pulseTimeout && pulseCount > 0) {
if (tempAction != lastAction || tempPulse != lastPulse) return;
Serial.print("Coin: ");
switch (pulseCount) {
case 20:
Serial.println("20 Pesos");
credit += 20;
break;
case 10:
Serial.println("10 Pesos");
credit += 10;
break;
case 5:
Serial.println("5 Pesos");
credit += 5;
break;
case 1:
Serial.println("1 Peso");
credit += 1;
break;
}
pulseCount = 0;
}
if (credit >= change) {
receiveChange = false;
coinEnabled = false;
digitalWrite(COIN_INH_PIN, coinEnabled);
}
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Parcel Received.");
lcd.setCursor(0, 1);
lcd.print("Thank you!");
sendNotification();
delay(2000);
saveState("received");
return 0;
}
void showInputChange() {}
String generateRandomPin() {
static const char numChars[] = "0123456789";
String tmp_Pin;
tmp_Pin.reserve(6);
for (int i = 0; i < 6; ++i) {
tmp_Pin += numChars[random(0, 100) % (sizeof(numChars) - 1)];
}
return tmp_Pin;
}
void sendOTP() {
otp = generateRandomPin();
Serial.println(otp);
sendSMS("ParcelDepo OTP: " + otp);
}
void sendNotification() {
sendSMS("ParcelDepo: Parcel Received!");
}
void sendSMS(String message) {
sim.println("AT+CMGF=1"); // Sets the GSM Module in Text Mode
delay(200);
Serial.println(F("[GSM] Set SMS Number"));
sim.println("AT+CMGS=\"" + phone + "\"\r"); // Mobile phone number to send message
delay(200);
sim.println(message);
delay(100);
sim.println((char)26); // ASCII code of CTRL+Z
delay(200);
// >>>> ACTUAL >>>>
// _buffer = _readSerial();
// <<<< ACTUAL <<<<
}
String _readSerial() {
_timeout = 0;
while (!sim.available() && _timeout < 12000) {
delay(13);
_timeout++;
}
if (sim.available()) {
return sim.readString();
}
}
void saveChange(int change) {
EEPROM.put(eeprom_addr_change, change);
delay(100);
Serial.print(F("[SYS] Change now: "));
Serial.println(String(change));
}
void saveState(String state) {
writeStringToEEPROM(eeprom_addr_state, state);
delay(100);
Serial.print(F("[SYS] State now: "));
Serial.println(state);
}
void savePhone(String phone) {
writeStringToEEPROM(eeprom_addr_phone, phone);
delay(100);
Serial.print(F("[SYS] Phone now: "));
Serial.println(phone);
}
void savePin(String pin) {
writeStringToEEPROM(eeprom_addr_pin, pin);
delay(100);
Serial.print(F("[SYS] Pin now: "));
Serial.println(pin);
}
int writeStringToEEPROM(int addrOffset, const String &strToWrite) {
byte len = strToWrite.length();
EEPROM.write(addrOffset, len);
for (int i = 0; i < len; i++) {
EEPROM.write(addrOffset + 1 + i, strToWrite[i]);
}
return addrOffset + 1 + len;
}
int readStringFromEEPROM(int addrOffset, String *strToRead) {
int newStrLen = EEPROM.read(addrOffset);
char data[newStrLen + 1];
for (int i = 0; i < newStrLen; i++) {
data[i] = EEPROM.read(addrOffset + 1 + i);
}
data[newStrLen] = '\0';
*strToRead = String(data);
return addrOffset + 1 + newStrLen;
}