2 * collectd - src/barometer.c
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; only version 2.1 of the License is
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "utils_cache.h"
29 #include <linux/i2c-dev.h>
32 #include <sys/ioctl.h>
35 /* ------------ MPL115 defines ------------ */
36 /* I2C address of the MPL115 sensor */
37 #define MPL115_I2C_ADDRESS 0x60
39 /* register addresses */
40 #define MPL115_ADDR_CONV 0x00
41 #define MPL115_ADDR_COEFFS 0x04
44 #define MPL115_NUM_CONV 4
45 #define MPL115_NUM_COEFFS 12
47 /* commands / addresses */
48 #define MPL115_CMD_CONVERT_PRESS 0x10
49 #define MPL115_CMD_CONVERT_TEMP 0x11
50 #define MPL115_CMD_CONVERT_BOTH 0x12
52 #define MPL115_CONVERSION_RETRIES 5
54 /* ------------ MPL3115 defines ------------ */
55 /* MPL3115 I2C address */
56 #define MPL3115_I2C_ADDRESS 0x60
58 /* register addresses (only the interesting ones) */
59 #define MPL3115_REG_STATUS 0x00
60 #define MPL3115_REG_OUT_P_MSB 0x01
61 #define MPL3115_REG_OUT_P_CSB 0x02
62 #define MPL3115_REG_OUT_P_LSB 0x03
63 #define MPL3115_REG_OUT_T_MSB 0x04
64 #define MPL3115_REG_OUT_T_LSB 0x05
65 #define MPL3115_REG_DR_STATUS 0x06
66 #define MPL3115_REG_WHO_AM_I 0x0C
67 #define MPL3115_REG_SYSMOD 0x11
68 #define MPL3115_REG_PT_DATA_CFG 0x13
69 #define MPL3115_REG_BAR_IN_MSB 0x14
70 #define MPL3115_REG_BAR_IN_LSB 0x15
71 #define MPL3115_REG_CTRL_REG1 0x26
72 #define MPL3115_REG_CTRL_REG2 0x27
73 #define MPL3115_REG_CTRL_REG3 0x28
74 #define MPL3115_REG_CTRL_REG4 0x29
75 #define MPL3115_REG_CTRL_REG5 0x2A
76 #define MPL3115_REG_OFF_P 0x2B
77 #define MPL3115_REG_OFF_T 0x2C
78 #define MPL3115_REG_OFF_H 0x2D
80 /* Register values, masks */
81 #define MPL3115_WHO_AM_I_RESP 0xC4
83 #define MPL3115_PT_DATA_DREM 0x04
84 #define MPL3115_PT_DATA_PDEF 0x02
85 #define MPL3115_PT_DATA_TDEF 0x01
87 #define MPL3115_DR_STATUS_TDR 0x02
88 #define MPL3115_DR_STATUS_PDR 0x04
89 #define MPL3115_DR_STATUS_PTDR 0x08
90 #define MPL3115_DR_STATUS_DR \
91 (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
93 #define MPL3115_DR_STATUS_TOW 0x20
94 #define MPL3115_DR_STATUS_POW 0x40
95 #define MPL3115_DR_STATUS_PTOW 0x80
97 #define MPL3115_CTRL_REG1_ALT 0x80
98 #define MPL3115_CTRL_REG1_RAW 0x40
99 #define MPL3115_CTRL_REG1_OST_MASK 0x38
100 #define MPL3115_CTRL_REG1_OST_1 0x00
101 #define MPL3115_CTRL_REG1_OST_2 0x08
102 #define MPL3115_CTRL_REG1_OST_4 0x10
103 #define MPL3115_CTRL_REG1_OST_8 0x18
104 #define MPL3115_CTRL_REG1_OST_16 0x20
105 #define MPL3115_CTRL_REG1_OST_32 0x28
106 #define MPL3115_CTRL_REG1_OST_64 0x30
107 #define MPL3115_CTRL_REG1_OST_128 0x38
108 #define MPL3115_CTRL_REG1_RST 0x04
109 #define MPL3115_CTRL_REG1_OST 0x02
110 #define MPL3115_CTRL_REG1_SBYB 0x01
111 #define MPL3115_CTRL_REG1_SBYB_MASK 0xFE
113 #define MPL3115_NUM_CONV_VALS 5
115 /* ------------ BMP085 defines ------------ */
116 /* I2C address of the BMP085 sensor */
117 #define BMP085_I2C_ADDRESS 0x77
119 /* register addresses */
120 #define BMP085_ADDR_ID_REG 0xD0
121 #define BMP085_ADDR_VERSION 0xD1
123 #define BMP085_ADDR_CONV 0xF6
125 #define BMP085_ADDR_CTRL_REG 0xF4
126 #define BMP085_ADDR_COEFFS 0xAA
129 #define BMP085_NUM_COEFFS 22
131 /* commands, values */
132 #define BMP085_CHIP_ID 0x55
134 #define BMP085_CMD_CONVERT_TEMP 0x2E
136 #define BMP085_CMD_CONVERT_PRESS_0 0x34
137 #define BMP085_CMD_CONVERT_PRESS_1 0x74
138 #define BMP085_CMD_CONVERT_PRESS_2 0xB4
139 #define BMP085_CMD_CONVERT_PRESS_3 0xF4
142 #define BMP085_TIME_CNV_TEMP 4500
144 #define BMP085_TIME_CNV_PRESS_0 4500
145 #define BMP085_TIME_CNV_PRESS_1 7500
146 #define BMP085_TIME_CNV_PRESS_2 13500
147 #define BMP085_TIME_CNV_PRESS_3 25500
149 /* ------------ Normalization ------------ */
150 /* Mean sea level pressure normalization methods */
152 #define MSLP_INTERNATIONAL 1
153 #define MSLP_DEU_WETT 2
155 /** Temperature reference history depth for averaging. See
156 * #get_reference_temperature */
157 #define REF_TEMP_AVG_NUM 5
159 /* ------------------------------------------ */
161 /** Supported sensor types */
169 static const char *config_keys[] = {
172 "PressureOffset", /**< only for MPL3115 */
173 "TemperatureOffset", /**< only for MPL3115 */
176 "TemperatureSensor"};
178 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
180 static char *config_device = NULL; /**< I2C bus device */
181 static int config_oversample = 1; /**< averaging window */
183 static double config_press_offset = 0.0; /**< pressure offset */
184 static double config_temp_offset = 0.0; /**< temperature offset */
186 static double config_altitude = NAN; /**< altitude */
187 static int config_normalize = 0; /**< normalization method */
189 static _Bool configured = 0; /**< the whole plugin config status */
191 static int i2c_bus_fd = -1; /**< I2C bus device FD */
193 static enum Sensor_type sensor_type =
194 Sensor_none; /**< detected/used sensor type */
196 static __s32 mpl3115_oversample = 0; /**< MPL3115 CTRL1 oversample setting */
198 // BMP085 configuration
199 static unsigned bmp085_oversampling; /**< BMP085 oversampling (0-3) */
201 bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */
202 static __u8 bmp085_cmdCnvPress; /**< BMP085 pressure conversion command */
204 /* MPL115 conversion coefficients */
205 static double mpl115_coeffA0;
206 static double mpl115_coeffB1;
207 static double mpl115_coeffB2;
208 static double mpl115_coeffC12;
209 static double mpl115_coeffC11;
210 static double mpl115_coeffC22;
212 /* BMP085 conversion coefficients */
213 static short bmp085_AC1;
214 static short bmp085_AC2;
215 static short bmp085_AC3;
216 static unsigned short bmp085_AC4;
217 static unsigned short bmp085_AC5;
218 static unsigned short bmp085_AC6;
219 static short bmp085_B1;
220 static short bmp085_B2;
221 static short bmp085_MB;
222 static short bmp085_MC;
223 static short bmp085_MD;
225 /* ------------------------ averaging ring buffer ------------------------ */
226 /* Used only for MPL115. MPL3115 supports real oversampling in the device so */
227 /* no need for any postprocessing. */
229 static _Bool avg_initialized = 0; /**< already initialized by real values */
231 typedef struct averaging_s {
232 long int *ring_buffer;
233 int ring_buffer_size;
234 long int ring_buffer_sum;
235 int ring_buffer_head;
238 static averaging_t pressure_averaging = {NULL, 0, 0L, 0};
239 static averaging_t temperature_averaging = {NULL, 0, 0L, 0};
242 * Create / allocate averaging buffer
244 * The buffer is initialized with zeros.
246 * @param avg pointer to ring buffer to be allocated
247 * @param size requested buffer size
249 * @return Zero when successful
251 static int averaging_create(averaging_t *avg, int size) {
252 avg->ring_buffer = calloc((size_t)size, sizeof(*avg->ring_buffer));
253 if (avg->ring_buffer == NULL) {
254 ERROR("barometer: averaging_create - ring buffer allocation of size %d "
260 avg->ring_buffer_size = size;
261 avg->ring_buffer_sum = 0L;
262 avg->ring_buffer_head = 0;
268 * Delete / free existing averaging buffer
270 * @param avg pointer to the ring buffer to be deleted
272 static void averaging_delete(averaging_t *avg) {
273 if (avg->ring_buffer != NULL) {
274 free(avg->ring_buffer);
275 avg->ring_buffer = NULL;
277 avg->ring_buffer_size = 0;
278 avg->ring_buffer_sum = 0L;
279 avg->ring_buffer_head = 0;
283 * Add new sample to the averaging buffer
285 * A new averaged value is returned. Note that till the buffer is full
286 * returned value is inaccurate as it is an average of real values and initial
289 * @param avg pointer to the ring buffer
290 * @param sample new sample value
292 * @return Averaged sample value
294 static double averaging_add_sample(averaging_t *avg, long int sample) {
297 avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head];
298 avg->ring_buffer[avg->ring_buffer_head] = sample;
299 avg->ring_buffer_head = (avg->ring_buffer_head + 1) % avg->ring_buffer_size;
300 result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
302 DEBUG("barometer: averaging_add_sample - added %ld, result = %lf", sample,
308 /* ------------------------ temperature refference ------------------------ */
311 * Linked list type of temperature sensor references
313 typedef struct temperature_list_s {
314 char *sensor_name; /**< sensor name/reference */
315 size_t num_values; /**< number of values (usually one) */
316 _Bool initialized; /**< sensor already provides data */
317 struct temperature_list_s *next; /**< next in the list */
318 } temperature_list_t;
320 static temperature_list_t *temp_list = NULL;
323 * Add new sensor to the temperature reference list
325 * @param list the list
326 * @param sensor reference name (as provided by the config file)
328 * @return Zero when successful
330 static int temp_list_add(temperature_list_t *list, const char *sensor) {
331 temperature_list_t *new_temp;
333 new_temp = malloc(sizeof(*new_temp));
334 if (new_temp == NULL)
337 new_temp->sensor_name = strdup(sensor);
338 new_temp->initialized = 0;
339 new_temp->num_values = 0;
340 if (new_temp->sensor_name == NULL) {
345 new_temp->next = temp_list;
346 temp_list = new_temp;
351 * Delete the whole temperature reference list
353 * @param list the list to be deleted
355 static void temp_list_delete(temperature_list_t **list) {
356 temperature_list_t *tmp;
358 while (*list != NULL) {
360 (*list) = (*list)->next;
361 free(tmp->sensor_name);
368 * Get reference temperature value
370 * First initially uc_get_rate_by_name is tried. At the startup due to
371 * nondeterministic order the temperature may not be read yet (then it fails and
372 * first measurment gives only absolute air pressure reading which is
373 * acceptable). Once it succedes (should be second measurement at the latest) we
374 * use average of few last readings from uc_get_history_by_name. It may take few
375 * readings to start filling so again we use uc_get_rate_by_name as a fallback.
376 * The idea is to use basic "noise" filtering (history averaging) across all the
377 * values which given sensor provides (up to given depth). Then we get minimum
380 * @param result where the result is stored. When not available NAN is stored.
382 * @return Zero when successful
384 static int get_reference_temperature(double *result) {
385 temperature_list_t *list = temp_list;
387 gauge_t *values = NULL; /**< rate values */
388 size_t values_num = 0; /**< number of rate values */
390 gauge_t values_history[REF_TEMP_AVG_NUM];
392 double avg_sum; /**< Value sum for computing average */
393 int avg_num; /**< Number of values for computing average */
394 double average; /**< Resulting value average */
398 while (list != NULL) {
402 /* First time need to read current rate to learn how many values are
403 there (typically for temperature it would be just one). We do not expect
404 dynamic changing of number of temperarure values in runtime yet (are
405 there any such cases?). */
406 if (!list->initialized) {
407 if (uc_get_rate_by_name(list->sensor_name, &values, &values_num)) {
409 "barometer: get_reference_temperature - rate \"%s\" not found yet",
415 DEBUG("barometer: get_reference_temperature - initialize \"%s\", %" PRIsz
417 list->sensor_name, values_num);
419 list->initialized = 1;
420 list->num_values = values_num;
422 for (size_t i = 0; i < values_num; ++i) {
423 DEBUG("barometer: get_reference_temperature - rate %" PRIsz ": %lf **",
425 if (!isnan(values[i])) {
426 avg_sum += values[i];
434 /* It is OK to get here the first time as well, in the worst case
435 the history will full of NANs. */
436 if (uc_get_history_by_name(list->sensor_name, values_history,
437 REF_TEMP_AVG_NUM, list->num_values)) {
438 ERROR("barometer: get_reference_temperature - history \"%s\" lost",
440 list->initialized = 0;
441 list->num_values = 0;
446 for (size_t i = 0; i < REF_TEMP_AVG_NUM * list->num_values; ++i) {
447 DEBUG("barometer: get_reference_temperature - history %" PRIsz ": %lf", i,
449 if (!isnan(values_history[i])) {
450 avg_sum += values_history[i];
455 if (avg_num == 0) /* still no history? fallback to current */
457 if (uc_get_rate_by_name(list->sensor_name, &values, &values_num)) {
458 ERROR("barometer: get_reference_temperature - rate \"%s\" lost",
460 list->initialized = 0;
461 list->num_values = 0;
466 for (size_t i = 0; i < values_num; ++i) {
467 DEBUG("barometer: get_reference_temperature - rate last %" PRIsz
470 if (!isnan(values[i])) {
471 avg_sum += values[i];
480 ERROR("barometer: get_reference_temperature - could not read \"%s\"",
482 list->initialized = 0;
483 list->num_values = 0;
485 average = avg_sum / (double)avg_num;
488 else if (*result > average)
492 } /* while sensor list */
494 if (*result == NAN) {
495 ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
498 DEBUG("barometer: get_reference_temperature - temp is %lf", *result);
502 /* ------------------------ MPL115 access ------------------------ */
505 * Detect presence of a MPL115 pressure sensor.
507 * Unfortunately there seems to be no ID register so we just try to read first
508 * conversion coefficient from device at MPL115 address and hope it is really
509 * MPL115. We should use this check as the last resort (which would be the
511 * case anyway since MPL115 is the least accurate sensor).
512 * As a sideeffect will leave set I2C slave address.
514 * @return 1 if MPL115, 0 otherwise
516 static int MPL115_detect(void) {
520 if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0) {
521 ERROR("barometer: MPL115_detect problem setting i2c slave address to "
523 MPL115_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf)));
527 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS);
529 DEBUG("barometer: MPL115_detect - positive detection");
533 DEBUG("barometer: MPL115_detect - negative detection");
538 * Read the MPL115 sensor conversion coefficients.
540 * These are (device specific) constants so we can read them just once.
542 * @return Zero when successful
544 static int MPL115_read_coeffs(void) {
545 uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = {0};
548 int8_t sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
549 int8_t sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
550 int16_t sia0, sib1, sib2, sic12, sic11, sic22;
554 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL115_ADDR_COEFFS,
555 STATIC_ARRAY_SIZE(mpl115_coeffs),
558 ERROR("barometer: MPL115_read_coeffs - problem reading data: %s",
559 sstrerror(errno, errbuf, sizeof(errbuf)));
563 /* Using perhaps less elegant/efficient code, but more readable. */
564 /* a0: 16total 1sign 12int 4fract 0pad */
565 sia0MSB = mpl115_coeffs[0];
566 sia0LSB = mpl115_coeffs[1];
567 sia0 = (int16_t)sia0MSB << 8; /* s16 type, Shift to MSB */
568 sia0 += (int16_t)sia0LSB & 0x00FF; /* Add LSB to 16bit number */
569 mpl115_coeffA0 = (double)(sia0);
570 mpl115_coeffA0 /= 8.0; /* 3 fract bits */
572 /* b1: 16total 1sign 2int 13fract 0pad */
573 sib1MSB = mpl115_coeffs[2];
574 sib1LSB = mpl115_coeffs[3];
575 sib1 = sib1MSB << 8; /* Shift to MSB */
576 sib1 += sib1LSB & 0x00FF; /* Add LSB to 16bit number */
577 mpl115_coeffB1 = (double)(sib1);
578 mpl115_coeffB1 /= 8192.0; /* 13 fract */
580 /* b2: 16total 1sign 1int 14fract 0pad */
581 sib2MSB = mpl115_coeffs[4];
582 sib2LSB = mpl115_coeffs[5];
583 sib2 = sib2MSB << 8; /* Shift to MSB */
584 sib2 += sib2LSB & 0x00FF; /* Add LSB to 16bit number */
585 mpl115_coeffB2 = (double)(sib2);
586 mpl115_coeffB2 /= 16384.0; /* 14 fract */
588 /* c12: 14total 1sign 0int 13fract 9pad */
589 sic12MSB = mpl115_coeffs[6];
590 sic12LSB = mpl115_coeffs[7];
591 sic12 = sic12MSB << 8; /* Shift to MSB only by 8 for MSB */
592 sic12 += sic12LSB & 0x00FF;
593 mpl115_coeffC12 = (double)(sic12);
594 mpl115_coeffC12 /= 4.0; /* 16-14=2 */
595 mpl115_coeffC12 /= 4194304.0; /* 13+9=22 fract */
597 /* c11: 11total 1sign 0int 11fract 11pad */
598 sic11MSB = mpl115_coeffs[8];
599 sic11LSB = mpl115_coeffs[9];
600 sic11 = sic11MSB << 8; /* Shift to MSB only by 8 for MSB */
601 sic11 += sic11LSB & 0x00FF;
602 mpl115_coeffC11 = (double)(sic11);
603 mpl115_coeffC11 /= 32.0; /* 16-11=5 */
604 mpl115_coeffC11 /= 4194304.0; /* 11+11=22 fract */
606 /* c12: 11total 1sign 0int 10fract 15pad */
607 sic22MSB = mpl115_coeffs[10];
608 sic22LSB = mpl115_coeffs[11];
609 sic22 = sic22MSB << 8; /* Shift to MSB only by 8 for MSB */
610 sic22 += sic22LSB & 0x00FF;
611 mpl115_coeffC22 = (double)(sic22);
612 mpl115_coeffC22 /= 32.0; // 16-11=5
613 mpl115_coeffC22 /= 33554432.0; /* 10+15=25 fract */
615 DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, "
617 mpl115_coeffA0, mpl115_coeffB1, mpl115_coeffB2, mpl115_coeffC12,
618 mpl115_coeffC11, mpl115_coeffC22);
623 * Convert raw adc values to real data using the sensor coefficients.
625 * @param adc_pressure adc pressure value to be converted
626 * @param adc_temp adc temperature value to be converted
627 * @param pressure computed real pressure
628 * @param temperature computed real temperature
630 static void MPL115_convert_adc_to_real(double adc_pressure, double adc_temp,
631 double *pressure, double *temperature) {
633 Pcomp = mpl115_coeffA0 +
634 (mpl115_coeffB1 + mpl115_coeffC11 * adc_pressure +
635 mpl115_coeffC12 * adc_temp) *
637 (mpl115_coeffB2 + mpl115_coeffC22 * adc_temp) * adc_temp;
639 *pressure = ((1150.0 - 500.0) * Pcomp / 1023.0) + 500.0;
640 *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
641 DEBUG("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C", *pressure,
646 * Read sensor averegaed measurements
648 * @param pressure averaged measured pressure
649 * @param temperature averaged measured temperature
651 * @return Zero when successful
653 static int MPL115_read_averaged(double *pressure, double *temperature) {
654 uint8_t mpl115_conv[MPL115_NUM_CONV] = {0};
658 int conv_temperature;
660 double adc_temperature;
666 /* start conversion of both temp and presure */
667 retries = MPL115_CONVERSION_RETRIES;
668 while (retries > 0) {
669 /* write 1 to start conversion */
670 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL115_CMD_CONVERT_BOTH, 0x01);
676 ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, "
677 "will retry at most %d more times",
678 sstrerror(errno, errbuf, sizeof(errbuf)), retries);
680 ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, "
681 "too many failed retries",
682 sstrerror(errno, errbuf, sizeof(errbuf)));
687 usleep(10000); /* wait 10ms for the conversion */
689 retries = MPL115_CONVERSION_RETRIES;
690 while (retries > 0) {
691 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL115_ADDR_CONV,
692 STATIC_ARRAY_SIZE(mpl115_conv),
699 ERROR("barometer: MPL115_read_averaged - reading conversion: %s, "
700 "will retry at most %d more times",
701 sstrerror(errno, errbuf, sizeof(errbuf)), retries);
703 ERROR("barometer: MPL115_read_averaged - reading conversion: %s, "
704 "too many failed retries",
705 sstrerror(errno, errbuf, sizeof(errbuf)));
710 conv_pressure = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
711 conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
712 DEBUG("barometer: MPL115_read_averaged, raw pressure ADC value = %d, "
713 "raw temperature ADC value = %d",
714 conv_pressure, conv_temperature);
716 adc_pressure = averaging_add_sample(&pressure_averaging, conv_pressure);
718 averaging_add_sample(&temperature_averaging, conv_temperature);
720 MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure,
723 DEBUG("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / "
724 "temperature = %lf, "
725 "real pressure = %lf hPa / temperature = %lf C",
726 adc_pressure, adc_temperature, *pressure, *temperature);
731 /* ------------------------ MPL3115 access ------------------------ */
734 * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
736 * As a sideeffect will leave set I2C slave address.
738 * @return 1 if MPL3115, 0 otherwise
740 static int MPL3115_detect(void) {
744 if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0) {
745 ERROR("barometer: MPL3115_detect problem setting i2c slave address to "
747 MPL3115_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf)));
751 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
752 if (res == MPL3115_WHO_AM_I_RESP) {
753 DEBUG("barometer: MPL3115_detect - positive detection");
757 DEBUG("barometer: MPL3115_detect - negative detection");
762 * Adjusts oversampling to values supported by MPL3115
764 * MPL3115 supports only power of 2 in the range 1 to 128.
766 static void MPL3115_adjust_oversampling(void) {
769 if (config_oversample > 100) {
771 mpl3115_oversample = MPL3115_CTRL_REG1_OST_128;
772 } else if (config_oversample > 48) {
774 mpl3115_oversample = MPL3115_CTRL_REG1_OST_64;
775 } else if (config_oversample > 24) {
777 mpl3115_oversample = MPL3115_CTRL_REG1_OST_32;
778 } else if (config_oversample > 12) {
780 mpl3115_oversample = MPL3115_CTRL_REG1_OST_16;
781 } else if (config_oversample > 6) {
783 mpl3115_oversample = MPL3115_CTRL_REG1_OST_8;
784 } else if (config_oversample > 3) {
786 mpl3115_oversample = MPL3115_CTRL_REG1_OST_4;
787 } else if (config_oversample > 1) {
789 mpl3115_oversample = MPL3115_CTRL_REG1_OST_2;
792 mpl3115_oversample = MPL3115_CTRL_REG1_OST_1;
795 DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from "
797 config_oversample, new_val);
798 config_oversample = new_val;
802 * Read sensor averaged measurements
804 * @param pressure averaged measured pressure
805 * @param temperature averaged measured temperature
807 * @return Zero when successful
809 static int MPL3115_read(double *pressure, double *temperature) {
812 __u8 data[MPL3115_NUM_CONV_VALS];
813 long int tmp_value = 0;
816 /* Set Active - activate the device from standby */
817 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
819 ERROR("barometer: MPL3115_read - cannot read CTRL_REG1: %s",
820 sstrerror(errno, errbuf, sizeof(errbuf)));
824 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
825 ctrl | MPL3115_CTRL_REG1_SBYB);
827 ERROR("barometer: MPL3115_read - problem activating: %s",
828 sstrerror(errno, errbuf, sizeof(errbuf)));
832 /* base sleep is 5ms x OST */
833 usleep(5000 * config_oversample);
835 /* check the flags/status if ready */
836 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
838 ERROR("barometer: MPL3115_read - cannot read status register: %s",
839 sstrerror(errno, errbuf, sizeof(errbuf)));
843 while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR) {
844 /* try some extra sleep... */
847 /* ... and repeat the check. The conversion has to finish sooner or later.
849 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
851 ERROR("barometer: MPL3115_read - cannot read status register: %s",
852 sstrerror(errno, errbuf, sizeof(errbuf)));
857 /* Now read all the data in one block. There is address autoincrement. */
858 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL3115_REG_OUT_P_MSB,
859 MPL3115_NUM_CONV_VALS, data);
861 ERROR("barometer: MPL3115_read - cannot read data registers: %s",
862 sstrerror(errno, errbuf, sizeof(errbuf)));
866 tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
867 *pressure = ((double)tmp_value) / 4.0 / 16.0 / 100.0;
868 DEBUG("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
870 if (data[3] > 0x7F) {
871 data[3] = ~data[3] + 1;
872 *temperature = data[3];
873 *temperature = -*temperature;
875 *temperature = data[3];
878 *temperature += (double)(data[4]) / 256.0;
879 DEBUG("barometer: MPL3115_read - temperature = %lf C", *temperature);
885 * Initialize MPL3115 for barometeric measurements
887 * @return 0 if successful
889 static int MPL3115_init_sensor(void) {
894 /* Reset the sensor. It will reset immediately without ACKing */
895 /* the transaction, so no error handling here. */
896 i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
897 MPL3115_CTRL_REG1_RST);
899 /* wait some time for the reset to finish */
902 /* now it should be in standby already so we can go and configure it */
904 /* Set temperature offset. */
905 /* result = ADCtemp + offset [C] */
906 offset = (__s8)(config_temp_offset * 16.0);
907 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset);
909 ERROR("barometer: MPL3115_init_sensor - problem setting temp offset: %s",
910 sstrerror(errno, errbuf, sizeof(errbuf)));
914 /* Set pressure offset. */
915 /* result = ADCpress + offset [hPa] */
916 offset = (__s8)(config_press_offset * 100.0 / 4.0);
917 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset);
920 "barometer: MPL3115_init_sensor - problem setting pressure offset: %s",
921 sstrerror(errno, errbuf, sizeof(errbuf)));
925 /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
926 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_PT_DATA_CFG,
927 MPL3115_PT_DATA_DREM | MPL3115_PT_DATA_PDEF |
928 MPL3115_PT_DATA_TDEF);
930 ERROR("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s",
931 sstrerror(errno, errbuf, sizeof(errbuf)));
935 /* Set to barometer with an OSR */
936 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
939 ERROR("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
940 sstrerror(errno, errbuf, sizeof(errbuf)));
947 /* ------------------------ BMP085 access ------------------------ */
950 * Detect presence of a BMP085 pressure sensor by checking its ID register
952 * As a sideeffect will leave set I2C slave address.
954 * @return 1 if BMP085, 0 otherwise
956 static int BMP085_detect(void) {
960 if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0) {
961 ERROR("barometer: BMP085_detect - problem setting i2c slave address to "
963 BMP085_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf)));
967 res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG);
968 if (res == BMP085_CHIP_ID) {
969 DEBUG("barometer: BMP085_detect - positive detection");
972 res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION);
974 ERROR("barometer: BMP085_detect - problem checking chip version: %s",
975 sstrerror(errno, errbuf, sizeof(errbuf)));
978 DEBUG("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X",
979 res & 0x0f, (res & 0xf0) >> 4);
983 DEBUG("barometer: BMP085_detect - negative detection");
988 * Adjusts oversampling settings to values supported by BMP085
990 * BMP085 supports only 1,2,4 or 8 samples.
992 static void BMP085_adjust_oversampling(void) {
995 if (config_oversample > 6) /* 8 */
998 bmp085_oversampling = 3;
999 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3;
1000 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3;
1001 } else if (config_oversample > 3) /* 4 */
1004 bmp085_oversampling = 2;
1005 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2;
1006 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2;
1007 } else if (config_oversample > 1) /* 2 */
1010 bmp085_oversampling = 1;
1011 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1;
1012 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1;
1016 bmp085_oversampling = 0;
1017 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0;
1018 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0;
1021 DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from "
1023 config_oversample, new_val);
1024 config_oversample = new_val;
1028 * Read the BMP085 sensor conversion coefficients.
1030 * These are (device specific) constants so we can read them just once.
1032 * @return Zero when successful
1034 static int BMP085_read_coeffs(void) {
1036 __u8 coeffs[BMP085_NUM_COEFFS];
1039 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_COEFFS,
1040 BMP085_NUM_COEFFS, coeffs);
1042 ERROR("barometer: BMP085_read_coeffs - problem reading data: %s",
1043 sstrerror(errno, errbuf, sizeof(errbuf)));
1047 bmp085_AC1 = ((int16_t)coeffs[0] << 8) | (int16_t)coeffs[1];
1048 bmp085_AC2 = ((int16_t)coeffs[2] << 8) | (int16_t)coeffs[3];
1049 bmp085_AC3 = ((int16_t)coeffs[4] << 8) | (int16_t)coeffs[5];
1050 bmp085_AC4 = ((uint16_t)coeffs[6] << 8) | (uint16_t)coeffs[7];
1051 bmp085_AC5 = ((uint16_t)coeffs[8] << 8) | (uint16_t)coeffs[9];
1052 bmp085_AC6 = ((uint16_t)coeffs[10] << 8) | (uint16_t)coeffs[11];
1053 bmp085_B1 = ((int16_t)coeffs[12] << 8) | (int16_t)coeffs[13];
1054 bmp085_B2 = ((int16_t)coeffs[14] << 8) | (int16_t)coeffs[15];
1055 bmp085_MB = ((int16_t)coeffs[16] << 8) | (int16_t)coeffs[17];
1056 bmp085_MC = ((int16_t)coeffs[18] << 8) | (int16_t)coeffs[19];
1057 bmp085_MD = ((int16_t)coeffs[20] << 8) | (int16_t)coeffs[21];
1059 DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"
1060 " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d",
1061 bmp085_AC1, bmp085_AC2, bmp085_AC3, bmp085_AC4, bmp085_AC5, bmp085_AC6,
1062 bmp085_B1, bmp085_B2, bmp085_MB, bmp085_MC, bmp085_MD);
1068 * Convert raw BMP085 adc values to real data using the sensor coefficients.
1070 * @param adc_pressure adc pressure value to be converted
1071 * @param adc_temp adc temperature value to be converted
1072 * @param pressure computed real pressure
1073 * @param temperature computed real temperature
1075 static void BMP085_convert_adc_to_real(long adc_pressure, long adc_temperature,
1076 double *pressure, double *temperature)
1081 unsigned long B4, B7;
1086 /* calculate real temperature */
1087 X1 = ((adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15;
1088 X2 = (bmp085_MC << 11) / (X1 + bmp085_MD);
1093 *temperature = (double)T * 0.1;
1095 /* calculate real pressure */
1096 /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept
1101 X1 = ((bmp085_B2 * ((B6 * B6) >> 12)) >> 11);
1102 X2 = (((long)bmp085_AC2 * B6) >> 11);
1104 B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
1107 X1 = (((long)bmp085_AC3 * B6) >> 13);
1108 X2 = (bmp085_B1 * ((B6 * B6) >> 12)) >> 16;
1109 X3 = ((X1 + X2) + 2) >> 2;
1110 B4 = ((long)bmp085_AC4 * (unsigned long)(X3 + 32768)) >> 15;
1113 B7 = (unsigned long)(adc_pressure - B3) * (50000 >> bmp085_oversampling);
1114 if (B7 < 0x80000000) {
1119 X1 = (P >> 8) * (P >> 8);
1120 X1 = (X1 * 3038) >> 16;
1121 X2 = ((-7357) * P) >> 16;
1122 P = P + ((X1 + X2 + 3791) >> 4);
1124 *pressure = P / 100.0; // in [hPa]
1125 DEBUG("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C", *pressure,
1130 * Read compensated sensor measurements
1132 * @param pressure averaged measured pressure
1133 * @param temperature averaged measured temperature
1135 * @return Zero when successful
1137 static int BMP085_read(double *pressure, double *temperature) {
1142 long adc_temperature;
1146 /* start conversion of temperature */
1147 res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG,
1148 BMP085_CMD_CONVERT_TEMP);
1150 ERROR("barometer: BMP085_read - problem requesting temperature conversion: "
1152 sstrerror(errno, errbuf, sizeof(errbuf)));
1156 usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
1159 i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 2, measBuff);
1161 ERROR("barometer: BMP085_read - problem reading temperature data: %s",
1162 sstrerror(errno, errbuf, sizeof(errbuf)));
1166 adc_temperature = ((unsigned short)measBuff[0] << 8) + measBuff[1];
1169 res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG,
1170 bmp085_cmdCnvPress);
1172 ERROR("barometer: BMP085_read - problem requesting pressure conversion: %s",
1173 sstrerror(errno, errbuf, sizeof(errbuf)));
1177 usleep(bmp085_timeCnvPress); /* wait for the conversion */
1180 i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 3, measBuff);
1182 ERROR("barometer: BMP085_read - problem reading pressure data: %s",
1183 sstrerror(errno, errbuf, sizeof(errbuf)));
1187 adc_pressure = (long)((((ulong)measBuff[0] << 16) |
1188 ((ulong)measBuff[1] << 8) | (ulong)measBuff[2]) >>
1189 (8 - bmp085_oversampling));
1191 DEBUG("barometer: BMP085_read - raw pressure ADC value = %ld, "
1192 "raw temperature ADC value = %ld",
1193 adc_pressure, adc_temperature);
1195 BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure,
1201 /* ------------------------ Sensor detection ------------------------ */
1203 * Detect presence of a supported sensor.
1205 * As a sideeffect will leave set I2C slave address.
1206 * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
1207 * first sensor beeing found.
1209 * @return detected sensor type
1211 static enum Sensor_type detect_sensor_type(void) {
1212 if (BMP085_detect())
1213 return Sensor_BMP085;
1215 else if (MPL3115_detect())
1216 return Sensor_MPL3115;
1218 else if (MPL115_detect())
1219 return Sensor_MPL115;
1224 /* ------------------------ Common functionality ------------------------ */
1227 * Convert absolute pressure (in hPa) to mean sea level pressure
1229 * Implemented methods are:
1230 * - MSLP_NONE - no converions, returns absolute pressure
1232 * - MSLP_INTERNATIONAL - see
1233 * http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
1234 * Requires #config_altitude
1236 * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See
1237 * http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
1238 * Requires both #config_altitude and temperature reference(s).
1240 * @param abs_pressure absloute pressure to be converted
1242 * @return mean sea level pressure if successful, NAN otherwise
1244 static double abs_to_mean_sea_level_pressure(double abs_pressure) {
1249 if (config_normalize >= MSLP_DEU_WETT) {
1250 result = get_reference_temperature(&temp);
1256 switch (config_normalize) {
1258 mean = abs_pressure;
1261 case MSLP_INTERNATIONAL:
1262 mean = abs_pressure / pow(1.0 - 0.0065 * config_altitude / 288.15,
1263 9.80665 * 0.0289644 / (8.31447 * 0.0065));
1266 case MSLP_DEU_WETT: {
1267 double E; /* humidity */
1270 E = 5.6402 * (-0.0916 + exp(0.06 * temp));
1272 E = 18.2194 * (1.0463 - exp(-0.0666 * temp));
1274 (287.05 * (temp + 273.15 + 0.12 * E + 0.0065 * config_altitude / 2)) *
1276 mean = abs_pressure * exp(x);
1281 "barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d",
1283 mean = abs_pressure;
1287 DEBUG("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, "
1288 "method = %d, meanPressure = %lf hPa",
1289 abs_pressure, config_normalize, mean);
1294 /* ------------------------ main plugin callbacks ------------------------ */
1297 * Main plugin configuration callback (using simple config)
1299 * @param key configuration key we should process
1300 * @param value configuration value we should process
1302 * @return Zero when successful.
1304 static int collectd_barometer_config(const char *key, const char *value) {
1305 DEBUG("barometer: collectd_barometer_config");
1307 if (strcasecmp(key, "Device") == 0) {
1308 sfree(config_device);
1309 config_device = strdup(value);
1310 } else if (strcasecmp(key, "Oversampling") == 0) {
1311 int oversampling_tmp = atoi(value);
1312 if (oversampling_tmp < 1 || oversampling_tmp > 1024) {
1313 WARNING("barometer: collectd_barometer_config: invalid oversampling: %d."
1314 " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for "
1315 "MPL3115) or 1 to 8 (for BMP085).",
1319 config_oversample = oversampling_tmp;
1320 } else if (strcasecmp(key, "Altitude") == 0) {
1321 config_altitude = atof(value);
1322 } else if (strcasecmp(key, "Normalization") == 0) {
1323 int normalize_tmp = atoi(value);
1324 if (normalize_tmp < 0 || normalize_tmp > 2) {
1325 WARNING("barometer: collectd_barometer_config: invalid normalization: %d",
1329 config_normalize = normalize_tmp;
1330 } else if (strcasecmp(key, "TemperatureSensor") == 0) {
1331 if (temp_list_add(temp_list, value)) {
1334 } else if (strcasecmp(key, "PressureOffset") == 0) {
1335 config_press_offset = atof(value);
1336 } else if (strcasecmp(key, "TemperatureOffset") == 0) {
1337 config_temp_offset = atof(value);
1346 * Shutdown callback.
1348 * Close I2C and delete all the buffers.
1350 * @return Zero when successful (at the moment the only possible outcome)
1352 static int collectd_barometer_shutdown(void) {
1353 DEBUG("barometer: collectd_barometer_shutdown");
1355 if (sensor_type == Sensor_MPL115) {
1356 averaging_delete(&pressure_averaging);
1357 averaging_delete(&temperature_averaging);
1359 temp_list_delete(&temp_list);
1362 if (i2c_bus_fd > 0) {
1365 sfree(config_device);
1372 * Plugin read callback for MPL115.
1374 * Dispatching will create values:
1375 * - <hostname>/barometer-mpl115/pressure-normalized
1376 * - <hostname>/barometer-mpl115/pressure-absolute
1377 * - <hostname>/barometer-mpl115/temperature
1379 * @return Zero when successful.
1381 static int MPL115_collectd_barometer_read(void) {
1384 double pressure = 0.0;
1385 double temperature = 0.0;
1386 double norm_pressure = 0.0;
1388 value_list_t vl = VALUE_LIST_INIT;
1391 DEBUG("barometer: MPL115_collectd_barometer_read");
1397 /* Rather than delaying init, we will intitialize during first read. This
1398 way at least we have a better chance to have the reference temperature
1399 already available. */
1400 if (!avg_initialized) {
1401 for (int i = 0; i < config_oversample - 1; ++i) {
1402 result = MPL115_read_averaged(&pressure, &temperature);
1404 ERROR("barometer: MPL115_collectd_barometer_read - mpl115 read, "
1405 "ignored during init");
1407 DEBUG("barometer: MPL115_collectd_barometer_read - init %d / %d", i + 1,
1408 config_oversample - 1);
1411 avg_initialized = 1;
1414 result = MPL115_read_averaged(&pressure, &temperature);
1418 norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1420 sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1421 sstrncpy(vl.plugin_instance, "mpl115", sizeof(vl.plugin_instance));
1426 /* dispatch normalized air pressure */
1427 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1428 sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1429 values[0].gauge = norm_pressure;
1430 plugin_dispatch_values(&vl);
1432 /* dispatch absolute air pressure */
1433 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1434 sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1435 values[0].gauge = pressure;
1436 plugin_dispatch_values(&vl);
1438 /* dispatch sensor temperature */
1439 sstrncpy(vl.type, "temperature", sizeof(vl.type));
1440 sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1441 values[0].gauge = temperature;
1442 plugin_dispatch_values(&vl);
1448 * Plugin read callback for MPL3115.
1450 * Dispatching will create values:
1451 * - <hostname>/barometer-mpl3115/pressure-normalized
1452 * - <hostname>/barometer-mpl3115/pressure-absolute
1453 * - <hostname>/barometer-mpl3115/temperature
1455 * @return Zero when successful.
1457 static int MPL3115_collectd_barometer_read(void) {
1460 double pressure = 0.0;
1461 double temperature = 0.0;
1462 double norm_pressure = 0.0;
1464 value_list_t vl = VALUE_LIST_INIT;
1467 DEBUG("barometer: MPL3115_collectd_barometer_read");
1473 result = MPL3115_read(&pressure, &temperature);
1477 norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1479 sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1480 sstrncpy(vl.plugin_instance, "mpl3115", sizeof(vl.plugin_instance));
1485 /* dispatch normalized air pressure */
1486 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1487 sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1488 values[0].gauge = norm_pressure;
1489 plugin_dispatch_values(&vl);
1491 /* dispatch absolute air pressure */
1492 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1493 sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1494 values[0].gauge = pressure;
1495 plugin_dispatch_values(&vl);
1497 /* dispatch sensor temperature */
1498 sstrncpy(vl.type, "temperature", sizeof(vl.type));
1499 sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1500 values[0].gauge = temperature;
1501 plugin_dispatch_values(&vl);
1507 * Plugin read callback for BMP085.
1509 * Dispatching will create values:
1510 * - <hostname>/barometer-bmp085/pressure-normalized
1511 * - <hostname>/barometer-bmp085/pressure-absolute
1512 * - <hostname>/barometer-bmp085/temperature
1514 * @return Zero when successful.
1516 static int BMP085_collectd_barometer_read(void) {
1519 double pressure = 0.0;
1520 double temperature = 0.0;
1521 double norm_pressure = 0.0;
1523 value_list_t vl = VALUE_LIST_INIT;
1526 DEBUG("barometer: BMP085_collectd_barometer_read");
1532 result = BMP085_read(&pressure, &temperature);
1536 norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1538 sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1539 sstrncpy(vl.plugin_instance, "bmp085", sizeof(vl.plugin_instance));
1544 /* dispatch normalized air pressure */
1545 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1546 sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1547 values[0].gauge = norm_pressure;
1548 plugin_dispatch_values(&vl);
1550 /* dispatch absolute air pressure */
1551 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1552 sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1553 values[0].gauge = pressure;
1554 plugin_dispatch_values(&vl);
1556 /* dispatch sensor temperature */
1557 sstrncpy(vl.type, "temperature", sizeof(vl.type));
1558 sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1559 values[0].gauge = temperature;
1560 plugin_dispatch_values(&vl);
1566 * Initialization callback
1568 * Check config, initialize I2C bus access, conversion coefficients and
1572 * @return Zero when successful.
1574 static int collectd_barometer_init(void) {
1577 DEBUG("barometer: collectd_barometer_init");
1579 if (config_device == NULL) {
1580 ERROR("barometer: collectd_barometer_init I2C bus device not configured");
1584 if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude)) {
1585 ERROR("barometer: collectd_barometer_init no altitude configured "
1586 "for mean sea level pressure normalization.");
1590 if (config_normalize == MSLP_DEU_WETT && temp_list == NULL) {
1591 ERROR("barometer: collectd_barometer_init no temperature reference "
1592 "configured for mean sea level pressure normalization.");
1596 i2c_bus_fd = open(config_device, O_RDWR);
1597 if (i2c_bus_fd < 0) {
1598 ERROR("barometer: collectd_barometer_init problem opening I2C bus device "
1599 "\"%s\": %s (is loaded mod i2c-dev?)",
1600 config_device, sstrerror(errno, errbuf, sizeof(errbuf)));
1604 /* detect sensor type - this will also set slave address */
1605 sensor_type = detect_sensor_type();
1607 /* init correct sensor type */
1608 switch (sensor_type) {
1610 case Sensor_MPL3115: {
1611 MPL3115_adjust_oversampling();
1613 if (MPL3115_init_sensor())
1616 plugin_register_read("barometer", MPL3115_collectd_barometer_read);
1620 case Sensor_MPL115: {
1621 if (averaging_create(&pressure_averaging, config_oversample)) {
1623 "barometer: collectd_barometer_init pressure averaging init failed");
1627 if (averaging_create(&temperature_averaging, config_oversample)) {
1628 ERROR("barometer: collectd_barometer_init temperature averaging init "
1633 if (MPL115_read_coeffs() < 0)
1636 plugin_register_read("barometer", MPL115_collectd_barometer_read);
1640 case Sensor_BMP085: {
1641 BMP085_adjust_oversampling();
1643 if (BMP085_read_coeffs() < 0)
1646 plugin_register_read("barometer", BMP085_collectd_barometer_read);
1649 /* anything else -> error */
1651 ERROR("barometer: collectd_barometer_init - no supported sensor found");
1659 /* ------------------------ plugin register / entry point
1660 * ------------------------ */
1663 * Plugin "entry" - register all callback.
1666 void module_register(void) {
1667 plugin_register_config("barometer", collectd_barometer_config, config_keys,
1669 plugin_register_init("barometer", collectd_barometer_init);
1670 plugin_register_shutdown("barometer", collectd_barometer_shutdown);