Skip to content
This repository was archived by the owner on Jun 14, 2023. It is now read-only.

Commit 92b300d

Browse files
committed
Fix SVM40-Uart driver
- Add convenience methods - Add some more explanations how to setup the sensor with arduino in readme
1 parent 08bf7d1 commit 92b300d

File tree

4 files changed

+146
-40
lines changed

4 files changed

+146
-40
lines changed

README.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ Note: Installation via the Arduino Library Manager is coming soon.
2828
# Quick Start
2929

3030
1. Connect the SVM40 Sensor to one of your Arduino board's
31-
UART buses. We recommend using `Serial1`. Check the pinout of your Arduino
32-
board to find the correct pins. The pinout of the SVM40
31+
UART buses. You will need an Arduino board that has more than one UART since one instance is used for programming and tracing. We recommend using `Serial1`. Check the pinout of your Arduino board to find the correct pins. The pinout of the SVM40
3332
Sensor board can be found in the data sheet.
3433

35-
* **VDD** of the SEK-SVM40 to the **3.3V** of your Arduino board (5V works as well)
36-
* **GND** of the SEK-SVM40 to the **GND** of your Arduino board
37-
* **RX** of the SEK-SVM40 to the **UART1-TX** of your Arduino board
38-
* **TX** of the SEK-SVM40 to the **UART1-RX** of your Arduino board
34+
* **VDD** (pin 1) of the SEK-SVM40 to the **3.3V** of your Arduino board (5V works as well)
35+
* **GND** (pin 2) of the SEK-SVM40 to the **GND** of your Arduino board
36+
* **RX** (pin 3, host TX) of the SEK-SVM40 to the **UART1-TX** of your Arduino board
37+
* **TX** (pin 4, host RX) of the SEK-SVM40 to the **UART1-RX** of your Arduino board
38+
39+
For use with UART **SEL** (pin 5 of SEK-SVM40 connector) must be floating!
3940

4041
2. Open the `exampleUsage` sample project within the Arduino IDE
4142

examples/exampleUsage/exampleUsage.ino

+34-16
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void setup() {
7171
errorToString(error, errorMessage, 256);
7272
Serial.println(errorMessage);
7373
} else {
74-
Serial.print("SerialNumber:");
74+
Serial.print("SerialNumber: ");
7575
Serial.println((char*)serialNumber);
7676
}
7777

@@ -83,7 +83,7 @@ void setup() {
8383
errorToString(error, errorMessage, 256);
8484
Serial.println(errorMessage);
8585
} else {
86-
Serial.print("ProductType:");
86+
Serial.print("ProductType: ");
8787
Serial.println((char*)productType);
8888
}
8989

@@ -95,7 +95,7 @@ void setup() {
9595
errorToString(error, errorMessage, 256);
9696
Serial.println(errorMessage);
9797
} else {
98-
Serial.print("ProductName:");
98+
Serial.print("ProductName: ");
9999
Serial.println((char*)productName);
100100
}
101101

@@ -130,6 +130,26 @@ void setup() {
130130
Serial.println(protocolMinor);
131131
}
132132

