55
66#include <zephyr/kernel.h>
77#include <zephyr/drivers/sensor.h>
8+ #include <zephyr/drivers/i2c.h>
89#include <zephyr/logging/log.h>
10+ #include <zephyr/drivers/sensor/ccs811.h>
911
1012#include <app/drivers/blink.h>
1113
@@ -16,60 +18,264 @@ LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL);
1618#define BLINK_PERIOD_MS_STEP 100U
1719#define BLINK_PERIOD_MS_MAX 1000U
1820
19- int main (void )
20- {
21- int ret ;
22- const struct device * sensor , * blink ;
23- struct sensor_value temp , press , hum ;
21+ /* Function prototypes */
22+ static int init_sensors (const struct device * * bme280 , const struct device * * ccs811 ,
23+ const struct device * * hm3301 , const struct device * * blink );
24+ static int read_bme280_data (const struct device * sensor , struct sensor_value * temp ,
25+ struct sensor_value * press , struct sensor_value * hum );
26+ static int read_ccs811_data (const struct device * sensor , struct sensor_value * co2 ,
27+ struct sensor_value * voc );
28+ static int read_hm3301_data (const struct device * sensor , struct sensor_value * pm1 ,
29+ struct sensor_value * pm25 , struct sensor_value * pm10 );
30+ static void log_sensor_data (const struct sensor_value * temp , const struct sensor_value * press ,
31+ const struct sensor_value * hum , const struct sensor_value * co2 ,
32+ const struct sensor_value * voc , const struct sensor_value * pm1 ,
33+ const struct sensor_value * pm25 , const struct sensor_value * pm10 );
2434
25- LOG_INF ("Zephyr Fire Detection System %s" , APP_VERSION_STRING );
35+ #ifdef CONFIG_CCS811_ENV_COMPENSATION
36+ static int update_ccs811_env_data (const struct device * ccs811_sensor ,
37+ const struct sensor_value * temp , const struct sensor_value * hum );
38+ #endif
2639
27- sensor = DEVICE_DT_GET (DT_NODELABEL (bme280 ));
28- if (!device_is_ready (sensor )) {
40+ static int init_sensors (const struct device * * bme280 , const struct device * * ccs811 ,
41+ const struct device * * hm3301 , const struct device * * blink )
42+ {
43+ /* Initialize BME280 sensor */
44+ * bme280 = DEVICE_DT_GET (DT_NODELABEL (bme280 ));
45+ if (!device_is_ready (* bme280 )) {
2946 LOG_ERR ("BME280 sensor not ready" );
30- return 0 ;
47+ return - ENODEV ;
3148 }
3249
33- blink = DEVICE_DT_GET (DT_NODELABEL (blink_led ));
34- if (!device_is_ready (blink )) {
50+ k_sleep (K_MSEC (5000 ));
51+
52+ /* Initialize CCS811 sensor */
53+ * ccs811 = DEVICE_DT_GET (DT_NODELABEL (ccs811 ));
54+ if (!device_is_ready (* ccs811 )) {
55+ LOG_ERR ("CCS811 sensor not ready" );
56+ return - ENODEV ;
57+ }
58+
59+ /* Initialize HM3301 sensor */
60+ * hm3301 = DEVICE_DT_GET (DT_NODELABEL (hm3301 ));
61+ if (!device_is_ready (* hm3301 )) {
62+ LOG_ERR ("HM3301 sensor not ready" );
63+ return - ENODEV ;
64+ }
65+
66+ * blink = DEVICE_DT_GET (DT_NODELABEL (blink_led ));
67+ if (!device_is_ready (* blink )) {
3568 LOG_ERR ("Blink LED not ready" );
36- return 0 ;
69+ return - ENODEV ;
3770 }
3871
39- ret = blink_off (blink );
72+ int ret = blink_off (* blink );
4073 if (ret < 0 ) {
4174 LOG_ERR ("Could not turn off LED (%d)" , ret );
75+ return ret ;
76+ }
77+
78+ LOG_INF ("All sensors initialized successfully" );
79+ return 0 ;
80+ }
81+
82+ static int read_bme280_data (const struct device * sensor , struct sensor_value * temp ,
83+ struct sensor_value * press , struct sensor_value * hum )
84+ {
85+ int ret = sensor_sample_fetch (sensor );
86+ if (ret < 0 ) {
87+ LOG_ERR ("Could not fetch BME280 sample (%d)" , ret );
88+ return ret ;
89+ }
90+
91+ ret = sensor_channel_get (sensor , SENSOR_CHAN_AMBIENT_TEMP , temp );
92+ if (ret < 0 ) {
93+ LOG_ERR ("Could not get temperature (%d)" , ret );
94+ return ret ;
95+ }
96+
97+ ret = sensor_channel_get (sensor , SENSOR_CHAN_PRESS , press );
98+ if (ret < 0 ) {
99+ LOG_ERR ("Could not get pressure (%d)" , ret );
100+ return ret ;
101+ }
102+
103+ ret = sensor_channel_get (sensor , SENSOR_CHAN_HUMIDITY , hum );
104+ if (ret < 0 ) {
105+ LOG_ERR ("Could not get humidity (%d)" , ret );
106+ return ret ;
107+ }
108+
109+ return 0 ;
110+ }
111+
112+ static int read_ccs811_data (const struct device * sensor , struct sensor_value * co2 ,
113+ struct sensor_value * voc )
114+ {
115+ int ret = sensor_sample_fetch (sensor );
116+ if (ret < 0 ) {
117+ LOG_ERR ("Could not fetch CCS811 sample (%d)" , ret );
118+ return ret ;
119+ }
120+
121+ ret = sensor_channel_get (sensor , SENSOR_CHAN_CO2 , co2 );
122+ if (ret < 0 ) {
123+ LOG_ERR ("Could not get CO2 (%d)" , ret );
124+ return ret ;
125+ }
126+
127+ ret = sensor_channel_get (sensor , SENSOR_CHAN_VOC , voc );
128+ if (ret < 0 ) {
129+ LOG_ERR ("Could not get VOC (%d)" , ret );
130+ return ret ;
131+ }
132+
133+ return 0 ;
134+ }
135+
136+ static int read_hm3301_data (const struct device * sensor , struct sensor_value * pm1 ,
137+ struct sensor_value * pm25 , struct sensor_value * pm10 )
138+ {
139+ int ret = sensor_sample_fetch (sensor );
140+ if (ret < 0 ) {
141+ LOG_ERR ("Could not fetch HM3301 sample (%d)" , ret );
142+ return ret ;
143+ }
144+
145+ ret = sensor_channel_get (sensor , SENSOR_CHAN_PM_1_0 , pm1 );
146+ if (ret < 0 ) {
147+ LOG_ERR ("Could not get PM1.0 (%d)" , ret );
148+ return ret ;
149+ }
150+
151+ ret = sensor_channel_get (sensor , SENSOR_CHAN_PM_2_5 , pm25 );
152+ if (ret < 0 ) {
153+ LOG_ERR ("Could not get PM2.5 (%d)" , ret );
154+ return ret ;
155+ }
156+
157+ ret = sensor_channel_get (sensor , SENSOR_CHAN_PM_10 , pm10 );
158+ if (ret < 0 ) {
159+ LOG_ERR ("Could not get PM10 (%d)" , ret );
160+ return ret ;
161+ }
162+
163+ return 0 ;
164+ }
165+
166+ static void log_sensor_data (const struct sensor_value * temp , const struct sensor_value * press ,
167+ const struct sensor_value * hum , const struct sensor_value * co2 ,
168+ const struct sensor_value * voc , const struct sensor_value * pm1 ,
169+ const struct sensor_value * pm25 , const struct sensor_value * pm10 )
170+ {
171+ LOG_INF ("BME280: Temp: %d.%06d C, Press: %d.%06d kPa, Hum: %d.%06d %%" , temp -> val1 ,
172+ temp -> val2 , press -> val1 , press -> val2 , hum -> val1 , hum -> val2 );
173+
174+ LOG_INF ("CCS811: CO2: %d ppm, VOC: %d ppb" , co2 -> val1 , voc -> val1 );
175+
176+ LOG_INF ("HM3301: PM1.0: %d μg/m³, PM2.5: %d μg/m³, PM10: %d μg/m³" , pm1 -> val1 , pm25 -> val1 ,
177+ pm10 -> val1 );
178+ }
179+
180+ #ifdef CONFIG_CCS811_ENV_COMPENSATION
181+ static int update_ccs811_env_data (const struct device * ccs811_sensor ,
182+ const struct sensor_value * temp , const struct sensor_value * hum )
183+ {
184+ /* Previous environmental values for smart updates */
185+ static struct sensor_value prev_temp = {0 , 0 };
186+ static struct sensor_value prev_hum = {0 , 0 };
187+ static bool env_data_initialized = false;
188+
189+ bool should_update = false;
190+
191+ /* Check if this is the first update */
192+ if (!env_data_initialized ) {
193+ should_update = true;
194+ env_data_initialized = true;
195+ LOG_INF ("Initializing CCS811 environmental data" );
196+ } else {
197+ /* Check for significant changes (0.5°C or 0.5% RH threshold) */
198+ int32_t temp_diff = abs ((temp -> val1 * 1000000 + temp -> val2 ) -
199+ (prev_temp .val1 * 1000000 + prev_temp .val2 ));
200+ int32_t hum_diff = abs ((hum -> val1 * 1000000 + hum -> val2 ) -
201+ (prev_hum .val1 * 1000000 + prev_hum .val2 ));
202+
203+ /* Update if temperature changed by more than 0.5°C or humidity by more than 0.5% */
204+ if (temp_diff >= 500000 || hum_diff >= 500000 ) {
205+ should_update = true;
206+ LOG_DBG ("Environmental change detected - updating CCS811" );
207+ }
208+ }
209+
210+ if (should_update ) {
211+ int ret = ccs811_envdata_update (ccs811_sensor , temp , hum );
212+ if (ret < 0 ) {
213+ LOG_ERR ("Could not update CCS811 environmental data (%d)" , ret );
214+ return ret ;
215+ }
216+
217+ LOG_INF ("CCS811 env data updated: T=%d.%02d°C, H=%d.%02d%%" , temp -> val1 ,
218+ temp -> val2 / 10000 , hum -> val1 , hum -> val2 / 10000 );
219+
220+ /* Store current values for next comparison */
221+ prev_temp = * temp ;
222+ prev_hum = * hum ;
223+ }
224+
225+ return 0 ;
226+ }
227+ #endif /* CONFIG_CCS811_ENV_COMPENSATION */
228+
229+ int main (void )
230+ {
231+ int ret ;
232+ const struct device * bme280_sensor , * ccs811_sensor , * hm3301_sensor , * blink ;
233+ struct sensor_value temp , press , hum , co2 , voc , pm1 , pm25 , pm10 ;
234+
235+ LOG_INF ("Zephyr Fire Detection System %s" , APP_VERSION_STRING );
236+
237+ /* Get I2C device for scanning */
238+ const struct device * i2c_dev = DEVICE_DT_GET (DT_NODELABEL (i2c2 ));
239+ if (!device_is_ready (i2c_dev )) {
240+ LOG_ERR ("I2C device not ready" );
241+ return 0 ;
242+ }
243+
244+ /* Initialize all sensors */
245+ ret = init_sensors (& bme280_sensor , & ccs811_sensor , & hm3301_sensor , & blink );
246+ if (ret < 0 ) {
247+ LOG_ERR ("Sensor initialization failed" );
42248 return 0 ;
43249 }
44250
45251 while (1 ) {
46- ret = sensor_sample_fetch (sensor );
252+ /* Read BME280 data (temperature, pressure, humidity) */
253+ ret = read_bme280_data (bme280_sensor , & temp , & press , & hum );
47254 if (ret < 0 ) {
48- LOG_ERR ("Could not fetch BME280 sample (%d)" , ret );
49- k_sleep (K_MSEC (1000 ));
50- continue ;
255+ LOG_ERR ("Failed to read BME280 data" );
51256 }
52257
53- ret = sensor_channel_get ( sensor , SENSOR_CHAN_AMBIENT_TEMP , & temp );
54- if ( ret < 0 ) {
55- LOG_ERR ( "Could not get temperature (%d)" , ret );
56- continue ;
258+ #ifdef CONFIG_CCS811_ENV_COMPENSATION
259+ /* Update CCS811 environmental data if BME280 reading was successful */
260+ if ( ret == 0 ) {
261+ update_ccs811_env_data ( ccs811_sensor , & temp , & hum ) ;
57262 }
263+ #endif /* CONFIG_CCS811_ENV_COMPENSATION */
58264
59- ret = sensor_channel_get (sensor , SENSOR_CHAN_PRESS , & press );
265+ /* Read CCS811 data (CO2 and VOC) */
266+ ret = read_ccs811_data (ccs811_sensor , & co2 , & voc );
60267 if (ret < 0 ) {
61- LOG_ERR ("Could not get pressure (%d)" , ret );
62- continue ;
268+ LOG_ERR ("Failed to read CCS811 data" );
63269 }
64270
65- ret = sensor_channel_get (sensor , SENSOR_CHAN_HUMIDITY , & hum );
271+ /* Read HM3301 data (PM1.0, PM2.5, PM10) */
272+ ret = read_hm3301_data (hm3301_sensor , & pm1 , & pm25 , & pm10 );
66273 if (ret < 0 ) {
67- LOG_ERR ("Could not get humidity (%d)" , ret );
68- continue ;
274+ LOG_ERR ("Failed to read HM3301 data" );
69275 }
70276
71- LOG_INF ( "BME280: Temp: %d.%06d C, Press: %d.%06d kPa, Hum: %d.%06d %%" , temp . val1 ,
72- temp . val2 , press . val1 , press . val2 , hum . val1 , hum . val2 );
277+ /* Log all sensor data */
278+ log_sensor_data ( & temp , & press , & hum , & co2 , & voc , & pm1 , & pm25 , & pm10 );
73279
74280 k_sleep (K_MSEC (1000 ));
75281 }
0 commit comments