Merge pull request #1957 from alignan/pull/bme280-sensor

sensors: bme280 weather sensor
This commit is contained in:
Antonio Lignan 2016-12-10 18:37:21 +01:00 committed by GitHub
commit ac2a31455e
17 changed files with 857 additions and 10 deletions

26
dev/bme280/README.bme280 Normal file
View file

@ -0,0 +1,26 @@
Contiki implementation for Bosch Sensortec BME280 sensor.
BME280 is compact and fast and includes temp, RH, and pressure.
Chip uses I2C or SPI. This implementation and follow Contiki
device API and I2C.
For better performance and less chip warm up and less I2C transactions
burst read is recommended. Here all T/RH/P is read in one single
I2C read and kept the measurements have the same time.
The burst read is stored in struct bme280_mea which accessible from
the Contiki. Also note that the full chip resolution is available.
The variables are overscaled to give the app full controlover resolution.
See bme280.h
The pressure can be calculated with 32 or 64. The define BME280_64BIT
controls this. Typically in your project-conf.h
Implemented according to datasheet Rev 1.1.
Limitations:
Implementation implements Weather Mode which uses forced one-shot
mode no oversampling nor filters and reads all T/RH/P in one read.

45
dev/bme280/bme280-arch.h Normal file
View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2016, Zolertia <http://www.zolertia.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
#ifndef BME280_ARCH_H
#define BME280_ARCH_H
/* Initialize the I2C module */
void bme280_arch_i2c_init();
/* I2C read registers */
void bme280_arch_i2c_read_mem(uint8_t addr, uint8_t reg, uint8_t *buf,
uint8_t bytes);
/* I2C write to a single register */
void bme280_arch_i2c_write_mem(uint8_t addr, uint8_t reg, uint8_t value);
#endif
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2015, Copyright Robert Olsson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*
* Author : Robert Olsson rolss@kth.se/robert@radio-sensors.com
* Created : 2016-09-14
*/
#include "contiki.h"
#include "lib/sensors.h"
#include "dev/bme280/bme280.h"
#include "dev/bme280/bme280-sensor.h"
/*---------------------------------------------------------------------------*/
static int
value(int type)
{
/* Read all measurements with one burst read */
bme280_read(BME280_MODE_WEATHER);
/* Return a la Contiki API */
switch(type) {
case BME280_SENSOR_TEMP:
return bme280_mea.t_overscale100 / 100;
case BME280_SENSOR_HUMIDITY:
return bme280_mea.h_overscale1024 >> 10;
case BME280_SENSOR_PRESSURE:
/* Scale down w. 10 not to overslow the signed int */
#ifdef BME280_64BIT
return bme280_mea.p_overscale256 / (256 * 10);
#else
return bme280_mea.p / 10;
#endif
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int
status(int type)
{
return 0;
}
/*---------------------------------------------------------------------------*/
static int
configure(int type, int c)
{
return bme280_init(BME280_MODE_WEATHER);
}
/*---------------------------------------------------------------------------*/
SENSORS_SENSOR(bme280_sensor, "bme280", value, configure, status);

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2015, Copyright Robert Olsson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*
* Author : Robert Olsson rolss@kth.se/robert@radio-sensors.com
* Created : 2016-09-14
*/
#ifndef BME280_SENSOR_H_
#define BME280_SENSOR_H_
#include "lib/sensors.h"
#include "bme280.h"
extern const struct sensors_sensor bme280_sensor;
#define BME280_SENSOR_TEMP 0
#define BME280_SENSOR_HUMIDITY 1
#define BME280_SENSOR_PRESSURE 2
#endif /* BME280_SENSOR_H_ */

276
dev/bme280/bme280.c Normal file
View file

@ -0,0 +1,276 @@
/*
* Copyright (c) 2015, Copyright Robert Olsson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*
* Author : Robert Olsson rolss@kth.se/robert@radio-sensors.com
* Created : 2016-09-14
*/
/**
* \file
* Basic functions for Bosch BME280 based on datasheet Rev 1.1
*/
#include "contiki.h"
#include <string.h>
#include "bme280.h"
#include "bme280-arch.h"
#include "lib/sensors.h"
static struct {
unsigned short dig_t1;
signed short dig_t2;
signed short dig_t3;
unsigned short dig_p1;
signed short dig_p2;
signed short dig_p3;
signed short dig_p4;
signed short dig_p5;
signed short dig_p6;
signed short dig_p7;
signed short dig_p8;
signed short dig_p9;
unsigned char dig_h1;
signed short dig_h2;
unsigned char dig_h3;
signed short dig_h4;
signed short dig_h5;
signed char dig_h6;
int32_t t_fine;
uint8_t mode;
} bm;
int32_t
bme280_t_overscale100(int32_t ut)
{
int32_t v1, v2, t;
v1 = ((((ut >> 3) - ((int32_t)bm.dig_t1 << 1))) *
((int32_t)bm.dig_t2)) >> 11;
v2 = (((((ut >> 4) - ((int32_t)bm.dig_t1)) * ((ut >> 4) -
((int32_t)bm.dig_t1))) >> 12) * ((int32_t)bm.dig_t3)) >> 14;
bm.t_fine = v1 + v2;
t = (bm.t_fine * 5 + 128) >> 8;
return t;
}
#ifdef BME280_32BIT
static uint32_t
bme280_p(int32_t up)
{
int32_t v1, v2;
uint32_t p;
v1 = (((int32_t)bm.t_fine) >> 1) - (int32_t)64000;
v2 = (((v1 >> 2) * (v1 >> 2)) >> 11) * ((int32_t)bm.dig_p6);
v2 = v2 + ((v1 * ((int32_t)bm.dig_p5)) << 1);
v2 = (v2 >> 2) + (((int32_t)bm.dig_p4) << 16);
v1 = (((bm.dig_p3 * (((v1 >> 2) * (v1 >> 2)) >> 13)) >> 3) +
((((int32_t)bm.dig_p2) * v1) >> 1)) >> 18;
v1 = ((((32768 + v1)) * ((int32_t)bm.dig_p1)) >> 15);
if(v1 == 0) {
return 0;
}
p = (((uint32_t)(((int32_t)1048576) - up) - (v2 >> 12))) * 3125;
if(p < 0x80000000) {
p = (p << 1) / ((uint32_t)v1);
} else {
p = (p / (uint32_t)v1) * 2;
}
v1 = (((int32_t)bm.dig_p9) * ((int32_t)(((p >> 3) * (p >> 3)) >> 13))) >> 12;
v2 = (((int32_t)(p >> 2)) * ((int32_t)bm.dig_p8)) >> 13;
p = (uint32_t)((int32_t)p + ((v1 + v2 + bm.dig_p7) >> 4));
return p;
}
#else
static uint32_t
bme280_p_overscale256(int32_t up)
{
int64_t v1, v2, p;
v1 = ((int64_t)bm.t_fine) - 128000;
v2 = v1 * v1 * (int64_t)bm.dig_p6;
v2 = v2 + ((v1 * (int64_t)bm.dig_p5) << 17);
v2 = v2 + (((int64_t)bm.dig_p4) << 35);
v1 = ((v1 * v1 * (int64_t)bm.dig_p3) >> 8) + ((v1 * (int64_t)bm.dig_p2) << 12);
v1 = (((((int64_t)1) << 47) + v1)) * ((int64_t)bm.dig_p1) >> 33;
if(v1 == 0) {
return 0;
}
p = 1048576 - up;
p = (((p << 31) - v2) * 3125) / v1;
v1 = (((int64_t)bm.dig_p9) * (p >> 13) * (p >> 13)) >> 25;
v2 = (((int64_t)bm.dig_p8) * p) >> 19;
p = (((p + v1 + v2) >> 8) + (((int64_t)bm.dig_p7) << 4));
return (uint32_t)p;
}
#endif
static uint32_t
bme280_h_overscale1024(int32_t uh)
{
int32_t v1;
v1 = (bm.t_fine - ((int32_t)76800));
v1 = (((((uh << 14) - (((int32_t)bm.dig_h4) << 20) - (((int32_t)bm.dig_h5) * v1)) + ((int32_t)16384)) >> 15)
* (((((((v1 * ((int32_t)bm.dig_h6)) >> 10) * (((v1 * ((int32_t)bm.dig_h3)) >> 11) + ((int32_t)32768)))
>> 10) + ((int32_t)2097152)) * ((int32_t)bm.dig_h2) + 8192) >> 14));
v1 = (v1 - (((((v1 >> 15) * (v1 >> 15)) >> 7) * ((int32_t)bm.dig_h1)) >> 4));
v1 = (v1 < 0 ? 0 : v1);
v1 = (v1 > 419430400 ? 419430400 : v1);
return (uint32_t)(v1 >> 12);
}
uint8_t
bme280_init(uint8_t mode)
{
uint16_t i;
uint8_t buf[26];
bme280_arch_i2c_init();
/* Do not mess with other chips */
bme280_arch_i2c_read_mem(BME280_ADDR, 0xD0, buf, 1);
if(buf[0] != BME280_CHIP_ID) {
return 0;
}
bme280_arch_i2c_write_mem(BME280_ADDR, BME280_CNTL_RESET, 0xB6);
for(i = 0; i < BME280_MAX_WAIT; i++) {
clock_delay_usec(1000);
}
memset(buf, 0, sizeof(buf));
/* Burst read of all calibration part 1 */
bme280_arch_i2c_read_mem(BME280_ADDR, BME280_DIG_T1_ADDR, buf, sizeof(buf));
bm.dig_t1 = ((uint16_t)buf[1] << 8) | (uint16_t)buf[0];
bm.dig_t2 = ((int16_t)buf[3] << 8) | (uint16_t)buf[2];
bm.dig_t3 = ((int16_t)buf[5] << 8) | (uint16_t)buf[4];
bm.dig_p1 = ((uint16_t)buf[7] << 8) | (uint16_t)buf[6];
bm.dig_p2 = ((int16_t)buf[9] << 8) | (uint16_t)buf[8];
bm.dig_p3 = ((int16_t)buf[11] << 8) | (uint16_t)buf[10];
bm.dig_p4 = ((int16_t)buf[13] << 8) | (uint16_t)buf[12];
bm.dig_p5 = ((int16_t)buf[15] << 8) | (uint16_t)buf[14];
bm.dig_p6 = ((int16_t)buf[17] << 8) | (uint16_t)buf[16];
bm.dig_p7 = ((int16_t)buf[19] << 8) | (uint16_t)buf[18];
bm.dig_p8 = ((int16_t)buf[21] << 8) | (uint16_t)buf[20];
bm.dig_p9 = ((int16_t)buf[23] << 8) | (uint16_t)buf[22];
/* A0 not used */
bm.dig_h1 = (unsigned char)buf[25];
/* Burst read of all calibration part 2 */
bme280_arch_i2c_read_mem(BME280_ADDR, BME280_DIG_H2_ADDR, buf, 8);
bm.dig_h2 = ((int16_t)buf[1] << 8) | (uint16_t)buf[0];
bm.dig_h3 = (unsigned char)buf[2];
bm.dig_h4 = ((int16_t)buf[3] << 4) | (((uint16_t)buf[4]) & 0xF);
bm.dig_h5 = ((int16_t)buf[6] << 4) | (((uint16_t)buf[5]) & 0xF);
bm.dig_h6 = (unsigned char)buf[7];
bm.mode = mode;
return 1;
}
void
bme280_read(uint8_t mode)
{
int32_t ut, uh, up;
uint8_t buf[8], sleep;
uint16_t i;
memset(buf, 0, sizeof(buf));
/* Are we initilized and in the right mode? */
if(mode == BME280_MODE_NONE || mode != bm.mode) {
return;
}
ut = uh = up = 0;
/* Weather mode. See sectiom 3.5 Datasheet */
if(mode == BME280_MODE_WEATHER) {
/* Humidity oversampling *1 */
bme280_arch_i2c_write_mem(BME280_ADDR, BME280_CNTL_HUM, 0x01);
/* 00100111 0x27 oversampling *1 for t and p plus normal mode */
/* 0.5 ms -- no filter -- no SPI */
bme280_arch_i2c_write_mem(BME280_ADDR, BME280_CONTROL, 0x00);
/* 00100110 0x26 oversampling *1 for t and p plus forced mode */
/* Trigger measurement needed for every time in forced mode */
bme280_arch_i2c_write_mem(BME280_ADDR, BME280_CNTL_MEAS, 0x26);
/* Wait to get into sleep mode == measurement done */
for(i = 0; i < BME280_MAX_WAIT; i++) {
bme280_arch_i2c_read_mem(BME280_ADDR, BME280_CNTL_MEAS, &sleep, 1);
sleep = sleep& 0x03;
if(sleep== 0) {
break;
} else {
clock_delay_usec(1000);
}
}
if(i == BME280_MAX_WAIT) {
return; /* error wait*/
}
} else { /* if(mode == BME280_MODE_WEATHER) */
return; /* error mode*/
}
/* Burst read of all measurements */
bme280_arch_i2c_read_mem(BME280_ADDR, BME280_PRESS, buf, 8);
ut = (uint32_t)(buf[3]) << 12 | (uint32_t)(buf[4]) << 4 | (uint32_t)buf[5] >> 4;
up = (uint32_t)(buf[0]) << 12 | (uint32_t)(buf[1]) << 4 | (uint32_t)buf[2] >> 4;
uh = (uint32_t)(buf[6]) << 8 | (uint32_t)buf[7];
bme280_mea.t_overscale100 = bme280_t_overscale100(ut);
bme280_mea.h_overscale1024 = bme280_h_overscale1024(uh);
#ifdef BME280_64BIT
bme280_mea.p_overscale256 = bme280_p_overscale256(up);
#else
bme280_mea.p = bme280_p(up);
#endif
#if TEST
printf("T_BME280=%5.2f", (double)bme280_mea.t_overscale100 / 100.);
printf(" RH_BME280=%5.2f ", (double)bme280_mea.h_overscale1024 / 1024.);
#ifdef BME280_64BIT
printf(" P_BME280=%5.2f\n", (double)bme280_mea.p_overscale256 / 256.);
#else
printf(" P_BME280=%5.2f\n", (double)bme280_mea.p);
#endif
#endif
}

110
dev/bme280/bme280.h Normal file
View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2015, Copyright Robert Olsson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*
* Author : Robert Olsson rolss@kth.se/robert@radio-sensors.com
*
* Created : 2016-09-14
*/
/**
* \file
* Definitions for the Bosch BME280 based on datasheet Rev 1.1
*/
#ifndef BME280_H
#define BME280_H
#ifndef BME280_32BIT
#define BME280_64BIT
#endif
uint8_t bme280_init(uint8_t mode);
void bme280_read(uint8_t mode);
#ifdef BME280_CONF_ADDR
#define BME280_ADDR BME280_CONF_ADDR
#else
#define BME280_ADDR (0x77 << 1) /* Alternative 0x76 */
#endif
/* Diffrent BOSCH chip id's */
#define BMP085_CHIP_ID 0x55 /* And also BMP180 */
#define BMP280_CHIP_ID 0x58
#define BME280_CHIP_ID 0x60
/* Address map */
#define BME280_DIG_T1_ADDR 0x88
#define BME280_DIG_T2_ADDR 0x8A
#define BME280_DIG_T3_ADDR 0x8C
#define BME280_DIG_P1_ADDR 0x8E
#define BME280_DIG_P2_ADDR 0x90
#define BME280_DIG_P3_ADDR 0x92
#define BME280_DIG_P4_ADDR 0x94
#define BME280_DIG_P5_ADDR 0x96
#define BME280_DIG_P6_ADDR 0x98
#define BME280_DIG_P7_ADDR 0x9A
#define BME280_DIG_P8_ADDR 0x9C
#define BME280_DIG_P9_ADDR 0x9E
#define BME280_DIG_H1_ADDR 0xA1
#define BMP_CHIP_ID_ADDR 0xD0
#define BME280_CNTL_RESET 0xE0
#define BME280_DIG_H2_ADDR 0xE1
#define BME280_DIG_H3_ADDR 0xE3
#define BME280_DIG_H4_ADDR 0xE4
#define BME280_DIG_H5_ADDR 0xE5
#define BME280_DIG_H6_ADDR 0xE7
#define BME280_CNTL_HUM 0xF2
#define BME280_STATUS 0xF3
#define BME280_CNTL_MEAS 0xF4
#define BME280_CONTROL 0xF5
#define BME280_PRESS 0xF7
/* Function modes outlined in datasheet */
#define BME280_MODE_NONE 0
#define BME280_MODE_WEATHER 1
#define BME280_MODE_HUMIDITY 2
#define BME280_MODE_INDOOR_NAVIGATION 3
#define BME280_MODE_GAMING 4
#define BME280_MAX_WAIT 300 /* ms. Forced mode max wait */
struct {
int32_t t_overscale100;
uint32_t h_overscale1024;
#ifdef BME280_64BIT
uint32_t p_overscale256;
#else
uint32_t p;
#endif
} bme280_mea;
#endif /* BME280_H */

View file

@ -8,6 +8,7 @@ PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
PRINTF_LIB = $(PRINTF_LIB_FLT)
CLIBS = $(PRINTF_LIB)
MODULES += dev/bme280
CUSTOM_RULE_LINK = 1
%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a

View file

@ -49,9 +49,8 @@
#include "dev/temp_mcu-sensor.h"
#include "dev/light-sensor.h"
#include "dev/pulse-sensor.h"
#ifdef CO2
#include "dev/bme280/bme280-sensor.h"
#include "dev/co2_sa_kxx-sensor.h"
#endif
/*---------------------------------------------------------------------------*/
PROCESS(hello_sensors_process, "Hello sensor process");
AUTOSTART_PROCESSES(&hello_sensors_process);
@ -80,9 +79,29 @@ read_values(void)
printf(" LIGHT=%-d", light_sensor.value(0));
printf(" PULSE_0=%-d", pulse_sensor.value(0));
printf(" PULSE_1=%-d", pulse_sensor.value(1));
#ifdef CO2
if( i2c_probed & I2C_CO2SA ) {
printf(" CO2=%-d", co2_sa_kxx_sensor.value( CO2_SA_KXX_CO2));
}
if( i2c_probed & I2C_BME280 ) {
#if STD_API
printf(" BME280_TEMP=%-d", bme280_sensor.value(BME280_SENSOR_TEMP));
printf(" BME280_RH=%-d", bme280_sensor.value(BME280_SENSOR_HUMIDITY));
printf(" BME280_P=%-d", bme280_sensor.value(BME280_SENSOR_PRESSURE));
#else
/* Trigger burst read */
bme280_sensor.value(BME280_SENSOR_TEMP);
printf(" T_BME280=%5.2f", (double)bme280_mea.t_overscale100 / 100.);
printf(" RH_BME280=%5.2f", (double)bme280_mea.h_overscale1024 / 1024.);
#ifdef BME280_64BIT
printf(" P_BME280=%5.2f", (double)bme280_mea.p_overscale256 / 256.);
#else
printf(" P_BME280=%5.2f", (double)bme280_mea.p);
#endif
#endif
}
printf("\n");
}
/*---------------------------------------------------------------------------*/
@ -95,9 +114,14 @@ PROCESS_THREAD(hello_sensors_process, ev, data)
SENSORS_ACTIVATE(temp_mcu_sensor);
SENSORS_ACTIVATE(light_sensor);
SENSORS_ACTIVATE(pulse_sensor);
#ifdef CO2
if( i2c_probed & I2C_BME280 ) {
SENSORS_ACTIVATE(bme280_sensor);
}
if( i2c_probed & I2C_CO2SA ) {
SENSORS_ACTIVATE(co2_sa_kxx_sensor);
#endif
}
leds_init();
leds_on(LEDS_RED);
leds_on(LEDS_YELLOW);

View file

@ -42,6 +42,8 @@
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/* #define BME280_32BIT */
#define NETSTACK_CONF_RDC nullrdc_driver
#define NETSTACK_CONF_MAC nullmac_driver

View file

@ -5,12 +5,15 @@ CONTIKI_PROJECT += test-bmp085-bmp180 test-motion test-rotation-sensor
CONTIKI_PROJECT += test-grove-light-sensor test-grove-loudness-sensor
CONTIKI_PROJECT += test-weather-meter test-grove-gyro test-lcd test-iaq
CONTIKI_PROJECT += test-pm10-sensor test-vac-sensor test-aac-sensor
CONTIKI_PROJECT += test-zonik test-dht22.c test-ac-dimmer.c
CONTIKI_PROJECT += test-zonik test-dht22.c test-ac-dimmer.c test-servo.c
CONTIKI_PROJECT += test-bme280
CONTIKI_TARGET_SOURCEFILES += tsl256x.c sht25.c bmpx8x.c motion-sensor.c
CONTIKI_TARGET_SOURCEFILES += adc-sensors.c weather-meter.c grove-gyro.c
CONTIKI_TARGET_SOURCEFILES += rgb-bl-lcd.c pm10-sensor.c iaq.c zonik.c relay.c
CONTIKI_TARGET_SOURCEFILES += dht22.c servo.c ac-dimmer.c
CONTIKI_TARGET_SOURCEFILES += dht22.c servo.c ac-dimmer.c bme280-arch.c
MODULES += /dev/bme280
all: $(CONTIKI_PROJECT)

View file

@ -50,6 +50,9 @@
#define MOTION_SENSOR_PIN 5
#define MOTION_SENSOR_VECTOR GPIO_A_IRQn
/* Use the following I2C address for the BME280 sensor (from MikroElektronika) */
#define BME280_CONF_ADDR 0x76
#endif /* PROJECT_CONF_H_ */
/** @} */

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2016, Zolertia <http://www.zolertia.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/*---------------------------------------------------------------------------*/
/**
* \addtogroup zoul-examples
* @{
*
* \defgroup zoul-bme280-test BME280 temperature and humidity sensor test
*
* Demonstrates the use of the BME280 digital temperature and humidity sensor
* @{
*
* \file
* A quick program for testing the BME280 temperature and humidity sensor
* \author
* Antonio Lignan <alinan@zolertia.com>
*/
/*---------------------------------------------------------------------------*/
#include <stdio.h>
#include "contiki.h"
#include "dev/bme280/bme280.h"
#include "dev/bme280/bme280-sensor.h"
/*---------------------------------------------------------------------------*/
#define BME280_USE_STD_API 1
/*---------------------------------------------------------------------------*/
PROCESS(zoul_bme280_process, "BME280 test");
AUTOSTART_PROCESSES(&zoul_bme280_process);
/*---------------------------------------------------------------------------*/
static struct etimer et;
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(zoul_bme280_process, ev, data)
{
PROCESS_BEGIN();
SENSORS_ACTIVATE(bme280_sensor);
/* Let it spin and read sensor data */
while(1) {
etimer_set(&et, CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
#if BME280_USE_STD_API
printf("temperature = %-d ", bme280_sensor.value(BME280_SENSOR_TEMP));
printf("humidity = %-d ", bme280_sensor.value(BME280_SENSOR_HUMIDITY));
printf("pressure = %-d\n", bme280_sensor.value(BME280_SENSOR_PRESSURE));
#else /* BME280_USE_STD_API */
/* Trigger burst read */
bme280_sensor.value(BME280_SENSOR_TEMP);
printf("temperature = %5.2f" , (double)bme280_mea.t_overscale100 / 100.);
printf("humidity = %5.2f ", (double)bme280_mea.h_overscale1024 / 1024.);
#ifdef BME280_64BIT
printf("pressure = %5.2f\n", (double)bme280_mea.p_overscale256 / 256.);
#else /* BME280_64BIT */
printf("pressure = %5.2f\n", (double)bme280_mea.p);
#endif /* BME280_64BIT */
#endif /* BME280_USE_STD_API */
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View file

@ -10,6 +10,7 @@ CONTIKI_TARGET_SOURCEFILES += temp-sensor.c
CONTIKI_TARGET_SOURCEFILES += enc28j60_avr.c
CONTIKI_TARGET_SOURCEFILES += co2_sa_kxx-sensor.c
CONTIKI_TARGET_SOURCEFILES += bme280-arch.c
CONTIKIAVR=$(CONTIKI)/cpu/avr
CONTIKIBOARD=.

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2016, Zolertia
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "i2c.h"
/*---------------------------------------------------------------------------*/
void
bme280_arch_i2c_init(void)
{
/* Does nothing */
}
/*---------------------------------------------------------------------------*/
void
bme280_arch_i2c_write_mem(uint8_t addr, uint8_t reg, uint8_t value)
{
i2c_write_mem(addr, reg, value);
}
/*---------------------------------------------------------------------------*/
void
bme280_arch_i2c_read_mem(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t bytes)
{
i2c_read_mem(addr, reg, buf, bytes);
}

View file

@ -224,5 +224,11 @@ i2c_probe(void)
probed |= I2C_CO2SA;
print_delim(p++, "CO2SA", del);
}
watchdog_periodic();
if(!i2c_start(I2C_BME280_ADDR)) {
i2c_stop();
probed |= I2C_BME280;
print_delim(p++, "BME280", del);
}
return probed;
}

View file

@ -40,12 +40,13 @@
/* Here we define the i2c address for dev we support */
#define I2C_AT24MAC_ADDR 0xB0 /* EUI64 ADDR */
#define I2C_SHT2X_ADDR (0x40 << 1) /* SHT2X ADDR */
#define I2C_BME280_ADDR (0x77 << 1) /* Alternative 0x76 */
/* Here we define a enumration for devices */
#define I2C_AT24MAC (1<<0)
#define I2C_SHT2X (1<<1)
#define I2C_CO2SA (1<<2) /* Sense-Air CO2 */
#define I2C_BME280 (1<<3)
#define I2C_READ 1
#define I2C_WRITE 0

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2015, Zolertia
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*---------------------------------------------------------------------------*/
/**
* \addtogroup zoul-bme280-sensor
* @{
*
* \file
* Architecture-specific I2C for the external BME280 weather sensor
*
* \author
* Antonio Lignan <alinan@zolertia.com>
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "dev/i2c.h"
/*---------------------------------------------------------------------------*/
void
bme280_arch_i2c_init(void)
{
i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN,
I2C_SCL_NORMAL_BUS_SPEED);
}
/*---------------------------------------------------------------------------*/
void
bme280_arch_i2c_write_mem(uint8_t addr, uint8_t reg, uint8_t value)
{
uint8_t buf[2];
buf[0] = reg;
buf[1] = value;
i2c_master_enable();
i2c_burst_send(addr, buf, 2);
}
/*---------------------------------------------------------------------------*/
void
bme280_arch_i2c_read_mem(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t bytes)
{
i2c_master_enable();
if(i2c_single_send(addr, reg) == I2C_MASTER_ERR_NONE) {
while(i2c_master_busy());
i2c_burst_receive(addr, buf, bytes);
}
}
/*---------------------------------------------------------------------------*/
/**
* @}
*/