133+
error = svm40.setTemperatureOffsetForRhtMeasurements(0);
134+
if (error) {
135+
Serial.print("Error trying to execute "
136+
"setTemperatureOffsetForRhtMeasurements(): ");
137+
errorToString(error, errorMessage, 256);
138+
Serial.println(errorMessage);
139+
}
140+
141+
float tOffset;
142+
error = svm40.getTemperatureOffsetForRhtMeasurements(tOffset);
143+
if (error) {
144+
Serial.print("Error trying to execute "
145+
"getTemperatureOffsetForRhtMeasurements(): ");
146+
errorToString(error, errorMessage, 256);
147+
Serial.println(errorMessage);
148+
} else {
149+
Serial.print("Temperature Offset: ");
150+
Serial.println(tOffset);
151+
}
152+
133153
// Start Measurement
134154
error = svm40.startContinuousMeasurement();
135155
if (error) {
@@ -144,24 +164,22 @@ void loop() {
144164
char errorMessage[256];
145165
delay(1000);
146166

147-
// Read Measurement
148-
int16_t vocIndex;
149-
int16_t humidity;
150-
int16_t temperature;
151-
error = svm40.readMeasuredValuesAsIntegers(vocIndex, humidity, temperature);
167+
float vocIndex;
168+
float humidity;
169+
float temperature;
170+
error = svm40.readMeasuredValues(vocIndex, humidity, temperature);
152171
if (error) {
153-
Serial.print(
154-
"Error trying to execute readMeasuredValuesAsIntegers(): ");
172+
Serial.print("Error trying to execute readMeasuredValues: ");
155173
errorToString(error, errorMessage, 256);
156174
Serial.println(errorMessage);
157175
} else {
158-
Serial.print("VocIndex:");
159-
Serial.print(vocIndex / 10.0);
176+
Serial.print("VocIndex: ");
177+
Serial.print(vocIndex);
160178
Serial.print("\t");
161-
Serial.print("Humidity:");
162-
Serial.print(humidity / 100.0);
179+
Serial.print("Humidity: ");
180+
Serial.print(humidity);
163181
Serial.print("\t");
164-
Serial.print("Temperature:");
165-
Serial.println(temperature / 200.0);
182+
Serial.print("Temperature: ");
183+
Serial.println(temperature);
166184
}
167185
}

src/SensirionUartSvm40.cpp

+56-14
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@
3535
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3636
* POSSIBILITY OF SUCH DAMAGE.
3737
*/
38-
3938
#include "SensirionUartSvm40.h"
4039
#include "Arduino.h"
4140
#include "SensirionCore.h"
41+
#include <math.h>
4242

4343
#define SVM40_UART_ADDRESS 0x00
4444

@@ -142,12 +142,31 @@ uint16_t SensirionUartSvm40::readMeasuredValuesAsIntegersWithRawParameters(
142142
return error;
143143
}
144144

145-
uint16_t SensirionUartSvm40::getTemperatureOffsetForRhtMeasurements(
146-
uint8_t tOffset[], uint8_t tOffsetSize) {
145+
uint16_t SensirionUartSvm40::readMeasuredValues(float& vocIndex,
146+
float& humidity,
147+
float& temperature) {
147148
uint16_t error;
148-
uint8_t buffer[522];
149-
SensirionShdlcTxFrame txFrame(buffer, 522);
150-
SensirionShdlcRxFrame rxFrame(buffer, 522);
149+
int16_t humidityRaw;
150+
int16_t temperatureRaw;
151+
int16_t vocRaw;
152+
153+
error = readMeasuredValuesAsIntegers(vocRaw, humidityRaw, temperatureRaw);
154+
if (error) {
155+
return error;
156+
}
157+
158+
humidity = static_cast<float>(humidityRaw) / 100.0f;
159+
temperature = static_cast<float>(temperatureRaw) / 200.0f;
160+
vocIndex = static_cast<float>(vocRaw) / 10.0f;
161+
return NoError;
162+
}
163+
164+
uint16_t SensirionUartSvm40::getTemperatureOffsetForRhtMeasurementsRaw(
165+
int16_t& tOffset) {
166+
uint16_t error;
167+
uint8_t buffer[20];
168+
SensirionShdlcTxFrame txFrame(buffer, sizeof buffer);
169+
SensirionShdlcRxFrame rxFrame(buffer, sizeof buffer);
151170

152171
error = txFrame.begin(0x60, SVM40_UART_ADDRESS, 1);
153172
error |= txFrame.addUInt8(0x01);
@@ -162,10 +181,27 @@ uint16_t SensirionUartSvm40::getTemperatureOffsetForRhtMeasurements(
162181
return error;
163182
}
164183

165-
error |= rxFrame.getBytes(tOffset, tOffsetSize);
184+
error |= rxFrame.getInt16(tOffset);
166185
return error;
167186
}
168187

188+
uint16_t
189+
SensirionUartSvm40::getTemperatureOffsetForRhtMeasurements(float& tOffset) {
190+
uint16_t error;
191+
int16_t tOffsetRaw;
192+
193+
tOffset = NAN;
194+
195+
error = getTemperatureOffsetForRhtMeasurementsRaw(tOffsetRaw);
196+
197+
if (error) {
198+
return error;
199+
}
200+
201+
tOffset = static_cast<float>(tOffsetRaw) / 200.0f;
202+
return NoError;
203+
}
204+
169205
uint16_t SensirionUartSvm40::getVocTuningParameters(
170206
int16_t& vocIndexOffset, int16_t& learningTimeHours,
171207
int16_t& gatingMaxDurationMinutes, int16_t& stdInitial) {
@@ -213,16 +249,16 @@ uint16_t SensirionUartSvm40::storeNvData() {
213249
return error;
214250
}
215251

216-
uint16_t SensirionUartSvm40::setTemperatureOffsetForRhtMeasurements(
217-
uint8_t tOffset[], uint8_t tOffsetSize) {
252+
uint16_t
253+
SensirionUartSvm40::setTemperatureOffsetForRhtMeasurementsRaw(int16_t tOffset) {
218254
uint16_t error;
219-
uint8_t buffer[520];
220-
SensirionShdlcTxFrame txFrame(buffer, 520);
221-
SensirionShdlcRxFrame rxFrame(buffer, 520);
255+
uint8_t buffer[16];
256+
SensirionShdlcTxFrame txFrame(buffer, sizeof buffer);
257+
SensirionShdlcRxFrame rxFrame(buffer, sizeof buffer);
222258

223-
error = txFrame.begin(0x60, SVM40_UART_ADDRESS, 255);
259+
error = txFrame.begin(0x60, SVM40_UART_ADDRESS, 3);
224260
error |= txFrame.addUInt8(0x81);
225-
error |= txFrame.addBytes(tOffset, tOffsetSize);
261+
error |= txFrame.addInt16(tOffset);
226262
error |= txFrame.finish();
227263
if (error) {
228264
return error;
@@ -234,6 +270,12 @@ uint16_t SensirionUartSvm40::setTemperatureOffsetForRhtMeasurements(
234270
return error;
235271
}
236272

273+
uint16_t
274+
SensirionUartSvm40::setTemperatureOffsetForRhtMeasurements(float tOffset) {
275+
int16_t tOffsetRaw = static_cast<int16_t>(tOffset * 200.0f);
276+
return setTemperatureOffsetForRhtMeasurementsRaw(tOffsetRaw);
277+
}
278+
237279
uint16_t SensirionUartSvm40::setVocTuningParameters(
238280
int16_t vocIndexOffset, int16_t learningTimeHours,
239281
int16_t gatingMaxDurationMinutes, int16_t stdInitial) {

src/SensirionUartSvm40.h

+49-4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,26 @@ class SensirionUartSvm40 {
9696
uint16_t readMeasuredValuesAsIntegers(int16_t& vocIndex, int16_t& humidity,
9797
int16_t& temperature);
9898

99+
/**
100+
* readMeasuredValues() - Returns the new measurement results.
101+
*
102+
* @note This command is only available in measurement mode. The firmware
103+
* updates the measurement values every second. Polling data with a faster
104+
* sampling rate will return the same values. The first measurement is
105+
* available 1 second after the start measurement command is issued. Any
106+
* readout prior to this will return zero initialized values.
107+
*
108+
* @param vocIndex VOC index.
109+
*
110+
* @param humidity Compensated ambient humidity in % RH.
111+
*
112+
* @param temperature Compensated ambient temperature in degrees celsius.
113+
*
114+
* @return 0 on success, an error code otherwise
115+
*/
116+
uint16_t readMeasuredValues(float& vocIndex, float& humidity,
117+
float& temperature);
118+
99119
/**
100120
* readMeasuredValuesAsIntegersWithRawParameters() - Returns the new
101121
* measurement results as integers with raw values added.
@@ -140,8 +160,20 @@ class SensirionUartSvm40 {
140160
*
141161
* @return 0 on success, an error code otherwise
142162
*/
143-
uint16_t getTemperatureOffsetForRhtMeasurements(uint8_t tOffset[],
144-
uint8_t tOffsetSize);
163+
uint16_t getTemperatureOffsetForRhtMeasurementsRaw(int16_t& tOffset);
164+
165+
/**
166+
* getTemperatureOffsetForRhtMeasurements() - Gets the T-Offset for the
167+
* temperature compensation of the RHT algorithm.
168+
*
169+
* @param tOffset Temperature offset which is used for the RHT measurements
170+
* in degrees celsius with no scaling.
171+
*
172+
* @note Only supported for firmware version >= 2.0.
173+
*
174+
* @return 0 on success, an error code otherwise
175+
*/
176+
uint16_t getTemperatureOffsetForRhtMeasurements(float& tOffset);
145177

146178
/**
147179
* getVocTuningParameters() - Gets the currently set parameters for
@@ -192,8 +224,21 @@ class SensirionUartSvm40 {
192224
*
193225
* @return 0 on success, an error code otherwise
194226
*/
195-
uint16_t setTemperatureOffsetForRhtMeasurements(uint8_t tOffset[],
196-
uint8_t tOffsetSize);
227+
uint16_t setTemperatureOffsetForRhtMeasurementsRaw(int16_t tOffset);
228+
229+
/**
230+
* setTemperatureOffsetForRhtMeasurements() - Sets the T-Offset for the
231+
* temperature compensation of the RHT algorithm.
232+
*
233+
* @note Execute the store command after writing the parameter to store it
234+
* in the non-volatile memory of the device otherwise the parameter will be
235+
* reset upton a device reset.
236+
*
237+
* @param tOffset Temperature offset in degrees celsius.
238+
*
239+
* @return 0 on success, an error code otherwise
240+
*/
241+
uint16_t setTemperatureOffsetForRhtMeasurements(float tOffset);
197242

198243
/**
199244
* setVocTuningParameters() - Sets parameters to customize the VOC

0 commit comments

Comments
 (0)