Skip to content

Commit 6b52463

Browse files
authored
Merge pull request #3 from arduino-libraries/persistence
Add support for new defaults register
2 parents 778a4e7 + db4c882 commit 6b52463

19 files changed

+240
-138
lines changed

examples/ChangeI2CAddress/ChangeI2CAddress.ino

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ void setup() {
3535
Serial.print("🔧 Changing device address to 0x");
3636
Serial.print(customI2CAddress, HEX);
3737
Serial.println("...");
38-
device.setDeviceAddress(customI2CAddress);
38+
39+
// Setting the second parameter to true makes the change persistent
40+
device.setDeviceAddress(customI2CAddress, true);
3941
checkConnection(device);
4042

41-
// Store the new address in flash
42-
device.storeSettingsInFlash();
43-
4443
Serial.println("🔄 Resetting device to check if change is persistent...");
4544
device.reset();
4645
delay(2000); // Wait for the device to reset

examples/OutdoorAirQuality/OutdoorAirQuality.ino

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ void setup() {
4040

4141
// Enable outdoor air quality sensor (disabled by default)
4242
// Please note that it may take some time for the sensor to deliver the first data
43-
outdoorAirQualitySensor.setMode(OutdoorAirQualitySensorMode::outdoorAirQuality);
43+
// Use setEnabled(true, true) make the change persistent
44+
outdoorAirQualitySensor.setEnabled(true);
4445
displaySensorData(outdoorAirQualitySensor);
4546

4647
// Optionally disable the sensor

examples/RGBLED/RGBLED.ino

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ void pulseLED(RGBLED &led) {
2121
}
2222

2323
void pulseColors(RGBLED &led) {
24-
// Brightness can also be set via 4th struct element
25-
led.setColor({255, 0, 0}, 255); // Red
24+
led.setColor({255, 0, 0}); // Red
2625
pulseLED(led);
2726

2827
// Color can be set via Color struct or 3 separate uint8_t values

examples/UARTRead/UARTRead.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
*
1313
* NiclaSenseEnv device;
1414
* device.begin();
15-
* device.setUARTCSVOutputEnabled(true);
16-
* device.storeSettingsInFlash() # Store the settings so they are not lost after a reset
15+
* The second parameter ensures that the settings are not lost after a reset
16+
* device.setUARTCSVOutputEnabled(true, true);
1717
*
1818
* Initial author: Sebastian Romero ([email protected])
1919
*

src/I2CDevice.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,25 @@ I2CDevice::I2CDevice(TwoWire& bus, uint8_t deviceAddress)
88
I2CDevice::I2CDevice(uint8_t deviceAddress)
99
: bus(Wire), i2cDeviceAddress(deviceAddress) {}
1010

11+
bool I2CDevice::persistRegister(RegisterInfo registerInfo){
12+
writeToRegister(DEFAULTS_REGISTER_INFO, registerInfo.address | (1 << 7));
13+
14+
// Read bit 7 to check if the write is complete. When the write is complete, bit 7 will be 0.
15+
// Try 10 times with increasing delay between each try
16+
for (int i = 0; i < 10; ++i) {
17+
uint8_t defaultsRegisterData = readFromRegister<uint8_t>(DEFAULTS_REGISTER_INFO);
18+
if (!(defaultsRegisterData & (1 << 7))) {
19+
return true;
20+
}
21+
// Even a value of 1 us seems to work, but we start with 100 us to be safe.
22+
Serial.println("⌛️ Waiting for flash write to complete...");
23+
// Exponential sleep duration
24+
delayMicroseconds(100 * (2 << i));
25+
}
26+
27+
return false;
28+
}
29+
1130
bool I2CDevice::connected() {
1231
bus.beginTransmission(i2cDeviceAddress);
1332
return bus.endTransmission() == 0;

src/I2CDevice.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ class I2CDevice {
141141
return bus.endTransmission() == 0;
142142
}
143143

144+
/**
145+
* @brief Makes the value of a given register persistent.
146+
* @param registerInfo The register to make persistent.
147+
* @return Whether or not the register value was successfully persisted.
148+
*/
149+
bool persistRegister(RegisterInfo registerInfo);
150+
144151
/**
145152
* @brief Reference to the I2C bus used by the device.
146153
*/

src/IndoorAirQualitySensor.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,23 @@ IndoorAirQualitySensorMode IndoorAirQualitySensor::mode() {
5252
return IndoorAirQualitySensorMode((data >> 1) & 7);
5353
}
5454

55-
void IndoorAirQualitySensor::setMode(IndoorAirQualitySensorMode sensorMode) {
55+
bool IndoorAirQualitySensor::setMode(IndoorAirQualitySensorMode sensorMode, bool persist) {
5656
uint8_t currentRegisterData = readFromRegister<uint8_t>(STATUS_REGISTER_INFO);
5757
uint8_t mode = static_cast<uint8_t>(sensorMode); // convert to numeric type
5858

5959
// Check if the existing value is already the same
6060
if ((currentRegisterData & (7 << 1)) == (mode << 1)) {
61-
return;
61+
return true;
6262
}
63-
writeToRegister(STATUS_REGISTER_INFO, (currentRegisterData & ~(7 << 1)) | (mode << 1));
63+
if(!writeToRegister(STATUS_REGISTER_INFO, (currentRegisterData & ~(7 << 1)) | (mode << 1))){
64+
return false;
65+
}
66+
67+
if(persist){
68+
return persistRegister(STATUS_REGISTER_INFO);
69+
}
70+
71+
return true;
6472
}
6573

6674
String IndoorAirQualitySensor::modeString() {
@@ -85,13 +93,11 @@ bool IndoorAirQualitySensor::enabled() {
8593
return mode() != IndoorAirQualitySensorMode::powerDown;
8694
}
8795

88-
void IndoorAirQualitySensor::setEnabled(bool isEnabled) {
96+
bool IndoorAirQualitySensor::setEnabled(bool isEnabled, bool persist) {
8997
if (isEnabled == enabled()) {
90-
return;
91-
}
92-
if (isEnabled) {
93-
setMode(IndoorAirQualitySensorMode::defaultMode);
94-
} else {
95-
setMode(IndoorAirQualitySensorMode::powerDown);
98+
return true;
9699
}
100+
101+
auto mode = isEnabled ? IndoorAirQualitySensorMode::indoorAirQuality : IndoorAirQualitySensorMode::powerDown;
102+
return setMode(mode, persist);
97103
}

src/IndoorAirQualitySensor.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ class IndoorAirQualitySensor : public I2CDevice {
9797

9898
/**
9999
* @brief Set the mode of the IndoorAirQualitySensor.
100-
* Call storeSettingsInFlash() on NiclaSenseEnv instance after changing the mode to make the change persistent.
101100
*
102101
* Note on cleaning mode:
103102
* The cleaning mode performs a thermal cleaning cycle of the MOx element. It can eliminate some light pollution
@@ -117,8 +116,11 @@ class IndoorAirQualitySensor : public I2CDevice {
117116
* For more accurate readings, use the default indoor air quality mode.
118117
*
119118
* @param sensorMode The mode to set. See the IndoorAirQualitySensorMode enum class for possible values.
119+
* @param persist If true, the change will be saved to flash memory.
120+
* When persist is true, the mode setting of OutdoorAirQualitySensor and TemperatureHumiditySensor will also be persisted.
121+
* @return True if the mode was set successfully, false otherwise.
120122
*/
121-
void setMode(IndoorAirQualitySensorMode sensorMode);
123+
bool setMode(IndoorAirQualitySensorMode sensorMode, bool persist = false);
122124

123125
/**
124126
* @brief Get the mode as a string.
@@ -136,10 +138,13 @@ class IndoorAirQualitySensor : public I2CDevice {
136138

137139
/**
138140
* @brief Set the sensor enabled or disabled.
139-
* Call storeSettingsInFlash() on NiclaSenseEnv instance after changing the enabled state to make the change persistent.
141+
* When the sensor is enabled after being disabled, the sensor will go back to the indoorAirQuality mode.
140142
* @param isEnabled True to enable the sensor, false to disable it.
143+
* @param persist If true, the change will be saved to flash memory.
144+
* When persist is true, the mode setting of IndoorAirQualitySensor and TemperatureHumiditySensor will also be persisted.
145+
* @return True if the the sensor was enabled successfully.
141146
*/
142-
void setEnabled(bool isEnabled);
147+
bool setEnabled(bool isEnabled, bool persist = false);
143148
};
144149

145150
#endif

src/NiclaSenseEnv.cpp

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void NiclaSenseEnv::end() {
7373
}
7474
}
7575

76-
bool NiclaSenseEnv::storeSettingsInFlash() {
76+
bool NiclaSenseEnv::persistSettings() {
7777
uint8_t controlRegisterData = readFromRegister<uint8_t>(CONTROL_REGISTER_INFO);
7878

7979
writeToRegister(CONTROL_REGISTER_INFO, controlRegisterData | (1 << 7));
@@ -137,7 +137,7 @@ bool NiclaSenseEnv::restoreFactorySettings() {
137137
boardControlRegisterData = readFromRegister<uint8_t>(CONTROL_REGISTER_INFO);
138138

139139
if ((boardControlRegisterData & (1 << 5)) == 0) {
140-
return storeSettingsInFlash();
140+
return persistSettings();
141141
}
142142
Serial.println("⌛️ Waiting for factory reset to complete...");
143143
// Exponential sleep duration
@@ -152,81 +152,122 @@ int NiclaSenseEnv::UARTBaudRate() {
152152
return baudRateMap[uartControlRegisterData];
153153
}
154154

155-
void NiclaSenseEnv::setUARTBaudRate(int baudRate) {
155+
bool NiclaSenseEnv::setUARTBaudRate(int baudRate, bool persist) {
156156
int baudRateIndex = baudRateNativeValue(baudRate);
157157
if (baudRateIndex == -1) {
158-
return; // Baud rate not found
158+
return false; // Baud rate not found
159159
}
160160

161161
uint8_t uartControlRegisterData = readFromRegister<uint8_t>(UART_CONTROL_REGISTER_INFO);
162162
if ((uartControlRegisterData & 7) == baudRateIndex) {
163-
return; // Value is already the same
163+
return true; // Value is already the same
164164
}
165-
writeToRegister(UART_CONTROL_REGISTER_INFO, (uartControlRegisterData & ~7) | baudRateIndex);
165+
if(!writeToRegister(UART_CONTROL_REGISTER_INFO, (uartControlRegisterData & ~7) | baudRateIndex)){
166+
return false;
167+
}
168+
169+
if (persist) {
170+
return persistRegister(UART_CONTROL_REGISTER_INFO);
171+
}
172+
173+
return true;
166174
}
167175

168176
bool NiclaSenseEnv::isUARTCSVOutputEnabled() {
169177
uint8_t boardControlRegisterData = readFromRegister<uint8_t>(CONTROL_REGISTER_INFO);
170178
return (boardControlRegisterData & (1 << 1)) != 0;
171179
}
172180

173-
void NiclaSenseEnv::setUARTCSVOutputEnabled(bool enabled) {
181+
bool NiclaSenseEnv::setUARTCSVOutputEnabled(bool enabled, bool persist) {
174182
uint8_t boardControlRegisterData = readFromRegister<uint8_t>(CONTROL_REGISTER_INFO);
175183
if ((boardControlRegisterData & 2) == static_cast<int>(enabled)) {
176-
return; // Value is already the same
184+
return true; // Value is already the same
185+
}
186+
if(!writeToRegister(CONTROL_REGISTER_INFO, (boardControlRegisterData & ~2) | (enabled << 1))){
187+
return false;
177188
}
178-
writeToRegister(CONTROL_REGISTER_INFO, (boardControlRegisterData & ~2) | (enabled << 1));
189+
190+
if (persist) {
191+
return persistRegister(CONTROL_REGISTER_INFO);
192+
}
193+
194+
return true;
179195
}
180196

181197
char NiclaSenseEnv::CSVDelimiter() {
182198
uint8_t csvDelimiterRegisterData = readFromRegister<uint8_t>(CSV_DELIMITER_REGISTER_INFO);
183199
return static_cast<char>(csvDelimiterRegisterData);
184200
}
185201

186-
void NiclaSenseEnv::setCSVDelimiter(char delimiter) {
202+
bool NiclaSenseEnv::setCSVDelimiter(char delimiter, bool persist) {
187203
char currentDelimiter = CSVDelimiter();
188204
if (currentDelimiter == delimiter) {
189-
return; // Value is already the same
205+
return true; // Value is already the same
190206
}
191207

192208
// Define prohibited delimiters
193209
const char prohibitedDelimiters[] = {'\r', '\n', '\\', '"', '\''};
194210

195211
for (auto prohibitedDelimiter : prohibitedDelimiters) {
196212
if (delimiter == prohibitedDelimiter) {
197-
return; // Delimiter is prohibited
213+
return false; // Delimiter is prohibited
198214
}
199215
}
200216

201217
// Use ASCII code of the delimiter character
202-
writeToRegister(CSV_DELIMITER_REGISTER_INFO, static_cast<uint8_t>(delimiter));
218+
if(!writeToRegister(CSV_DELIMITER_REGISTER_INFO, static_cast<uint8_t>(delimiter))){
219+
return false;
220+
}
221+
222+
if (persist) {
223+
return persistRegister(CSV_DELIMITER_REGISTER_INFO);
224+
}
225+
226+
return true;
203227
}
204228

205229
bool NiclaSenseEnv::isDebuggingEnabled() {
206230
uint8_t boardControlRegisterData = readFromRegister<uint8_t>(CONTROL_REGISTER_INFO);
207231
return (boardControlRegisterData & 1) != 0;
208232
}
209233

210-
void NiclaSenseEnv::setDebuggingEnabled(bool enabled) {
234+
bool NiclaSenseEnv::setDebuggingEnabled(bool enabled, bool persist) {
211235
uint8_t boardControlRegisterData = readFromRegister<uint8_t>(CONTROL_REGISTER_INFO);
212236
if ((boardControlRegisterData & 1) == static_cast<int>(enabled)) {
213-
return; // Value is already the same
237+
return true; // Value is already the same
238+
}
239+
if(!writeToRegister(CONTROL_REGISTER_INFO, (boardControlRegisterData & ~1) | enabled)){
240+
return false;
214241
}
215-
writeToRegister(CONTROL_REGISTER_INFO, (boardControlRegisterData & ~1) | enabled);
242+
243+
if(persist){
244+
return persistRegister(CONTROL_REGISTER_INFO);
245+
}
246+
247+
return true;
216248
}
217249

218-
void NiclaSenseEnv::setDeviceAddress(int address) {
250+
bool NiclaSenseEnv::setDeviceAddress(int address, bool persist) {
219251
if (address < 0 || address > 127) {
220-
return; // Invalid address
252+
return false; // Invalid address
221253
}
222254
uint8_t addressRegisterData = readFromRegister<uint8_t>(SLAVE_ADDRESS_REGISTER_INFO);
223255
// Check bits 0 - 6
224256
if ((addressRegisterData & 127) == address) {
225-
return; // Value is already the same
257+
return true; // Value is already the same
226258
}
227-
writeToRegister(SLAVE_ADDRESS_REGISTER_INFO, (addressRegisterData & ~127) | address);
259+
if(!writeToRegister(SLAVE_ADDRESS_REGISTER_INFO, (addressRegisterData & ~127) | address)){
260+
return false;
261+
}
262+
228263
delayMicroseconds(100); // Wait for the new address to take effect
229264
this->i2cDeviceAddress = address;
265+
266+
if (persist) {
267+
return persistRegister(SLAVE_ADDRESS_REGISTER_INFO);
268+
}
269+
270+
return true;
230271
}
231272

232273
// Function to get the index for a given baud rate

0 commit comments

Comments
 (0)