Skip to content

Commit d7e7d54

Browse files
committed
SEN44 UART example
1 parent 7a01a1a commit d7e7d54

10 files changed

+1130
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "sensirion_uart.h"
2+
#include "sen44.h"
3+
4+
// used for sensor measurement return values
5+
struct sen44_measurement m;
6+
7+
char serial[SEN44_MAX_SERIAL_LEN];
8+
9+
void setup() {
10+
int16_t ret;
11+
12+
Serial.begin(115200);
13+
// wait for serial connection from PC
14+
// comment the following line if you'd like the output
15+
// without waiting for the interface being ready
16+
while(!Serial);
17+
18+
// init serial interface to communicate with sensor
19+
while (sensirion_uart_open() != 0) {
20+
Serial.println("UART init failed\n");
21+
// sleep for 1 s
22+
sensirion_sleep_usec(1000000);
23+
}
24+
delay(1000);
25+
26+
// get sensor serial id
27+
ret = sen44_get_serial(serial);
28+
29+
Serial.print("SEN44 Serial: ");
30+
Serial.println(serial);
31+
32+
// start the measurement mode
33+
// fan and laser will be activated
34+
// TVOC and RH,T sensors set to measure mode
35+
ret = sen44_start_measurement();
36+
if (ret < 0)
37+
Serial.println("error starting measurement\n");
38+
39+
//wait for startup of the fan
40+
delay(1000);
41+
42+
Serial.println("PM_1.0\tPM_2.5\tPM_4.0\tPM_10.0\tVOCT\tRH\tT");
43+
}
44+
45+
void loop() {
46+
int16_t ret;
47+
48+
// read sensor data
49+
ret = sen44_read_measurement(&m);
50+
if (ret < 0) {
51+
Serial.println("error reading measurement\n");
52+
Serial.println(ret);
53+
}
54+
55+
Serial.print("" + String(m.mc_1p0)); //serial print pm value
56+
Serial.print("\t" + String(m.mc_2p5)); //serial print pm value
57+
Serial.print("\t" + String(m.mc_4p0)); //serial print pm value
58+
Serial.print("\t" + String(m.mc_10p0)); //serial print pm value
59+
Serial.print("\t" + String(float(m.voc_index)/10)); //serial print NO2 value in ppb
60+
Serial.print("\t" + String(float(m.ambient_humidity)/100)); //serial print RH value
61+
Serial.print("\t" + String(float(m.ambient_temperature)/200)); //serial print T value
62+
Serial.println();
63+
64+
delay(1000);
65+
}

