Changeset - 55ef914749dc
[Not reviewed]
default
0 3 2
Ethan Zonca (ethanzonca) - 9 years ago 2017-01-18 10:34:25
e@ethanzonca.com
Add bme280, add humidity field to aprs output. Seems to work well.
5 files changed with 323 insertions and 11 deletions:
0 comments (0 inline, 0 general)
Include/bme280.h
Show inline comments
 
new file 100644
 
#ifndef _BME280_H_
 
#define _BME280_H_
 
 
#include <stdbool.h>
 
#include <inttypes.h>
 
#include "stm32f0xx_hal.h"
 
 
#define BME280_I2C_ADDR 0b11101100
 
 
#define PIN_BME280_SDA GPIO_PIN_7
 
#define PIN_BME280_SCL GPIO_PIN_6
 
#define PORT_BME280 GPIOB
 
 
 
//Register names
 
#define BME280_DIG_T1_LSB_REG			0x88
 
#define BME280_DIG_T1_MSB_REG			0x89
 
#define BME280_DIG_T2_LSB_REG			0x8A
 
#define BME280_DIG_T2_MSB_REG			0x8B
 
#define BME280_DIG_T3_LSB_REG			0x8C
 
#define BME280_DIG_T3_MSB_REG			0x8D
 
#define BME280_DIG_P1_LSB_REG			0x8E
 
#define BME280_DIG_P1_MSB_REG			0x8F
 
#define BME280_DIG_P2_LSB_REG			0x90
 
#define BME280_DIG_P2_MSB_REG			0x91
 
#define BME280_DIG_P3_LSB_REG			0x92
 
#define BME280_DIG_P3_MSB_REG			0x93
 
#define BME280_DIG_P4_LSB_REG			0x94
 
#define BME280_DIG_P4_MSB_REG			0x95
 
#define BME280_DIG_P5_LSB_REG			0x96
 
#define BME280_DIG_P5_MSB_REG			0x97
 
#define BME280_DIG_P6_LSB_REG			0x98
 
#define BME280_DIG_P6_MSB_REG			0x99
 
#define BME280_DIG_P7_LSB_REG			0x9A
 
#define BME280_DIG_P7_MSB_REG			0x9B
 
#define BME280_DIG_P8_LSB_REG			0x9C
 
#define BME280_DIG_P8_MSB_REG			0x9D
 
#define BME280_DIG_P9_LSB_REG			0x9E
 
#define BME280_DIG_P9_MSB_REG			0x9F
 
#define BME280_DIG_H1_REG				0xA1
 
#define BME280_CHIP_ID_REG				0xD0 //Chip ID
 
#define BME280_RST_REG					0xE0 //Softreset Reg
 
#define BME280_DIG_H2_LSB_REG			0xE1
 
#define BME280_DIG_H2_MSB_REG			0xE2
 
#define BME280_DIG_H3_REG				0xE3
 
#define BME280_DIG_H4_MSB_REG			0xE4
 
#define BME280_DIG_H4_LSB_REG			0xE5
 
#define BME280_DIG_H5_MSB_REG			0xE6
 
#define BME280_DIG_H6_REG				0xE7
 
#define BME280_CTRL_HUMIDITY_REG		0xF2 //Ctrl Humidity Reg
 
#define BME280_STAT_REG					0xF3 //Status Reg
 
#define BME280_CTRL_MEAS_REG			0xF4 //Ctrl Measure Reg
 
#define BME280_CONFIG_REG				0xF5 //Configuration Reg
 
#define BME280_PRESSURE_MSB_REG			0xF7 //Pressure MSB
 
#define BME280_PRESSURE_LSB_REG			0xF8 //Pressure LSB
 
#define BME280_PRESSURE_XLSB_REG		0xF9 //Pressure XLSB
 
#define BME280_TEMPERATURE_MSB_REG		0xFA //Temperature MSB
 
