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>
31 #include <i2c/smbus.h>
35 #include <sys/ioctl.h>
38 /* ------------ MPL115 defines ------------ */
39 /* I2C address of the MPL115 sensor */
40 #define MPL115_I2C_ADDRESS 0x60
42 /* register addresses */
43 #define MPL115_ADDR_CONV 0x00
44 #define MPL115_ADDR_COEFFS 0x04
47 #define MPL115_NUM_CONV 4
48 #define MPL115_NUM_COEFFS 12
50 /* commands / addresses */
51 #define MPL115_CMD_CONVERT_PRESS 0x10
52 #define MPL115_CMD_CONVERT_TEMP 0x11
53 #define MPL115_CMD_CONVERT_BOTH 0x12
55 #define MPL115_CONVERSION_RETRIES 5
57 /* ------------ MPL3115 defines ------------ */
58 /* MPL3115 I2C address */
59 #define MPL3115_I2C_ADDRESS 0x60
61 /* register addresses (only the interesting ones) */
62 #define MPL3115_REG_STATUS 0x00
63 #define MPL3115_REG_OUT_P_MSB 0x01
64 #define MPL3115_REG_OUT_P_CSB 0x02
65 #define MPL3115_REG_OUT_P_LSB 0x03
66 #define MPL3115_REG_OUT_T_MSB 0x04
67 #define MPL3115_REG_OUT_T_LSB 0x05
68 #define MPL3115_REG_DR_STATUS 0x06
69 #define MPL3115_REG_WHO_AM_I 0x0C
70 #define MPL3115_REG_SYSMOD 0x11
71 #define MPL3115_REG_PT_DATA_CFG 0x13
72 #define MPL3115_REG_BAR_IN_MSB 0x14
73 #define MPL3115_REG_BAR_IN_LSB 0x15
74 #define MPL3115_REG_CTRL_REG1 0x26
75 #define MPL3115_REG_CTRL_REG2 0x27
76 #define MPL3115_REG_CTRL_REG3 0x28
77 #define MPL3115_REG_CTRL_REG4 0x29
78 #define MPL3115_REG_CTRL_REG5 0x2A
79 #define MPL3115_REG_OFF_P 0x2B
80 #define MPL3115_REG_OFF_T 0x2C
81 #define MPL3115_REG_OFF_H 0x2D
83 /* Register values, masks */
84 #define MPL3115_WHO_AM_I_RESP 0xC4
86 #define MPL3115_PT_DATA_DREM 0x04
87 #define MPL3115_PT_DATA_PDEF 0x02
88 #define MPL3115_PT_DATA_TDEF 0x01
90 #define MPL3115_DR_STATUS_TDR 0x02
91 #define MPL3115_DR_STATUS_PDR 0x04
92 #define MPL3115_DR_STATUS_PTDR 0x08
93 #define MPL3115_DR_STATUS_DR \
94 (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
96 #define MPL3115_DR_STATUS_TOW 0x20
97 #define MPL3115_DR_STATUS_POW 0x40
98 #define MPL3115_DR_STATUS_PTOW 0x80
100 #define MPL3115_CTRL_REG1_ALT 0x80
101 #define MPL3115_CTRL_REG1_RAW 0x40
102 #define MPL3115_CTRL_REG1_OST_MASK 0x38
103 #define MPL3115_CTRL_REG1_OST_1 0x00
104 #define MPL3115_CTRL_REG1_OST_2 0x08
105 #define MPL3115_CTRL_REG1_OST_4 0x10
106 #define MPL3115_CTRL_REG1_OST_8 0x18
107 #define MPL3115_CTRL_REG1_OST_16 0x20
108 #define MPL3115_CTRL_REG1_OST_32 0x28
109 #define MPL3115_CTRL_REG1_OST_64 0x30
110 #define MPL3115_CTRL_REG1_OST_128 0x38
111 #define MPL3115_CTRL_REG1_RST 0x04
112 #define MPL3115_CTRL_REG1_OST 0x02
113 #define MPL3115_CTRL_REG1_SBYB 0x01
114 #define MPL3115_CTRL_REG1_SBYB_MASK 0xFE
116 #define MPL3115_NUM_CONV_VALS 5
118 /* ------------ BMP085 defines ------------ */
119 /* I2C address of the BMP085 sensor */
120 #define BMP085_I2C_ADDRESS 0x77
122 /* register addresses */
123 #define BMP085_ADDR_ID_REG 0xD0
124 #define BMP085_ADDR_VERSION 0xD1
126 #define BMP085_ADDR_CONV 0xF6
128 #define BMP085_ADDR_CTRL_REG 0xF4
129 #define BMP085_ADDR_COEFFS 0xAA
132 #define BMP085_NUM_COEFFS 22
134 /* commands, values */
135 #define BMP085_CHIP_ID 0x55
137 #define BMP085_CMD_CONVERT_TEMP 0x2E
139 #define BMP085_CMD_CONVERT_PRESS_0 0x34
140 #define BMP085_CMD_CONVERT_PRESS_1 0x74
141 #define BMP085_CMD_CONVERT_PRESS_2 0xB4
142 #define BMP085_CMD_CONVERT_PRESS_3 0xF4
145 #define BMP085_TIME_CNV_TEMP 4500
147 #define BMP085_TIME_CNV_PRESS_0 4500
148 #define BMP085_TIME_CNV_PRESS_1 7500
149 #define BMP085_TIME_CNV_PRESS_2 13500
150 #define BMP085_TIME_CNV_PRESS_3 25500
152 /* ------------ Normalization ------------ */
153 /* Mean sea level pressure normalization methods */
155 #define MSLP_INTERNATIONAL 1
156 #define MSLP_DEU_WETT 2
158 /** Temperature reference history depth for averaging. See
159 * #get_reference_temperature */
160 #define REF_TEMP_AVG_NUM 5
162 /* ------------------------------------------ */
164 /** Supported sensor types */
172 static const char *config_keys[] = {
175 "PressureOffset", /**< only for MPL3115 */
176 "TemperatureOffset", /**< only for MPL3115 */
179 "TemperatureSensor"};
181 static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
183 static char *config_device; /**< I2C bus device */
184 static int config_oversample = 1; /**< averaging window */
186 static double config_press_offset; /**< pressure offset */
187 static double config_temp_offset; /**< temperature offset */
189 static double config_altitude = NAN; /**< altitude */
190 static int config_normalize; /**< normalization method */
192 static bool configured; /**< the whole plugin config status */
194 static int i2c_bus_fd = -1; /**< I2C bus device FD */
196 static enum Sensor_type sensor_type =
197 Sensor_none; /**< detected/used sensor type */
199 static __s32 mpl3115_oversample; /**< MPL3115 CTRL1 oversample setting */
201 // BMP085 configuration
202 static unsigned bmp085_oversampling; /**< BMP085 oversampling (0-3) */
204 bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */
205 static __u8 bmp085_cmdCnvPress; /**< BMP085 pressure conversion command */
207 /* MPL115 conversion coefficients */
208 static double mpl115_coeffA0;
209 static double mpl115_coeffB1;
210 static double mpl115_coeffB2;
211 static double mpl115_coeffC12;
212 static double mpl115_coeffC11;
213 static double mpl115_coeffC22;
215 /* BMP085 conversion coefficients */
216 static short bmp085_AC1;
217 static short bmp085_AC2;
218 static short bmp085_AC3;
219 static unsigned short bmp085_AC4;
220 static unsigned short bmp085_AC5;
221 static unsigned short bmp085_AC6;
222 static short bmp085_B1;
223 static short bmp085_B2;
224 static short bmp085_MB;
225 static short bmp085_MC;
226 static short bmp085_MD;
228 /* ------------------------ averaging ring buffer ------------------------ */
229 /* Used only for MPL115. MPL3115 supports real oversampling in the device so */
230 /* no need for any postprocessing. */
232 static bool avg_initialized; /**< already initialized by real values */
234 typedef struct averaging_s {
235 long int *ring_buffer;
236 int ring_buffer_size;
237 long int ring_buffer_sum;
238 int ring_buffer_head;
241 static averaging_t pressure_averaging;
242 static averaging_t temperature_averaging;
245 * Create / allocate averaging buffer
247 * The buffer is initialized with zeros.
249 * @param avg pointer to ring buffer to be allocated
250 * @param size requested buffer size
252 * @return Zero when successful
254 static int averaging_create(averaging_t *avg, int size) {
255 avg->ring_buffer = calloc((size_t)size, sizeof(*avg->ring_buffer));
256 if (avg->ring_buffer == NULL) {
257 ERROR("barometer: averaging_create - ring buffer allocation of size %d "
263 avg->ring_buffer_size = size;
264 avg->ring_buffer_sum = 0L;
265 avg->ring_buffer_head = 0;
271 * Delete / free existing averaging buffer
273 * @param avg pointer to the ring buffer to be deleted
275 static void averaging_delete(averaging_t *avg) {
276 if (avg->ring_buffer != NULL) {
277 free(avg->ring_buffer);
278 avg->ring_buffer = NULL;
280 avg->ring_buffer_size = 0;
281 avg->ring_buffer_sum = 0L;
282 avg->ring_buffer_head = 0;
286 * Add new sample to the averaging buffer
288 * A new averaged value is returned. Note that till the buffer is full
289 * returned value is inaccurate as it is an average of real values and initial
292 * @param avg pointer to the ring buffer
293 * @param sample new sample value
295 * @return Averaged sample value
297 static double averaging_add_sample(averaging_t *avg, long int sample) {
300 avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head];
301 avg->ring_buffer[avg->ring_buffer_head] = sample;
302 avg->ring_buffer_head = (avg->ring_buffer_head + 1) % avg->ring_buffer_size;
303 result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
305 DEBUG("barometer: averaging_add_sample - added %ld, result = %lf", sample,
311 /* ------------------------ temperature refference ------------------------ */
314 * Linked list type of temperature sensor references
316 typedef struct temperature_list_s {
317 char *sensor_name; /**< sensor name/reference */
318 size_t num_values; /**< number of values (usually one) */
319 bool initialized; /**< sensor already provides data */
320 struct temperature_list_s *next; /**< next in the list */
321 } temperature_list_t;
323 static temperature_list_t *temp_list;
326 * Add new sensor to the temperature reference list
328 * @param list the list
329 * @param sensor reference name (as provided by the config file)
331 * @return Zero when successful
333 static int temp_list_add(temperature_list_t *list, const char *sensor) {
334 temperature_list_t *new_temp;
336 new_temp = malloc(sizeof(*new_temp));
337 if (new_temp == NULL)
340 new_temp->sensor_name = strdup(sensor);
341 new_temp->initialized = 0;
342 new_temp->num_values = 0;
343 if (new_temp->sensor_name == NULL) {
348 new_temp->next = temp_list;
349 temp_list = new_temp;
354 * Delete the whole temperature reference list
356 * @param list the list to be deleted
358 static void temp_list_delete(temperature_list_t **list) {
359 temperature_list_t *tmp;
361 while (*list != NULL) {
363 (*list) = (*list)->next;
364 free(tmp->sensor_name);
371 * Get reference temperature value
373 * First initially uc_get_rate_by_name is tried. At the startup due to
374 * nondeterministic order the temperature may not be read yet (then it fails and
375 * first measurment gives only absolute air pressure reading which is
376 * acceptable). Once it succedes (should be second measurement at the latest) we
377 * use average of few last readings from uc_get_history_by_name. It may take few
378 * readings to start filling so again we use uc_get_rate_by_name as a fallback.
379 * The idea is to use basic "noise" filtering (history averaging) across all the
380 * values which given sensor provides (up to given depth). Then we get minimum
383 * @param result where the result is stored. When not available NAN is stored.
385 * @return Zero when successful
387 static int get_reference_temperature(double *result) {
388 temperature_list_t *list = temp_list;
390 gauge_t *values = NULL; /**< rate values */
391 size_t values_num = 0; /**< number of rate values */
393 gauge_t values_history[REF_TEMP_AVG_NUM];
395 double avg_sum; /**< Value sum for computing average */
396 int avg_num; /**< Number of values for computing average */
397 double average; /**< Resulting value average */
401 while (list != NULL) {
405 /* First time need to read current rate to learn how many values are
406 there (typically for temperature it would be just one). We do not expect
407 dynamic changing of number of temperarure values in runtime yet (are
408 there any such cases?). */
409 if (!list->initialized) {
410 if (uc_get_rate_by_name(list->sensor_name, &values, &values_num)) {
412 "barometer: get_reference_temperature - rate \"%s\" not found yet",
418 DEBUG("barometer: get_reference_temperature - initialize \"%s\", %" PRIsz
420 list->sensor_name, values_num);
422 list->initialized = 1;
423 list->num_values = values_num;
425 for (size_t i = 0; i < values_num; ++i) {
426 DEBUG("barometer: get_reference_temperature - rate %" PRIsz ": %lf **",
428 if (!isnan(values[i])) {
429 avg_sum += values[i];
437 /* It is OK to get here the first time as well, in the worst case
438 the history will full of NANs. */
439 if (uc_get_history_by_name(list->sensor_name, values_history,
440 REF_TEMP_AVG_NUM, list->num_values)) {
441 ERROR("barometer: get_reference_temperature - history \"%s\" lost",
443 list->initialized = 0;
444 list->num_values = 0;
449 for (size_t i = 0; i < REF_TEMP_AVG_NUM * list->num_values; ++i) {
450 DEBUG("barometer: get_reference_temperature - history %" PRIsz ": %lf", i,
452 if (!isnan(values_history[i])) {
453 avg_sum += values_history[i];
458 if (avg_num == 0) /* still no history? fallback to current */
460 if (uc_get_rate_by_name(list->sensor_name, &values, &values_num)) {
461 ERROR("barometer: get_reference_temperature - rate \"%s\" lost",
463 list->initialized = 0;
464 list->num_values = 0;
469 for (size_t i = 0; i < values_num; ++i) {
470 DEBUG("barometer: get_reference_temperature - rate last %" PRIsz
473 if (!isnan(values[i])) {
474 avg_sum += values[i];
483 ERROR("barometer: get_reference_temperature - could not read \"%s\"",
485 list->initialized = 0;
486 list->num_values = 0;
488 average = avg_sum / (double)avg_num;
491 else if (*result > average)
495 } /* while sensor list */
497 if (*result == NAN) {
498 ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
501 DEBUG("barometer: get_reference_temperature - temp is %lf", *result);
505 /* ------------------------ MPL115 access ------------------------ */
508 * Detect presence of a MPL115 pressure sensor.
510 * Unfortunately there seems to be no ID register so we just try to read first
511 * conversion coefficient from device at MPL115 address and hope it is really
512 * MPL115. We should use this check as the last resort (which would be the
514 * case anyway since MPL115 is the least accurate sensor).
515 * As a sideeffect will leave set I2C slave address.
517 * @return 1 if MPL115, 0 otherwise
519 static int MPL115_detect(void) {
522 if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0) {
523 ERROR("barometer: MPL115_detect problem setting i2c slave address to "
525 MPL115_I2C_ADDRESS, STRERRNO);
529 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS);
531 DEBUG("barometer: MPL115_detect - positive detection");
535 DEBUG("barometer: MPL115_detect - negative detection");
540 * Read the MPL115 sensor conversion coefficients.
542 * These are (device specific) constants so we can read them just once.
544 * @return Zero when successful
546 static int MPL115_read_coeffs(void) {
547 uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = {0};
550 int8_t sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
551 int8_t sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
552 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", STRERRNO);
562 /* Using perhaps less elegant/efficient code, but more readable. */
563 /* a0: 16total 1sign 12int 4fract 0pad */
564 sia0MSB = mpl115_coeffs[0];
565 sia0LSB = mpl115_coeffs[1];
566 sia0 = (int16_t)sia0MSB << 8; /* s16 type, Shift to MSB */
567 sia0 += (int16_t)sia0LSB & 0x00FF; /* Add LSB to 16bit number */
568 mpl115_coeffA0 = (double)(sia0);
569 mpl115_coeffA0 /= 8.0; /* 3 fract bits */
571 /* b1: 16total 1sign 2int 13fract 0pad */
572 sib1MSB = mpl115_coeffs[2];
573 sib1LSB = mpl115_coeffs[3];
574 sib1 = sib1MSB << 8; /* Shift to MSB */
575 sib1 += sib1LSB & 0x00FF; /* Add LSB to 16bit number */
576 mpl115_coeffB1 = (double)(sib1);
577 mpl115_coeffB1 /= 8192.0; /* 13 fract */
579 /* b2: 16total 1sign 1int 14fract 0pad */
580 sib2MSB = mpl115_coeffs[4];
581 sib2LSB = mpl115_coeffs[5];
582 sib2 = sib2MSB << 8; /* Shift to MSB */
583 sib2 += sib2LSB & 0x00FF; /* Add LSB to 16bit number */
584 mpl115_coeffB2 = (double)(sib2);
585 mpl115_coeffB2 /= 16384.0; /* 14 fract */
587 /* c12: 14total 1sign 0int 13fract 9pad */
588 sic12MSB = mpl115_coeffs[6];
589 sic12LSB = mpl115_coeffs[7];
590 sic12 = sic12MSB << 8; /* Shift to MSB only by 8 for MSB */
591 sic12 += sic12LSB & 0x00FF;
592 mpl115_coeffC12 = (double)(sic12);
593 mpl115_coeffC12 /= 4.0; /* 16-14=2 */
594 mpl115_coeffC12 /= 4194304.0; /* 13+9=22 fract */
596 /* c11: 11total 1sign 0int 11fract 11pad */
597 sic11MSB = mpl115_coeffs[8];
598 sic11LSB = mpl115_coeffs[9];
599 sic11 = sic11MSB << 8; /* Shift to MSB only by 8 for MSB */
600 sic11 += sic11LSB & 0x00FF;
601 mpl115_coeffC11 = (double)(sic11);
602 mpl115_coeffC11 /= 32.0; /* 16-11=5 */
603 mpl115_coeffC11 /= 4194304.0; /* 11+11=22 fract */
605 /* c12: 11total 1sign 0int 10fract 15pad */
606 sic22MSB = mpl115_coeffs[10];
607 sic22LSB = mpl115_coeffs[11];
608 sic22 = sic22MSB << 8; /* Shift to MSB only by 8 for MSB */
609 sic22 += sic22LSB & 0x00FF;
610 mpl115_coeffC22 = (double)(sic22);
611 mpl115_coeffC22 /= 32.0; // 16-11=5
612 mpl115_coeffC22 /= 33554432.0; /* 10+15=25 fract */
614 DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, "
616 mpl115_coeffA0, mpl115_coeffB1, mpl115_coeffB2, mpl115_coeffC12,
617 mpl115_coeffC11, mpl115_coeffC22);
622 * Convert raw adc values to real data using the sensor coefficients.
624 * @param adc_pressure adc pressure value to be converted
625 * @param adc_temp adc temperature value to be converted
626 * @param pressure computed real pressure
627 * @param temperature computed real temperature
629 static void MPL115_convert_adc_to_real(double adc_pressure, double adc_temp,
630 double *pressure, double *temperature) {
632 Pcomp = mpl115_coeffA0 +
633 (mpl115_coeffB1 + mpl115_coeffC11 * adc_pressure +
634 mpl115_coeffC12 * adc_temp) *
636 (mpl115_coeffB2 + mpl115_coeffC22 * adc_temp) * adc_temp;
638 *pressure = ((1150.0 - 500.0) * Pcomp / 1023.0) + 500.0;
639 *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
640 DEBUG("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C", *pressure,
645 * Read sensor averegaed measurements
647 * @param pressure averaged measured pressure
648 * @param temperature averaged measured temperature
650 * @return Zero when successful
652 static int MPL115_read_averaged(double *pressure, double *temperature) {
653 uint8_t mpl115_conv[MPL115_NUM_CONV] = {0};
657 int conv_temperature;
659 double adc_temperature;
664 /* start conversion of both temp and presure */
665 retries = MPL115_CONVERSION_RETRIES;
666 while (retries > 0) {
667 /* write 1 to start conversion */
668 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL115_CMD_CONVERT_BOTH, 0x01);
674 ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, "
675 "will retry at most %d more times",
678 ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, "
679 "too many failed retries",
685 usleep(10000); /* wait 10ms for the conversion */
687 retries = MPL115_CONVERSION_RETRIES;
688 while (retries > 0) {
689 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL115_ADDR_CONV,
690 STATIC_ARRAY_SIZE(mpl115_conv),
697 ERROR("barometer: MPL115_read_averaged - reading conversion: %s, "
698 "will retry at most %d more times",
701 ERROR("barometer: MPL115_read_averaged - reading conversion: %s, "
702 "too many failed retries",
708 conv_pressure = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
709 conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
710 DEBUG("barometer: MPL115_read_averaged, raw pressure ADC value = %d, "
711 "raw temperature ADC value = %d",
712 conv_pressure, conv_temperature);
714 adc_pressure = averaging_add_sample(&pressure_averaging, conv_pressure);
716 averaging_add_sample(&temperature_averaging, conv_temperature);
718 MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure,
721 DEBUG("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / "
722 "temperature = %lf, "
723 "real pressure = %lf hPa / temperature = %lf C",
724 adc_pressure, adc_temperature, *pressure, *temperature);
729 /* ------------------------ MPL3115 access ------------------------ */
732 * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
734 * As a sideeffect will leave set I2C slave address.
736 * @return 1 if MPL3115, 0 otherwise
738 static int MPL3115_detect(void) {
741 if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0) {
742 ERROR("barometer: MPL3115_detect problem setting i2c slave address to "
744 MPL3115_I2C_ADDRESS, STRERRNO);
748 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
749 if (res == MPL3115_WHO_AM_I_RESP) {
750 DEBUG("barometer: MPL3115_detect - positive detection");
754 DEBUG("barometer: MPL3115_detect - negative detection");
759 * Adjusts oversampling to values supported by MPL3115
761 * MPL3115 supports only power of 2 in the range 1 to 128.
763 static void MPL3115_adjust_oversampling(void) {
766 if (config_oversample > 100) {
768 mpl3115_oversample = MPL3115_CTRL_REG1_OST_128;
769 } else if (config_oversample > 48) {
771 mpl3115_oversample = MPL3115_CTRL_REG1_OST_64;
772 } else if (config_oversample > 24) {
774 mpl3115_oversample = MPL3115_CTRL_REG1_OST_32;
775 } else if (config_oversample > 12) {
777 mpl3115_oversample = MPL3115_CTRL_REG1_OST_16;
778 } else if (config_oversample > 6) {
780 mpl3115_oversample = MPL3115_CTRL_REG1_OST_8;
781 } else if (config_oversample > 3) {
783 mpl3115_oversample = MPL3115_CTRL_REG1_OST_4;
784 } else if (config_oversample > 1) {
786 mpl3115_oversample = MPL3115_CTRL_REG1_OST_2;
789 mpl3115_oversample = MPL3115_CTRL_REG1_OST_1;
792 DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from "
794 config_oversample, new_val);
795 config_oversample = new_val;
799 * Read sensor averaged measurements
801 * @param pressure averaged measured pressure
802 * @param temperature averaged measured temperature
804 * @return Zero when successful
806 static int MPL3115_read(double *pressure, double *temperature) {
809 __u8 data[MPL3115_NUM_CONV_VALS];
810 long int tmp_value = 0;
812 /* Set Active - activate the device from standby */
813 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
815 ERROR("barometer: MPL3115_read - cannot read CTRL_REG1: %s", STRERRNO);
819 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
820 ctrl | MPL3115_CTRL_REG1_SBYB);
822 ERROR("barometer: MPL3115_read - problem activating: %s", STRERRNO);
826 /* base sleep is 5ms x OST */
827 usleep(5000 * config_oversample);
829 /* check the flags/status if ready */
830 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
832 ERROR("barometer: MPL3115_read - cannot read status register: %s",
837 while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR) {
838 /* try some extra sleep... */
841 /* ... and repeat the check. The conversion has to finish sooner or later.
843 res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
845 ERROR("barometer: MPL3115_read - cannot read status register: %s",
851 /* Now read all the data in one block. There is address autoincrement. */
852 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL3115_REG_OUT_P_MSB,
853 MPL3115_NUM_CONV_VALS, data);
855 ERROR("barometer: MPL3115_read - cannot read data registers: %s", STRERRNO);
859 tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
860 *pressure = ((double)tmp_value) / 4.0 / 16.0 / 100.0;
861 DEBUG("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
863 if (data[3] > 0x7F) {
864 data[3] = ~data[3] + 1;
865 *temperature = data[3];
866 *temperature = -*temperature;
868 *temperature = data[3];
871 *temperature += (double)(data[4]) / 256.0;
872 DEBUG("barometer: MPL3115_read - temperature = %lf C", *temperature);
878 * Initialize MPL3115 for barometeric measurements
880 * @return 0 if successful
882 static int MPL3115_init_sensor(void) {
886 /* Reset the sensor. It will reset immediately without ACKing */
887 /* the transaction, so no error handling here. */
888 i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
889 MPL3115_CTRL_REG1_RST);
891 /* wait some time for the reset to finish */
894 /* now it should be in standby already so we can go and configure it */
896 /* Set temperature offset. */
897 /* result = ADCtemp + offset [C] */
898 offset = (__s8)(config_temp_offset * 16.0);
899 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset);
901 ERROR("barometer: MPL3115_init_sensor - problem setting temp offset: %s",
906 /* Set pressure offset. */
907 /* result = ADCpress + offset [hPa] */
908 offset = (__s8)(config_press_offset * 100.0 / 4.0);
909 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset);
912 "barometer: MPL3115_init_sensor - problem setting pressure offset: %s",
917 /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
918 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_PT_DATA_CFG,
919 MPL3115_PT_DATA_DREM | MPL3115_PT_DATA_PDEF |
920 MPL3115_PT_DATA_TDEF);
922 ERROR("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s",
927 /* Set to barometer with an OSR */
928 res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
931 ERROR("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
939 /* ------------------------ BMP085 access ------------------------ */
942 * Detect presence of a BMP085 pressure sensor by checking its ID register
944 * As a sideeffect will leave set I2C slave address.
946 * @return 1 if BMP085, 0 otherwise
948 static int BMP085_detect(void) {
951 if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0) {
952 ERROR("barometer: BMP085_detect - problem setting i2c slave address to "
954 BMP085_I2C_ADDRESS, STRERRNO);
958 res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG);
959 if (res == BMP085_CHIP_ID) {
960 DEBUG("barometer: BMP085_detect - positive detection");
963 res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION);
965 ERROR("barometer: BMP085_detect - problem checking chip version: %s",
969 DEBUG("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X",
970 res & 0x0f, (res & 0xf0) >> 4);
974 DEBUG("barometer: BMP085_detect - negative detection");
979 * Adjusts oversampling settings to values supported by BMP085
981 * BMP085 supports only 1,2,4 or 8 samples.
983 static void BMP085_adjust_oversampling(void) {
986 if (config_oversample > 6) /* 8 */
989 bmp085_oversampling = 3;
990 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3;
991 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3;
992 } else if (config_oversample > 3) /* 4 */
995 bmp085_oversampling = 2;
996 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2;
997 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2;
998 } else if (config_oversample > 1) /* 2 */
1001 bmp085_oversampling = 1;
1002 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1;
1003 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1;
1007 bmp085_oversampling = 0;
1008 bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0;
1009 bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0;
1012 DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from "
1014 config_oversample, new_val);
1015 config_oversample = new_val;
1019 * Read the BMP085 sensor conversion coefficients.
1021 * These are (device specific) constants so we can read them just once.
1023 * @return Zero when successful
1025 static int BMP085_read_coeffs(void) {
1027 __u8 coeffs[BMP085_NUM_COEFFS];
1029 res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_COEFFS,
1030 BMP085_NUM_COEFFS, coeffs);
1032 ERROR("barometer: BMP085_read_coeffs - problem reading data: %s", STRERRNO);
1036 bmp085_AC1 = ((int16_t)coeffs[0] << 8) | (int16_t)coeffs[1];
1037 bmp085_AC2 = ((int16_t)coeffs[2] << 8) | (int16_t)coeffs[3];
1038 bmp085_AC3 = ((int16_t)coeffs[4] << 8) | (int16_t)coeffs[5];
1039 bmp085_AC4 = ((uint16_t)coeffs[6] << 8) | (uint16_t)coeffs[7];
1040 bmp085_AC5 = ((uint16_t)coeffs[8] << 8) | (uint16_t)coeffs[9];
1041 bmp085_AC6 = ((uint16_t)coeffs[10] << 8) | (uint16_t)coeffs[11];
1042 bmp085_B1 = ((int16_t)coeffs[12] << 8) | (int16_t)coeffs[13];
1043 bmp085_B2 = ((int16_t)coeffs[14] << 8) | (int16_t)coeffs[15];
1044 bmp085_MB = ((int16_t)coeffs[16] << 8) | (int16_t)coeffs[17];
1045 bmp085_MC = ((int16_t)coeffs[18] << 8) | (int16_t)coeffs[19];
1046 bmp085_MD = ((int16_t)coeffs[20] << 8) | (int16_t)coeffs[21];
1048 DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"
1049 " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d",
1050 bmp085_AC1, bmp085_AC2, bmp085_AC3, bmp085_AC4, bmp085_AC5, bmp085_AC6,
1051 bmp085_B1, bmp085_B2, bmp085_MB, bmp085_MC, bmp085_MD);
1057 * Convert raw BMP085 adc values to real data using the sensor coefficients.
1059 * @param adc_pressure adc pressure value to be converted
1060 * @param adc_temp adc temperature value to be converted
1061 * @param pressure computed real pressure
1062 * @param temperature computed real temperature
1064 static void BMP085_convert_adc_to_real(long adc_pressure, long adc_temperature,
1065 double *pressure, double *temperature)
1070 unsigned long B4, B7;
1075 /* calculate real temperature */
1076 X1 = ((adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15;
1077 X2 = (bmp085_MC << 11) / (X1 + bmp085_MD);
1082 *temperature = (double)T * 0.1;
1084 /* calculate real pressure */
1085 /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept
1090 X1 = ((bmp085_B2 * ((B6 * B6) >> 12)) >> 11);
1091 X2 = (((long)bmp085_AC2 * B6) >> 11);
1093 B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
1096 X1 = (((long)bmp085_AC3 * B6) >> 13);
1097 X2 = (bmp085_B1 * ((B6 * B6) >> 12)) >> 16;
1098 X3 = ((X1 + X2) + 2) >> 2;
1099 B4 = ((long)bmp085_AC4 * (unsigned long)(X3 + 32768)) >> 15;
1102 B7 = (unsigned long)(adc_pressure - B3) * (50000 >> bmp085_oversampling);
1103 if (B7 < 0x80000000) {
1108 X1 = (P >> 8) * (P >> 8);
1109 X1 = (X1 * 3038) >> 16;
1110 X2 = ((-7357) * P) >> 16;
1111 P = P + ((X1 + X2 + 3791) >> 4);
1113 *pressure = P / 100.0; // in [hPa]
1114 DEBUG("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C", *pressure,
1119 * Read compensated sensor measurements
1121 * @param pressure averaged measured pressure
1122 * @param temperature averaged measured temperature
1124 * @return Zero when successful
1126 static int BMP085_read(double *pressure, double *temperature) {
1131 long adc_temperature;
1133 /* start conversion of temperature */
1134 res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG,
1135 BMP085_CMD_CONVERT_TEMP);
1137 ERROR("barometer: BMP085_read - problem requesting temperature conversion: "
1143 usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
1146 i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 2, measBuff);
1148 ERROR("barometer: BMP085_read - problem reading temperature data: %s",
1153 adc_temperature = ((unsigned short)measBuff[0] << 8) + measBuff[1];
1156 res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG,
1157 bmp085_cmdCnvPress);
1159 ERROR("barometer: BMP085_read - problem requesting pressure conversion: %s",
1164 usleep(bmp085_timeCnvPress); /* wait for the conversion */
1167 i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 3, measBuff);
1169 ERROR("barometer: BMP085_read - problem reading pressure data: %s",
1174 adc_pressure = (long)((((ulong)measBuff[0] << 16) |
1175 ((ulong)measBuff[1] << 8) | (ulong)measBuff[2]) >>
1176 (8 - bmp085_oversampling));
1178 DEBUG("barometer: BMP085_read - raw pressure ADC value = %ld, "
1179 "raw temperature ADC value = %ld",
1180 adc_pressure, adc_temperature);
1182 BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure,
1188 /* ------------------------ Sensor detection ------------------------ */
1190 * Detect presence of a supported sensor.
1192 * As a sideeffect will leave set I2C slave address.
1193 * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
1194 * first sensor beeing found.
1196 * @return detected sensor type
1198 static enum Sensor_type detect_sensor_type(void) {
1199 if (BMP085_detect())
1200 return Sensor_BMP085;
1202 else if (MPL3115_detect())
1203 return Sensor_MPL3115;
1205 else if (MPL115_detect())
1206 return Sensor_MPL115;
1211 /* ------------------------ Common functionality ------------------------ */
1214 * Convert absolute pressure (in hPa) to mean sea level pressure
1216 * Implemented methods are:
1217 * - MSLP_NONE - no converions, returns absolute pressure
1219 * - MSLP_INTERNATIONAL - see
1220 * http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
1221 * Requires #config_altitude
1223 * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See
1224 * http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
1225 * Requires both #config_altitude and temperature reference(s).
1227 * @param abs_pressure absloute pressure to be converted
1229 * @return mean sea level pressure if successful, NAN otherwise
1231 static double abs_to_mean_sea_level_pressure(double abs_pressure) {
1236 if (config_normalize >= MSLP_DEU_WETT) {
1237 result = get_reference_temperature(&temp);
1243 switch (config_normalize) {
1245 mean = abs_pressure;
1248 case MSLP_INTERNATIONAL:
1249 mean = abs_pressure / pow(1.0 - 0.0065 * config_altitude / 288.15,
1250 9.80665 * 0.0289644 / (8.31447 * 0.0065));
1253 case MSLP_DEU_WETT: {
1254 double E; /* humidity */
1257 E = 5.6402 * (-0.0916 + exp(0.06 * temp));
1259 E = 18.2194 * (1.0463 - exp(-0.0666 * temp));
1261 (287.05 * (temp + 273.15 + 0.12 * E + 0.0065 * config_altitude / 2)) *
1263 mean = abs_pressure * exp(x);
1268 "barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d",
1270 mean = abs_pressure;
1274 DEBUG("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, "
1275 "method = %d, meanPressure = %lf hPa",
1276 abs_pressure, config_normalize, mean);
1281 /* ------------------------ main plugin callbacks ------------------------ */
1284 * Main plugin configuration callback (using simple config)
1286 * @param key configuration key we should process
1287 * @param value configuration value we should process
1289 * @return Zero when successful.
1291 static int collectd_barometer_config(const char *key, const char *value) {
1292 DEBUG("barometer: collectd_barometer_config");
1294 if (strcasecmp(key, "Device") == 0) {
1295 sfree(config_device);
1296 config_device = strdup(value);
1297 } else if (strcasecmp(key, "Oversampling") == 0) {
1298 int oversampling_tmp = atoi(value);
1299 if (oversampling_tmp < 1 || oversampling_tmp > 1024) {
1300 WARNING("barometer: collectd_barometer_config: invalid oversampling: %d."
1301 " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for "
1302 "MPL3115) or 1 to 8 (for BMP085).",
1306 config_oversample = oversampling_tmp;
1307 } else if (strcasecmp(key, "Altitude") == 0) {
1308 config_altitude = atof(value);
1309 } else if (strcasecmp(key, "Normalization") == 0) {
1310 int normalize_tmp = atoi(value);
1311 if (normalize_tmp < 0 || normalize_tmp > 2) {
1312 WARNING("barometer: collectd_barometer_config: invalid normalization: %d",
1316 config_normalize = normalize_tmp;
1317 } else if (strcasecmp(key, "TemperatureSensor") == 0) {
1318 if (temp_list_add(temp_list, value)) {
1321 } else if (strcasecmp(key, "PressureOffset") == 0) {
1322 config_press_offset = atof(value);
1323 } else if (strcasecmp(key, "TemperatureOffset") == 0) {
1324 config_temp_offset = atof(value);
1333 * Shutdown callback.
1335 * Close I2C and delete all the buffers.
1337 * @return Zero when successful (at the moment the only possible outcome)
1339 static int collectd_barometer_shutdown(void) {
1340 DEBUG("barometer: collectd_barometer_shutdown");
1342 if (sensor_type == Sensor_MPL115) {
1343 averaging_delete(&pressure_averaging);
1344 averaging_delete(&temperature_averaging);
1346 temp_list_delete(&temp_list);
1349 if (i2c_bus_fd > 0) {
1352 sfree(config_device);
1359 * Plugin read callback for MPL115.
1361 * Dispatching will create values:
1362 * - <hostname>/barometer-mpl115/pressure-normalized
1363 * - <hostname>/barometer-mpl115/pressure-absolute
1364 * - <hostname>/barometer-mpl115/temperature
1366 * @return Zero when successful.
1368 static int MPL115_collectd_barometer_read(void) {
1371 double pressure = 0.0;
1372 double temperature = 0.0;
1373 double norm_pressure = 0.0;
1375 value_list_t vl = VALUE_LIST_INIT;
1378 DEBUG("barometer: MPL115_collectd_barometer_read");
1384 /* Rather than delaying init, we will intitialize during first read. This
1385 way at least we have a better chance to have the reference temperature
1386 already available. */
1387 if (!avg_initialized) {
1388 for (int i = 0; i < config_oversample - 1; ++i) {
1389 result = MPL115_read_averaged(&pressure, &temperature);
1391 ERROR("barometer: MPL115_collectd_barometer_read - mpl115 read, "
1392 "ignored during init");
1394 DEBUG("barometer: MPL115_collectd_barometer_read - init %d / %d", i + 1,
1395 config_oversample - 1);
1398 avg_initialized = true;
1401 result = MPL115_read_averaged(&pressure, &temperature);
1405 norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1407 sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1408 sstrncpy(vl.plugin_instance, "mpl115", sizeof(vl.plugin_instance));
1413 /* dispatch normalized air pressure */
1414 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1415 sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1416 values[0].gauge = norm_pressure;
1417 plugin_dispatch_values(&vl);
1419 /* dispatch absolute air pressure */
1420 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1421 sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1422 values[0].gauge = pressure;
1423 plugin_dispatch_values(&vl);
1425 /* dispatch sensor temperature */
1426 sstrncpy(vl.type, "temperature", sizeof(vl.type));
1427 sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1428 values[0].gauge = temperature;
1429 plugin_dispatch_values(&vl);
1435 * Plugin read callback for MPL3115.
1437 * Dispatching will create values:
1438 * - <hostname>/barometer-mpl3115/pressure-normalized
1439 * - <hostname>/barometer-mpl3115/pressure-absolute
1440 * - <hostname>/barometer-mpl3115/temperature
1442 * @return Zero when successful.
1444 static int MPL3115_collectd_barometer_read(void) {
1447 double pressure = 0.0;
1448 double temperature = 0.0;
1449 double norm_pressure = 0.0;
1451 value_list_t vl = VALUE_LIST_INIT;
1454 DEBUG("barometer: MPL3115_collectd_barometer_read");
1460 result = MPL3115_read(&pressure, &temperature);
1464 norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1466 sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1467 sstrncpy(vl.plugin_instance, "mpl3115", sizeof(vl.plugin_instance));
1472 /* dispatch normalized air pressure */
1473 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1474 sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1475 values[0].gauge = norm_pressure;
1476 plugin_dispatch_values(&vl);
1478 /* dispatch absolute air pressure */
1479 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1480 sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1481 values[0].gauge = pressure;
1482 plugin_dispatch_values(&vl);
1484 /* dispatch sensor temperature */
1485 sstrncpy(vl.type, "temperature", sizeof(vl.type));
1486 sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1487 values[0].gauge = temperature;
1488 plugin_dispatch_values(&vl);
1494 * Plugin read callback for BMP085.
1496 * Dispatching will create values:
1497 * - <hostname>/barometer-bmp085/pressure-normalized
1498 * - <hostname>/barometer-bmp085/pressure-absolute
1499 * - <hostname>/barometer-bmp085/temperature
1501 * @return Zero when successful.
1503 static int BMP085_collectd_barometer_read(void) {
1506 double pressure = 0.0;
1507 double temperature = 0.0;
1508 double norm_pressure = 0.0;
1510 value_list_t vl = VALUE_LIST_INIT;
1513 DEBUG("barometer: BMP085_collectd_barometer_read");
1519 result = BMP085_read(&pressure, &temperature);
1523 norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1525 sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1526 sstrncpy(vl.plugin_instance, "bmp085", sizeof(vl.plugin_instance));
1531 /* dispatch normalized air pressure */
1532 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1533 sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1534 values[0].gauge = norm_pressure;
1535 plugin_dispatch_values(&vl);
1537 /* dispatch absolute air pressure */
1538 sstrncpy(vl.type, "pressure", sizeof(vl.type));
1539 sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1540 values[0].gauge = pressure;
1541 plugin_dispatch_values(&vl);
1543 /* dispatch sensor temperature */
1544 sstrncpy(vl.type, "temperature", sizeof(vl.type));
1545 sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1546 values[0].gauge = temperature;
1547 plugin_dispatch_values(&vl);
1553 * Initialization callback
1555 * Check config, initialize I2C bus access, conversion coefficients and
1559 * @return Zero when successful.
1561 static int collectd_barometer_init(void) {
1563 DEBUG("barometer: collectd_barometer_init");
1565 if (config_device == NULL) {
1566 ERROR("barometer: collectd_barometer_init I2C bus device not configured");
1570 if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude)) {
1571 ERROR("barometer: collectd_barometer_init no altitude configured "
1572 "for mean sea level pressure normalization.");
1576 if (config_normalize == MSLP_DEU_WETT && temp_list == NULL) {
1577 ERROR("barometer: collectd_barometer_init no temperature reference "
1578 "configured for mean sea level pressure normalization.");
1582 i2c_bus_fd = open(config_device, O_RDWR);
1583 if (i2c_bus_fd < 0) {
1584 ERROR("barometer: collectd_barometer_init problem opening I2C bus device "
1585 "\"%s\": %s (is loaded mod i2c-dev?)",
1586 config_device, STRERRNO);
1590 /* detect sensor type - this will also set slave address */
1591 sensor_type = detect_sensor_type();
1593 /* init correct sensor type */
1594 switch (sensor_type) {
1596 case Sensor_MPL3115: {
1597 MPL3115_adjust_oversampling();
1599 if (MPL3115_init_sensor())
1602 plugin_register_read("barometer", MPL3115_collectd_barometer_read);
1606 case Sensor_MPL115: {
1607 if (averaging_create(&pressure_averaging, config_oversample)) {
1609 "barometer: collectd_barometer_init pressure averaging init failed");
1613 if (averaging_create(&temperature_averaging, config_oversample)) {
1614 ERROR("barometer: collectd_barometer_init temperature averaging init "
1619 if (MPL115_read_coeffs() < 0)
1622 plugin_register_read("barometer", MPL115_collectd_barometer_read);
1626 case Sensor_BMP085: {
1627 BMP085_adjust_oversampling();
1629 if (BMP085_read_coeffs() < 0)
1632 plugin_register_read("barometer", BMP085_collectd_barometer_read);
1635 /* anything else -> error */
1637 ERROR("barometer: collectd_barometer_init - no supported sensor found");
1645 /* ------------------------ plugin register / entry point
1646 * ------------------------ */
1649 * Plugin "entry" - register all callback.
1652 void module_register(void) {
1653 plugin_register_config("barometer", collectd_barometer_config, config_keys,
1655 plugin_register_init("barometer", collectd_barometer_init);
1656 plugin_register_shutdown("barometer", collectd_barometer_shutdown);