SEN44_UART_minimal_example/sen44.c

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/*
2+
* Copyright (c) 2019, Sensirion AG
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* * Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* * Neither the name of Sensirion AG nor the names of its
16+
* contributors may be used to endorse or promote products derived from
17+
* this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
* POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
#include "sen44.h"
33+
#include "sensirion_shdlc.h"
34+
#include "sps_git_version.h"
35+
36+
#define SEN44_ADDR 0x00
37+
#define SEN44_CMD_START_MEASUREMENT 0x00
38+
#define SEN44_CMD_STOP_MEASUREMENT 0x01
39+
#define SEN44_SUBCMD_MEASUREMENT_START_PMSGP { 0x02 }
40+
#define SEN44_CMD_READ_MEASUREMENT 0x03
41+
42+
#define SEN44_SUBCMD_READ_MEASUREMENT_DEFAULT { 0x07 }
43+
#define SEN44_READ_MEASUREMENT_MODE_DEFAULT 0x00
44+
#define SEN44_READ_MEASUREMENT_SIZE_DEFAULT 7
45+
46+
#define SEN44_CMD_READ_FAN_SPEED 0x40
47+
#define SEN44_CMD_FAN_CLEAN_INTV 0x80
48+
#define SEN44_CMD_FAN_CLEAN_INTV_LEN 5
49+
#define SEN44_SUBCMD_READ_FAN_CLEAN_INTV 0x00
50+
#define SEN44_CMD_START_FAN_CLEANING 0x56
51+
#define SEN44_CMD_DEV_INFO 0xd0
52+
#define SEN44_CMD_DEV_INFO_SUBCMD_GET_SERIAL { 0x03 }
53+
#define SEN44_CMD_RESET 0xd3
54+
#define SEN44_ERR_STATE(state) (SEN44_ERR_STATE_MASK | (state))
55+
56+
const char *sen44_get_driver_version() {
57+
return SPS_DRV_VERSION_STR;
58+
}
59+
60+
int16_t sen44_probe() {
61+
char serial[SEN44_MAX_SERIAL_LEN];
62+
int16_t ret = sen44_get_serial(serial);
63+
64+
return ret;
65+
}
66+
67+
int16_t sen44_get_serial(char *serial) {
68+
struct sensirion_shdlc_rx_header header;
69+
uint8_t param_buf[] = SEN44_CMD_DEV_INFO_SUBCMD_GET_SERIAL;
70+
int16_t ret;
71+
72+
ret = sensirion_shdlc_xcv(SEN44_ADDR, SEN44_CMD_DEV_INFO, sizeof(param_buf),
73+
param_buf, SEN44_MAX_SERIAL_LEN, &header,
74+
(uint8_t *)serial);
75+
if (ret < 0)
76+
return ret;
77+
78+
if (header.state)
79+
return SEN44_ERR_STATE(header.state);
80+
81+
return 0;
82+
}
83+
84+
int16_t sen44_start_measurement() {
85+
struct sensirion_shdlc_rx_header header;
86+
uint8_t param_buf[] = SEN44_SUBCMD_MEASUREMENT_START_PMSGP;
87+
88+
return sensirion_shdlc_xcv(SEN44_ADDR, SEN44_CMD_START_MEASUREMENT,
89+
sizeof(param_buf), param_buf, 0, &header, NULL);
90+
}
91+
92+
int16_t sen44_stop_measurement() {
93+
struct sensirion_shdlc_rx_header header;
94+
95+
return sensirion_shdlc_xcv(SEN44_ADDR, SEN44_CMD_STOP_MEASUREMENT, 0, NULL,
96+
0, &header, NULL);
97+
}
98+
99+
int16_t sen44_read_measurement(struct sen44_measurement *measurement) {
100+
struct sensirion_shdlc_rx_header header;
101+
int i;
102+
int16_t ret;
103+
uint16_t idx;
104+
int8_t datasize;
105+
106+
datasize = SEN44_READ_MEASUREMENT_SIZE_DEFAULT;
107+
108+
union {
109+
uint16_t u16_value;
110+
int16_t s16_value;
111+
} val, data[datasize];
112+
113+
uint8_t param_buf[] = SEN44_SUBCMD_READ_MEASUREMENT_DEFAULT;
114+
115+
ret = sensirion_shdlc_xcv(SEN44_ADDR, SEN44_CMD_READ_MEASUREMENT, sizeof(param_buf), param_buf, sizeof(data), &header, (uint8_t *)data);
116+
if (ret)
117+
return ret;
118+
119+
if (header.data_len != sizeof(data))
120+
return SEN44_ERR_NOT_ENOUGH_DATA;
121+
122+
idx = 0;
123+
val.u16_value = be16_to_cpu(data[idx].u16_value);
124+
measurement->mc_1p0 = val.u16_value;
125+
++idx;
126+
val.u16_value = be16_to_cpu(data[idx].u16_value);
127+
measurement->mc_2p5 = val.u16_value;
128+
++idx;
129+
val.u16_value = be16_to_cpu(data[idx].u16_value);
130+
measurement->mc_4p0 = val.u16_value;
131+
++idx;
132+
val.u16_value = be16_to_cpu(data[idx].u16_value);
133+
measurement->mc_10p0 = val.u16_value;
134+
++idx;
135+
val.s16_value = be16_to_cpu(data[idx].u16_value);
136+
measurement->voc_index = val.s16_value;
137+
++idx;
138+
val.s16_value = be16_to_cpu(data[idx].u16_value);
139+
measurement->ambient_humidity = val.s16_value;
140+
++idx;
141+
val.s16_value = be16_to_cpu(data[idx].u16_value);
142+
measurement->ambient_temperature = val.s16_value;
143+
++idx;
144+
145+
if (header.state)
146+
return SEN44_ERR_STATE(header.state);
147+
148+
return 0;
149+
}
150+
151+
int16_t sen44_get_fan_auto_cleaning_interval(uint32_t *interval_seconds) {
152+
struct sensirion_shdlc_rx_header header;
153+
uint8_t tx_data[] = {SEN44_SUBCMD_READ_FAN_CLEAN_INTV};
154+
int16_t ret;
155+
156+
ret = sensirion_shdlc_xcv(
157+
SEN44_ADDR, SEN44_CMD_FAN_CLEAN_INTV, sizeof(tx_data), tx_data,
158+
sizeof(*interval_seconds), &header, (uint8_t *)interval_seconds);
159+
if (ret < 0)
160+
return ret;
161+
162+
*interval_seconds = be32_to_cpu(*interval_seconds);
163+
164+
if (header.state)
165+
return SEN44_ERR_STATE(header.state);
166+
167+
return 0;
168+
}
169+
170+
int16_t sen44_set_fan_auto_cleaning_interval(uint32_t interval_seconds) {
171+
struct sensirion_shdlc_rx_header header;
172+
uint8_t ix;
173+
uint8_t cleaning_command[SEN44_CMD_FAN_CLEAN_INTV_LEN];
174+
uint32_t value = be32_to_cpu(interval_seconds);
175+
176+
cleaning_command[0] = SEN44_SUBCMD_READ_FAN_CLEAN_INTV;
177+
for (ix = 0; ix < sizeof(uint32_t); ix++)
178+
cleaning_command[ix + 1] = (uint8_t)(value >> (8 * ix));
179+
return sensirion_shdlc_xcv(
180+
SEN44_ADDR, SEN44_CMD_FAN_CLEAN_INTV, sizeof(cleaning_command),
181+
(const uint8_t *)cleaning_command, sizeof(interval_seconds), &header,
182+
(uint8_t *)&interval_seconds);
183+
}
184+
185+
int16_t sen44_get_fan_auto_cleaning_interval_days(uint8_t *interval_days) {
186+
int16_t ret;
187+
uint32_t interval_seconds;
188+
189+
ret = sen44_get_fan_auto_cleaning_interval(&interval_seconds);
190+
if (ret < 0)
191+
return ret;
192+
193+
*interval_days = interval_seconds / (24 * 60 * 60);
194+
return ret;
195+
}
196+
197+
int16_t sen44_set_fan_auto_cleaning_interval_days(uint8_t interval_days) {
198+
return sen44_set_fan_auto_cleaning_interval((uint32_t)interval_days * 24 *
199+
60 * 60);
200+
}
201+
202+
int16_t sen44_start_manual_fan_cleaning() {
203+
struct sensirion_shdlc_rx_header header;
204+
205+
return sensirion_shdlc_xcv(SEN44_ADDR, SEN44_CMD_START_FAN_CLEANING, 0,
206+
NULL, 0, &header, NULL);
207+
}
208+
209+
int16_t sen44_reset() {
210+
return sensirion_shdlc_tx(SEN44_ADDR, SEN44_CMD_RESET, 0, NULL);
211+
}

0 commit comments

Comments
 (0)