#define BME280_TEMPERATURE_LSB_REG		0xFB //Temperature LSB
 
#define BME280_TEMPERATURE_XLSB_REG		0xFC //Temperature XLSB
 
#define BME280_HUMIDITY_MSB_REG			0xFD //Humidity MSB
 
#define BME280_HUMIDITY_LSB_REG			0xFE //Humidity LSB
 
 
bool bme280_init(void);
 
void bme280_update(void);
 
void bme280_update_pressure(void);
 
void bme280_update_temperature(void);
 
void bme280_update_humidity(void);
 
int32_t bme280_get_pressure(void);
 
int32_t bme280_get_temperature(void);
 
int32_t bme280_get_humidity(void);
 
int32_t bme280_read_pressure_raw(void);
 
int32_t bme280_read_temperature_raw(void);
 
int32_t bme280_read_humidity_raw(void);
 
int32_t bme280_read_pressure_raw(void);
 
int32_t bme280_read_temperature_raw(void);
 
int32_t bme280_read_humidity_raw(void);
 
uint8_t bme280_read_byte(uint8_t register_address);
 
void bme280_read(uint8_t register_address, uint8_t* data, uint8_t length);
 
void bme280_write(uint8_t register_address, uint8_t data);
 
int32_t bme280_convert_temperature(int32_t adc_T);
 
uint32_t bme280_convert_pressure(int32_t adc_P);
 
uint32_t bme280_convert_humidity(int32_t adc_H);
 
I2C_HandleTypeDef* bme280_get_i2c_handle(void);
 
 
#endif /* _BME280_H_ */
Libraries/aprs/aprs.c
Show inline comments
 
@@ -24,7 +24,8 @@
 
#include <stdlib.h>
 

	
 
#include "config.h"
 
#include "pressure.h"
 
//#include "pressure.h"
 
#include "bme280.h"
 
#include "aprs.h"
 
#include "gps.h"
 
//#include "gps.h"
 
@@ -80,11 +81,15 @@ void aprs_send(void)
 
  ax25_send_string(tmpBuffer);
 

	
 
  // Pressure
 
  snprintf(tmpBuffer, 128, "%d,", pressure_getpressure());
 
  snprintf(tmpBuffer, 128, "%d,", bme280_get_pressure());
 
  ax25_send_string(tmpBuffer);
 
  
 
  // Temperature
 
  snprintf(tmpBuffer, 128, "%d,", pressure_gettemp());
 
  snprintf(tmpBuffer, 128, "%d,", bme280_get_temperature());
 
  ax25_send_string(tmpBuffer);
 

	
 
  // Humidity
 
  snprintf(tmpBuffer, 128, "%d,", bme280_get_humidity());
 
  ax25_send_string(tmpBuffer);
 

	
 
  // HDOP
Source/bme280.c
Show inline comments
 
new file 100644
 
#include "bme280.h"
 
#include "stm32f0xx_hal.h"
 
#include "config.h"
 
 
static uint16_t dig_T1;
 
static int16_t dig_T2;
 
static int16_t dig_T3;
 
 
static uint16_t dig_P1;
 
static int16_t dig_P2;
 
static int16_t dig_P3;
 
static int16_t dig_P4;
 
static int16_t dig_P5;
 
static int16_t dig_P6;
 
static int16_t dig_P7;
 
static int16_t dig_P8;
 
static int16_t dig_P9;
 
 
static uint8_t dig_H1;
 
static int16_t dig_H2;
 
static uint8_t dig_H3;
 
static int16_t dig_H4;
 
static int16_t dig_H5;
 
static uint8_t dig_H6;
 
 
static int16_t pressure;
 
static int16_t temperature;
 
static int16_t humidity;
 
 
static I2C_HandleTypeDef hi2c1;
 
 
 
// Initialize the BME280 PTU on I2C
 
bool bme280_init(void)
 
