Skip to content

Commit 0acde14

Browse files
committed
v1.9.0: Add FlashStorage support for Arduino Nano 33 IoT
- Fix EEPROM.h error on Nano 33 IoT (SAMD21 boards don't have EEPROM) - Implement FlashStorage-based persistent settings for Nano 33 IoT - Support 10 values per type (int, float, bool, string) with 15-char keys - Update README with FlashStorage installation instructions - Maintain backward compatibility with ESP32 (Preferences) and UNO R4 (EEPROM) - Add clearMemory() support for FlashStorage
1 parent 31745c6 commit 0acde14

File tree

3 files changed

+175
-2
lines changed

3 files changed

+175
-2
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ WebGUI provides a simplified method for creating webpages that can interact with
7575
3. Search for "WebGUI"
7676
4. Click **Install**
7777

78+
### Additional Dependencies
79+
80+
#### For Arduino Nano 33 IoT Users
81+
The Nano 33 IoT requires the **FlashStorage** library for persistent settings:
82+
1. Go to **Sketch****Include Library****Manage Libraries**
83+
2. Search for "FlashStorage"
84+
3. Install **FlashStorage** by cmaglie
85+
86+
> **Note:** The FlashStorage library is only required if you're using the `saveSetting()` and `loadSetting()` functions on the Nano 33 IoT. Basic WebGUI functionality works without it.
87+
7888
### Manual Installation
7989
1. Download the latest release from [GitHub](https://github.com/npuckett/WebGUI)
8090
2. Extract the ZIP file

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=WebGUI
2-
version=1.8.5
2+
version=1.9.0
33
author=Nick Puckett
44
maintainer=WebGUI Library Contributors
55
sentence=Simple web-based GUI library for Arduino with WiFi support

src/WebGUI.cpp

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,24 @@
77
#include "WebGUI.h"
88

99
// Platform-specific includes for settings
10-
#if defined(ARDUINO_UNOWIFIR4) || defined(ARDUINO_SAMD_NANO_33_IOT)
10+
#if defined(ARDUINO_UNOWIFIR4)
1111
#include <EEPROM.h>
12+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
13+
#include <FlashStorage.h>
14+
15+
// FlashStorage structures for Nano 33 IoT
16+
// We'll create a simple key-value storage system
17+
typedef struct {
18+
bool valid;
19+
int intValues[10];
20+
float floatValues[10];
21+
bool boolValues[10];
22+
char stringValues[10][16]; // 10 strings, max 15 chars each
23+
char keys[40][16]; // 40 keys total (10 per type), max 15 chars each
24+
} FlashSettings;
25+
26+
FlashStorage(flash_settings, FlashSettings);
27+
1228
#elif defined(ESP32)
1329
#include <Preferences.h>
1430
#endif
@@ -1193,6 +1209,9 @@ void WebGUI::initSettings() {
11931209
preferences = new Preferences();
11941210
static_cast<Preferences*>(preferences)->begin("webgui", false);
11951211
}
1212+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1213+
// FlashStorage doesn't need initialization
1214+
// Data structures are managed through FlashStorage library
11961215
#else
11971216
// Initialize EEPROM for Arduino boards
11981217
EEPROM.begin();
@@ -1206,6 +1225,31 @@ void WebGUI::saveSetting(const char* key, int value) {
12061225

12071226
#if defined(ESP32)
12081227
static_cast<Preferences*>(preferences)->putInt(key, value);
1228+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1229+
FlashSettings settings = flash_settings.read();
1230+
if (!settings.valid) {
1231+
memset(&settings, 0, sizeof(settings));
1232+
settings.valid = true;
1233+
}
1234+
1235+
// Find existing key or empty slot
1236+
int slot = -1;
1237+
for (int i = 0; i < 10; i++) {
1238+
if (strcmp(settings.keys[i], key) == 0) {
1239+
slot = i;
1240+
break;
1241+
}
1242+
if (settings.keys[i][0] == '\0' && slot == -1) {
1243+
slot = i;
1244+
}
1245+
}
1246+
1247+
if (slot != -1) {
1248+
strncpy(settings.keys[slot], key, 15);
1249+
settings.keys[slot][15] = '\0';
1250+
settings.intValues[slot] = value;
1251+
flash_settings.write(settings);
1252+
}
12091253
#else
12101254
// Calculate hash-based address with proper spacing for int (4 bytes)
12111255
uint16_t hash = 0;
@@ -1222,6 +1266,30 @@ void WebGUI::saveSetting(const char* key, float value) {
12221266

12231267
#if defined(ESP32)
12241268
static_cast<Preferences*>(preferences)->putFloat(key, value);
1269+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1270+
FlashSettings settings = flash_settings.read();
1271+
if (!settings.valid) {
1272+
memset(&settings, 0, sizeof(settings));
1273+
settings.valid = true;
1274+
}
1275+
1276+
int slot = -1;
1277+
for (int i = 0; i < 10; i++) {
1278+
if (strcmp(settings.keys[10 + i], key) == 0) {
1279+
slot = i;
1280+
break;
1281+
}
1282+
if (settings.keys[10 + i][0] == '\0' && slot == -1) {
1283+
slot = i;
1284+
}
1285+
}
1286+
1287+
if (slot != -1) {
1288+
strncpy(settings.keys[10 + slot], key, 15);
1289+
settings.keys[10 + slot][15] = '\0';
1290+
settings.floatValues[slot] = value;
1291+
flash_settings.write(settings);
1292+
}
12251293
#else
12261294
uint16_t hash = 0;
12271295
for (int i = 0; key[i] != '\0'; i++) {
@@ -1237,6 +1305,30 @@ void WebGUI::saveSetting(const char* key, bool value) {
12371305

12381306
#if defined(ESP32)
12391307
static_cast<Preferences*>(preferences)->putBool(key, value);
1308+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1309+
FlashSettings settings = flash_settings.read();
1310+
if (!settings.valid) {
1311+
memset(&settings, 0, sizeof(settings));
1312+
settings.valid = true;
1313+
}
1314+
1315+
int slot = -1;
1316+
for (int i = 0; i < 10; i++) {
1317+
if (strcmp(settings.keys[20 + i], key) == 0) {
1318+
slot = i;
1319+
break;
1320+
}
1321+
if (settings.keys[20 + i][0] == '\0' && slot == -1) {
1322+
slot = i;
1323+
}
1324+
}
1325+
1326+
if (slot != -1) {
1327+
strncpy(settings.keys[20 + slot], key, 15);
1328+
settings.keys[20 + slot][15] = '\0';
1329+
settings.boolValues[slot] = value;
1330+
flash_settings.write(settings);
1331+
}
12401332
#else
12411333
uint16_t addr = 16;
12421334
for (int i = 0; key[i] != '\0'; i++) {
@@ -1252,6 +1344,31 @@ void WebGUI::saveSetting(const char* key, const char* value) {
12521344

12531345
#if defined(ESP32)
12541346
static_cast<Preferences*>(preferences)->putString(key, value);
1347+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1348+
FlashSettings settings = flash_settings.read();
1349+
if (!settings.valid) {
1350+
memset(&settings, 0, sizeof(settings));
1351+
settings.valid = true;
1352+
}
1353+
1354+
int slot = -1;
1355+
for (int i = 0; i < 10; i++) {
1356+
if (strcmp(settings.keys[30 + i], key) == 0) {
1357+
slot = i;
1358+
break;
1359+
}
1360+
if (settings.keys[30 + i][0] == '\0' && slot == -1) {
1361+
slot = i;
1362+
}
1363+
}
1364+
1365+
if (slot != -1) {
1366+
strncpy(settings.keys[30 + slot], key, 15);
1367+
settings.keys[30 + slot][15] = '\0';
1368+
strncpy(settings.stringValues[slot], value, 15);
1369+
settings.stringValues[slot][15] = '\0';
1370+
flash_settings.write(settings);
1371+
}
12551372
#else
12561373
uint16_t hash = 0;
12571374
for (int i = 0; key[i] != '\0'; i++) {
@@ -1272,6 +1389,16 @@ int WebGUI::loadIntSetting(const char* key) {
12721389

12731390
#if defined(ESP32)
12741391
return static_cast<Preferences*>(preferences)->getInt(key, 0);
1392+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1393+
FlashSettings settings = flash_settings.read();
1394+
if (!settings.valid) return 0;
1395+
1396+
for (int i = 0; i < 10; i++) {
1397+
if (strcmp(settings.keys[i], key) == 0) {
1398+
return settings.intValues[i];
1399+
}
1400+
}
1401+
return 0;
12751402
#else
12761403
uint16_t hash = 0;
12771404
for (int i = 0; key[i] != '\0'; i++) {
@@ -1289,6 +1416,16 @@ float WebGUI::loadFloatSetting(const char* key) {
12891416

12901417
#if defined(ESP32)
12911418
return static_cast<Preferences*>(preferences)->getFloat(key, 0.0);
1419+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1420+
FlashSettings settings = flash_settings.read();
1421+
if (!settings.valid) return 0.0;
1422+
1423+
for (int i = 0; i < 10; i++) {
1424+
if (strcmp(settings.keys[10 + i], key) == 0) {
1425+
return settings.floatValues[i];
1426+
}
1427+
}
1428+
return 0.0;
12921429
#else
12931430
uint16_t hash = 0;
12941431
for (int i = 0; key[i] != '\0'; i++) {
@@ -1306,6 +1443,16 @@ bool WebGUI::loadBoolSetting(const char* key) {
13061443

13071444
#if defined(ESP32)
13081445
return static_cast<Preferences*>(preferences)->getBool(key, false);
1446+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1447+
FlashSettings settings = flash_settings.read();
1448+
if (!settings.valid) return false;
1449+
1450+
for (int i = 0; i < 10; i++) {
1451+
if (strcmp(settings.keys[20 + i], key) == 0) {
1452+
return settings.boolValues[i];
1453+
}
1454+
}
1455+
return false;
13091456
#else
13101457
uint16_t hash = 0;
13111458
for (int i = 0; key[i] != '\0'; i++) {
@@ -1323,6 +1470,16 @@ String WebGUI::loadStringSetting(const char* key) {
13231470

13241471
#if defined(ESP32)
13251472
return static_cast<Preferences*>(preferences)->getString(key, "");
1473+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1474+
FlashSettings settings = flash_settings.read();
1475+
if (!settings.valid) return "";
1476+
1477+
for (int i = 0; i < 10; i++) {
1478+
if (strcmp(settings.keys[30 + i], key) == 0) {
1479+
return String(settings.stringValues[i]);
1480+
}
1481+
}
1482+
return "";
13261483
#else
13271484
uint16_t hash = 0;
13281485
for (int i = 0; key[i] != '\0'; i++) {
@@ -1348,6 +1505,12 @@ void WebGUI::clearMemory() {
13481505
static_cast<Preferences*>(preferences)->clear();
13491506
Serial.println("✅ ESP32 Preferences cleared");
13501507
}
1508+
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
1509+
// For Nano 33 IoT - Clear FlashStorage
1510+
FlashSettings settings;
1511+
memset(&settings, 0, sizeof(settings));
1512+
flash_settings.write(settings);
1513+
Serial.println("✅ Nano 33 IoT Flash Storage cleared");
13511514
#else
13521515
// For Arduino UNO R4 WiFi and other EEPROM-based systems
13531516
// Clear first 1024 bytes of EEPROM (more than enough for most applications)

0 commit comments

Comments
 (0)