{
 
	GPIO_InitTypeDef GPIO_InitStruct;
 
 
	// I2C Pins
 
    GPIO_InitStruct.Pin = PIN_BME280_SCL|PIN_BME280_SDA;
 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
 
    GPIO_InitStruct.Pull = GPIO_PULLUP;
 
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
 
    GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
 
    HAL_GPIO_Init(PORT_BME280, &GPIO_InitStruct);
 
 
    // Initialize I2C peripheral
 
    __I2C1_CLK_ENABLE();
 
    hi2c1.Instance = I2C1;
 
    hi2c1.Init.Timing = 0x00108EFB;
 
    hi2c1.Init.OwnAddress1 = 0x0;
 
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
 
    hi2c1.Init.OwnAddress2 = 0;
 
    hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
 
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
 
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
 
    volatile HAL_StatusTypeDef res = HAL_I2C_Init(&hi2c1);
 
 
    // Configure Analog filter
 
    res =  HAL_I2CEx_AnalogFilter_Config(&hi2c1, I2C_ANALOGFILTER_ENABLED);
 
 
	// Enable I2C interrupt
 
    HAL_NVIC_SetPriority(I2C1_IRQn, 7, 4);
 
    HAL_NVIC_EnableIRQ(I2C1_IRQn);
 
 
 
	volatile uint8_t result = bme280_read_byte(BME280_CHIP_ID_REG);
 
 
 
	if (result != 0x60)
 
	{
 
		return false;
 
	}
 
 
	bme280_write(BME280_CTRL_MEAS_REG, 0x00);
 
	bme280_write(BME280_CONFIG_REG, 0b01100000); // 4hz sampling rate
 
	bme280_write(BME280_CTRL_HUMIDITY_REG, 0x01); //0b00000001, oversample*1
 
	bme280_write(BME280_CTRL_MEAS_REG, 0x27); //0b00100111
 
 
 
	//calibrate
 
 
	dig_T1 = ((uint16_t)((bme280_read_byte(BME280_DIG_T1_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_T1_LSB_REG)));
 
	dig_T2 = ((int16_t)((bme280_read_byte(BME280_DIG_T2_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_T2_LSB_REG)));
 
	dig_T3 = ((int16_t)((bme280_read_byte(BME280_DIG_T3_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_T3_LSB_REG)));
 
 
	dig_P1 = ((uint16_t)((bme280_read_byte(BME280_DIG_P1_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P1_LSB_REG)));
 
	dig_P2 = ((int16_t)((bme280_read_byte(BME280_DIG_P2_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P2_LSB_REG)));
 
	dig_P3 = ((int16_t)((bme280_read_byte(BME280_DIG_P3_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P3_LSB_REG)));
 
	dig_P4 = ((int16_t)((bme280_read_byte(BME280_DIG_P4_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P4_LSB_REG)));
 
	dig_P5 = ((int16_t)((bme280_read_byte(BME280_DIG_P5_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P5_LSB_REG)));
 
	dig_P6 = ((int16_t)((bme280_read_byte(BME280_DIG_P6_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P6_LSB_REG)));
 
	dig_P7 = ((int16_t)((bme280_read_byte(BME280_DIG_P7_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P7_LSB_REG)));
 
	dig_P8 = ((int16_t)((bme280_read_byte(BME280_DIG_P8_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P8_LSB_REG)));
 
	dig_P9 = ((int16_t)((bme280_read_byte(BME280_DIG_P9_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_P9_LSB_REG)));
 
 
	dig_H1 = ((uint8_t)(bme280_read_byte(BME280_DIG_H1_REG)));
 
	dig_H2 = ((int16_t)((bme280_read_byte(BME280_DIG_H2_MSB_REG) << 8) + bme280_read_byte(BME280_DIG_H2_LSB_REG)));
 
	dig_H3 = ((uint8_t)(bme280_read_byte(BME280_DIG_H3_REG)));
 
	dig_H4 = ((int16_t)((bme280_read_byte(BME280_DIG_H4_MSB_REG) << 4) + (bme280_read_byte(BME280_DIG_H4_LSB_REG) & 0x0F)));
 
	dig_H5 = ((int16_t)((bme280_read_byte(BME280_DIG_H5_MSB_REG) << 4) + ((bme280_read_byte(BME280_DIG_H4_LSB_REG) >> 4) & 0x0F)));
 
	dig_H6 = ((uint8_t)bme280_read_byte(BME280_DIG_H6_REG));
 
 
	return true;
 
}
 
 
 
// Acquire new readings from sensor and update values in RAM
 
void bme280_update(void)
 
{
 
	uint8_t result[8];
 
	bme280_read(BME280_PRESSURE_MSB_REG, result, 8);
 
 
	pressure = bme280_convert_pressure(result[0] << 12 | result[1] << 4 | (result[2] & 0xf0) << 0) / 256 / 10; // convert to mBar/hPa
 
	temperature = bme280_convert_temperature(result[3] << 12 | result[4] << 4 | (result[5] & 0xf0) << 0); // 0.01C
 
	humidity = bme280_convert_humidity(result[6] << 8 | result[7] << 0) / 1024; // 0.01% RH
 
}
 
 
 
// returns pressure in mb with 0.1mb resolution
 
int32_t bme280_get_pressure(void)
 
{
 
	return pressure;
 
}
 
 
// returns temperature in DegC with 0.01 DegC resolution
 
int32_t bme280_get_temperature(void)
 
{
 
 
	return temperature;
 
}
 
 
// returns humidity in %RH with 0.01% resolution
 
int32_t bme280_get_humidity(void)
 
{
 
 
	return humidity;
 
}
 
 
 
 
 
void bme280_read(uint8_t register_address, uint8_t* data, uint8_t length)
 
{
 
	HAL_I2C_Mem_Read(&hi2c1, BME280_I2C_ADDR, register_address, 1, data, length, 500);
 
}
 
 
uint8_t bme280_read_byte(uint8_t register_address)
 
{
 
	uint8_t result;
 
	bme280_read(register_address, &result, 1);
 
	return result;
 
}
 
 
void bme280_write(uint8_t register_address, uint8_t data)
 
{
 
	//register_address &= 0x7F;
 
	uint8_t data_arr[1];
 
	data_arr[0] = data;
 
	HAL_I2C_Mem_Write(&hi2c1, BME280_I2C_ADDR, register_address, 1, data_arr, 1, 500);
 
}
 
 
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
 
// t_fine carries fine temperature as global value
 
int32_t t_fine;
 
int32_t bme280_convert_temperature(int32_t adc_T)
 
{
 
	int32_t var1, var2, T;
 
	var1 = ((((adc_T>>3) - ((int32_t)dig_T1<<1))) * ((int32_t)dig_T2)) >> 11;
 
	var2 = (((((adc_T>>4) - ((int32_t)dig_T1)) * ((adc_T>>4) - ((int32_t)dig_T1))) >> 12) *
 
			((int32_t)dig_T3)) >> 14;
 
	t_fine = var1 + var2;
 
	T = (t_fine * 5 + 128) >> 8;
 
	return T;
 
}
 
 
 
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
 
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
 
uint32_t bme280_convert_pressure(int32_t adc_P)
 
{
 
	int64_t var1, var2, p;
 
	var1 = ((int64_t)t_fine) - 128000;
 
	var2 = var1 * var1 * (int64_t)dig_P6;
 
	var2 = var2 + ((var1*(int64_t)dig_P5)<<17);
 
	var2 = var2 + (((int64_t)dig_P4)<<35);
 
	var1 = ((var1 * var1 * (int64_t)dig_P3)>>8) + ((var1 * (int64_t)dig_P2)<<12);
 
	var1 = (((((int64_t)1)<<47)+var1))*((int64_t)dig_P1)>>33;
 
	if (var1 == 0)
 
	{
 
		return 0; // avoid exception caused by division by zero
 
	}
 
	p = 1048576-adc_P;
 
	p = (((p<<31)-var2)*3125)/var1;
 
	var1 = (((int64_t)dig_P9) * (p>>13) * (p>>13)) >> 25;
 
	var2 = (((int64_t)dig_P8) * p) >> 19;
 
	p = ((p + var1 + var2) >> 8) + (((int64_t)dig_P7)<<4);
 
	return (uint32_t)p;
 
}
 
 
// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
 
// Output value of “47445” represents 47445/1024 = 46.333 %RH
 
uint32_t bme280_convert_humidity(int32_t adc_H)
 
{
 
	int32_t v_x1_u32r;
 
	v_x1_u32r = (t_fine - ((int32_t)76800));
 
	v_x1_u32r = (((((adc_H << 14) - (((int32_t)dig_H4) << 20) - (((int32_t)dig_H5) * v_x1_u32r)) +
 
			((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)dig_H6)) >> 10) * (((v_x1_u32r *
 
					((int32_t)dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) *
 
					((int32_t)dig_H2) + 8192) >> 14));
 
	v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)dig_H1)) >> 4));
 
	v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
 
	v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
 
	return (uint32_t)(v_x1_u32r>>12);
 
}
 
 
I2C_HandleTypeDef* bme280_get_i2c_handle(void)
 
{
 
	return &hi2c1;
 
}
Source/main.c
Show inline comments
 
@@ -24,7 +24,8 @@
 
 
#include "config.h"
 
#include "error.h"
 
#include "pressure.h"
 
//#include "pressure.h"
 
#include "bme280.h"
 
#include "gps.h"
 
 
#include "system/gpio.h"
 
@@ -48,8 +49,8 @@ int main(void)
 
  si446x_init();
 
  si446x_init();
 
  gps_poweron();
 
  pressure_init();
 
 
//  pressure_init();
 
  bme280_init();
 
  // Software timers
 
  uint32_t last_transmission = HAL_GetTick();
 
  uint32_t last_led = HAL_GetTick();
 
@@ -60,7 +61,8 @@ int main(void)
 
	  if(HAL_GetTick() - last_transmission > 700)
 
	  {
 
		  gps_update_data(); // Will always return at 1hz rate (default measurement rate)
 
		  pressure_read();
 
		  //pressure_read();
 
		  bme280_update();
 
		  while(afsk_busy()); // ensure previous message finished
 
		  aprs_send();
 
Source/system/interrupts.c
Show inline comments
 
@@ -8,7 +8,7 @@
 
#include "stm32f0xx.h"
 
#include "system/gpio.h"
 
#include "aprs/afsk.h"
 
#include "pressure.h"
 
#include "bme280.h"
 
#include "system/adc.h"
 
 
// Systick
 
@@ -33,10 +33,10 @@ void TIM1_BRK_UP_TRG_COM_IRQHandler(void
 
// Handle I2C interrupts
 
void I2C1_IRQHandler(void)
 
{
 
	if (pressure_get_i2c_handle()->Instance->ISR & (I2C_FLAG_BERR | I2C_FLAG_ARLO | I2C_FLAG_OVR)) {
 
		HAL_I2C_ER_IRQHandler(pressure_get_i2c_handle());
 
	if (bme280_get_i2c_handle()->Instance->ISR & (I2C_FLAG_BERR | I2C_FLAG_ARLO | I2C_FLAG_OVR)) {
 
		HAL_I2C_ER_IRQHandler(bme280_get_i2c_handle());
 
	} else {
 
		HAL_I2C_EV_IRQHandler(pressure_get_i2c_handle());
 
		HAL_I2C_EV_IRQHandler(bme280_get_i2c_handle());
 
	}
 
}
 
0 comments (0 inline, 0 general)