BME280にアクセスするためのライブラリ

Committer:
j_rocket_boy
Date:
Wed Jul 11 16:28:32 2018 +0000
Revision:
8:c5f2c8022931
Parent:
4:4c4e3ec9a2c4
modify license year

Who changed what in which revision?

UserRevisionLine numberNew contents of line
j_rocket_boy 4:4c4e3ec9a2c4 1 // -*- coding: utf-8 -*-
j_rocket_boy 4:4c4e3ec9a2c4 2 /**
j_rocket_boy 4:4c4e3ec9a2c4 3 @file BME280.cpp
j_rocket_boy 4:4c4e3ec9a2c4 4 @brief MBE280のライブラリ
j_rocket_boy 4:4c4e3ec9a2c4 5
j_rocket_boy 4:4c4e3ec9a2c4 6 @author D.Nakayama
j_rocket_boy 4:4c4e3ec9a2c4 7 @version 1.0
j_rocket_boy 4:4c4e3ec9a2c4 8 @date 2018-07-10 D.Nakayama Written for C++/mbed.
j_rocket_boy 4:4c4e3ec9a2c4 9
j_rocket_boy 4:4c4e3ec9a2c4 10
j_rocket_boy 4:4c4e3ec9a2c4 11 @see
j_rocket_boy 8:c5f2c8022931 12 Copyright (C) 2018 D.Nakayama.
j_rocket_boy 4:4c4e3ec9a2c4 13 Released under the MIT license.
j_rocket_boy 4:4c4e3ec9a2c4 14 http://opensource.org/licenses/mit-license.php
j_rocket_boy 4:4c4e3ec9a2c4 15
j_rocket_boy 4:4c4e3ec9a2c4 16 */
j_rocket_boy 4:4c4e3ec9a2c4 17
j_rocket_boy 0:95f2b96cdc7f 18 #include "mbed.h"
j_rocket_boy 0:95f2b96cdc7f 19 #include "BME280.h"
j_rocket_boy 0:95f2b96cdc7f 20 #include "i2c_general_io.h"
j_rocket_boy 0:95f2b96cdc7f 21
j_rocket_boy 3:df1107ddf502 22 //コンストラクタ1
j_rocket_boy 3:df1107ddf502 23 BME280::BME280(PinName sda, PinName scl,
j_rocket_boy 3:df1107ddf502 24 char mode,
j_rocket_boy 3:df1107ddf502 25 char press_sample,
j_rocket_boy 3:df1107ddf502 26 char temp_sample,
j_rocket_boy 3:df1107ddf502 27 char hum_sample,
j_rocket_boy 3:df1107ddf502 28 char filter,
j_rocket_boy 3:df1107ddf502 29 char stanby)
j_rocket_boy 0:95f2b96cdc7f 30 :
j_rocket_boy 0:95f2b96cdc7f 31 i2c_p(new GEN_I2C(sda, scl)),
j_rocket_boy 0:95f2b96cdc7f 32 sensor(*i2c_p)
j_rocket_boy 0:95f2b96cdc7f 33 {
j_rocket_boy 3:df1107ddf502 34 _mode = mode;
j_rocket_boy 3:df1107ddf502 35 _press_sample = press_sample;
j_rocket_boy 3:df1107ddf502 36 _temp_sample = temp_sample;
j_rocket_boy 3:df1107ddf502 37 _hum_sample = hum_sample;
j_rocket_boy 3:df1107ddf502 38 _filter = filter;
j_rocket_boy 3:df1107ddf502 39 _stanby = stanby;
j_rocket_boy 0:95f2b96cdc7f 40 init();
j_rocket_boy 0:95f2b96cdc7f 41 }
j_rocket_boy 0:95f2b96cdc7f 42
j_rocket_boy 3:df1107ddf502 43 //コンストラクタ2
j_rocket_boy 3:df1107ddf502 44 BME280::BME280(GEN_I2C &i2c_obj,
j_rocket_boy 3:df1107ddf502 45 char mode,
j_rocket_boy 3:df1107ddf502 46 char press_sample,
j_rocket_boy 3:df1107ddf502 47 char temp_sample,
j_rocket_boy 3:df1107ddf502 48 char hum_sample,
j_rocket_boy 3:df1107ddf502 49 char filter,
j_rocket_boy 3:df1107ddf502 50 char stanby)
j_rocket_boy 0:95f2b96cdc7f 51 :
j_rocket_boy 0:95f2b96cdc7f 52 i2c_p(NULL),
j_rocket_boy 0:95f2b96cdc7f 53 sensor(i2c_obj)
j_rocket_boy 0:95f2b96cdc7f 54 {
j_rocket_boy 3:df1107ddf502 55 _mode = mode;
j_rocket_boy 3:df1107ddf502 56 _press_sample = press_sample;
j_rocket_boy 3:df1107ddf502 57 _temp_sample = temp_sample;
j_rocket_boy 3:df1107ddf502 58 _hum_sample = hum_sample;
j_rocket_boy 3:df1107ddf502 59 _filter = filter;
j_rocket_boy 3:df1107ddf502 60 _stanby = stanby;
j_rocket_boy 0:95f2b96cdc7f 61 init();
j_rocket_boy 0:95f2b96cdc7f 62 }
j_rocket_boy 0:95f2b96cdc7f 63
j_rocket_boy 3:df1107ddf502 64 //デストラクタ
j_rocket_boy 0:95f2b96cdc7f 65 BME280::~BME280()
j_rocket_boy 0:95f2b96cdc7f 66 {
j_rocket_boy 0:95f2b96cdc7f 67 if (NULL != i2c_p)
j_rocket_boy 0:95f2b96cdc7f 68 delete i2c_p;
j_rocket_boy 0:95f2b96cdc7f 69 }
j_rocket_boy 0:95f2b96cdc7f 70
j_rocket_boy 3:df1107ddf502 71 //センサーからデータ読み取り
j_rocket_boy 0:95f2b96cdc7f 72 void BME280::read_sensor(void){
j_rocket_boy 0:95f2b96cdc7f 73 char sensor_raw_data[8];
j_rocket_boy 1:0dbf59c6e564 74 long signed int T,P,H; //ADC読み込み後温度,気圧,湿度の生データ
j_rocket_boy 1:0dbf59c6e564 75 long signed int T_cor; //温度の補正データ
j_rocket_boy 1:0dbf59c6e564 76 long unsigned int P_cor,H_cor; //気圧,湿度の補正データ
j_rocket_boy 0:95f2b96cdc7f 77
j_rocket_boy 3:df1107ddf502 78
j_rocket_boy 0:95f2b96cdc7f 79 //読み込み
j_rocket_boy 3:df1107ddf502 80
j_rocket_boy 3:df1107ddf502 81 //ノーマルモードでないとき
j_rocket_boy 3:df1107ddf502 82 if( _mode != BME280_NORMAL_MODE ){
j_rocket_boy 3:df1107ddf502 83 set_force_mode(); //強制モードで測定開始
j_rocket_boy 3:df1107ddf502 84 while(BME280_STATUS_IS_MEASURING); //測定待ち
j_rocket_boy 3:df1107ddf502 85 }
j_rocket_boy 3:df1107ddf502 86
j_rocket_boy 3:df1107ddf502 87 sensor.read_reg(BME280_add, BME280_PRESS_MSB, sensor_raw_data, 8); //PRESS_MSBレジスタから8バイト読み込み
j_rocket_boy 3:df1107ddf502 88
j_rocket_boy 3:df1107ddf502 89 //ビットシフトしてデータを結合
j_rocket_boy 0:95f2b96cdc7f 90 T = sensor_raw_data[3] << 12 | sensor_raw_data[4] << 4 | sensor_raw_data[5] >> 4 ;
j_rocket_boy 0:95f2b96cdc7f 91 P = sensor_raw_data[0] << 12 | sensor_raw_data[1] << 4 | sensor_raw_data[2] >> 4 ;
j_rocket_boy 0:95f2b96cdc7f 92 H = sensor_raw_data[6] << 8 | sensor_raw_data[7];
j_rocket_boy 0:95f2b96cdc7f 93
j_rocket_boy 3:df1107ddf502 94
j_rocket_boy 0:95f2b96cdc7f 95 //補正
j_rocket_boy 0:95f2b96cdc7f 96 T_cor = BME280_compensate_T_int32(T);
j_rocket_boy 0:95f2b96cdc7f 97 P_cor = BME280_compensate_P_int64(P);
j_rocket_boy 0:95f2b96cdc7f 98 H_cor = BME280_compensate_H_int32(H);
j_rocket_boy 3:df1107ddf502 99
j_rocket_boy 0:95f2b96cdc7f 100
j_rocket_boy 3:df1107ddf502 101 //不動小数点数に直す
j_rocket_boy 3:df1107ddf502 102 press = P_cor / 256.0; //単位Pa
j_rocket_boy 3:df1107ddf502 103 temp = T_cor / 100.0; //単位℃
j_rocket_boy 3:df1107ddf502 104 hum = H_cor / 1024.0; //単位%
j_rocket_boy 3:df1107ddf502 105
j_rocket_boy 0:95f2b96cdc7f 106 }
j_rocket_boy 0:95f2b96cdc7f 107
j_rocket_boy 3:df1107ddf502 108 //強制測定モードをセットする関数。
j_rocket_boy 3:df1107ddf502 109 inline void BME280::set_force_mode(void){
j_rocket_boy 3:df1107ddf502 110 sensor.write_reg(BME280_add, BME280_CTRL_MEAS, (_press_sample & 0x1C) | (_temp_sample & 0xE0) | BME280_FORCE_MODE );
j_rocket_boy 0:95f2b96cdc7f 111 }
j_rocket_boy 0:95f2b96cdc7f 112
j_rocket_boy 0:95f2b96cdc7f 113
j_rocket_boy 0:95f2b96cdc7f 114 //データシートより,補正関数
j_rocket_boy 0:95f2b96cdc7f 115 // 温度を℃で返します。分解能は0.01℃です。「5123」の出力値は、51.23℃に相当します。
j_rocket_boy 0:95f2b96cdc7f 116 // t_fineは、グローバル値として細かい温度値を持ちます。
j_rocket_boy 1:0dbf59c6e564 117 long signed int BME280::BME280_compensate_T_int32(long signed int adc_T){
j_rocket_boy 1:0dbf59c6e564 118 long signed int var1, var2, T;
j_rocket_boy 1:0dbf59c6e564 119 var1 = ((((adc_T>>3) - ((long signed int)dig_T1<<1))) * ((long signed int)dig_T2)) >> 11;
j_rocket_boy 1:0dbf59c6e564 120 var2 = (((((adc_T>>4) - ((long signed int)dig_T1)) * ((adc_T>>4) - ((long signed int)dig_T1))) >> 12) *
j_rocket_boy 1:0dbf59c6e564 121 ((long signed int)dig_T3)) >> 14;
j_rocket_boy 0:95f2b96cdc7f 122 t_fine = var1 + var2;
j_rocket_boy 0:95f2b96cdc7f 123 T = (t_fine * 5 + 128) >> 8;
j_rocket_boy 0:95f2b96cdc7f 124 return T;
j_rocket_boy 0:95f2b96cdc7f 125 }
j_rocket_boy 0:95f2b96cdc7f 126
j_rocket_boy 0:95f2b96cdc7f 127 // 圧力(Pa)を、Q24.8形式の符号なし32ビット整数として返します。(24個の整数ビットと8個の小数ビット)
j_rocket_boy 0:95f2b96cdc7f 128 // 「24674867」の出力値は、24674867/256 = 96386.2Pa = 963.862hPaに相当します。
j_rocket_boy 1:0dbf59c6e564 129 long unsigned int BME280::BME280_compensate_P_int64(long signed int adc_P){
j_rocket_boy 1:0dbf59c6e564 130 long long signed int var1, var2, p;
j_rocket_boy 1:0dbf59c6e564 131 var1 = ((long long signed int)t_fine) - 128000;
j_rocket_boy 1:0dbf59c6e564 132 var2 = var1 * var1 * (long long signed int)dig_P6;
j_rocket_boy 1:0dbf59c6e564 133 var2 = var2 + ((var1*(long long signed int)dig_P5)<<17);
j_rocket_boy 1:0dbf59c6e564 134 var2 = var2 + (((long long signed int)dig_P4)<<35);
j_rocket_boy 1:0dbf59c6e564 135 var1 = ((var1 * var1 * (long long signed int)dig_P3)>>8) + ((var1 * (long long signed int)dig_P2)<<12);
j_rocket_boy 1:0dbf59c6e564 136 var1 = (((((long long signed int)1)<<47)+var1))*((long long signed int)dig_P1)>>33;
j_rocket_boy 0:95f2b96cdc7f 137 if (var1 == 0){
j_rocket_boy 0:95f2b96cdc7f 138 return 0; // ゼロ除算による例外を避ける。
j_rocket_boy 0:95f2b96cdc7f 139 }
j_rocket_boy 0:95f2b96cdc7f 140 p = 1048576-adc_P;
j_rocket_boy 0:95f2b96cdc7f 141 p = (((p<<31)-var2)*3125)/var1;
j_rocket_boy 1:0dbf59c6e564 142 var1 = (((long long signed int)dig_P9) * (p>>13) * (p>>13)) >> 25;
j_rocket_boy 1:0dbf59c6e564 143 var2 = (((long long signed int)dig_P8) * p) >> 19;
j_rocket_boy 1:0dbf59c6e564 144 p = ((p + var1 + var2) >> 8) + (((long long signed int)dig_P7)<<4);
j_rocket_boy 1:0dbf59c6e564 145 return (long unsigned int)p;
j_rocket_boy 0:95f2b96cdc7f 146 }
j_rocket_boy 0:95f2b96cdc7f 147
j_rocket_boy 0:95f2b96cdc7f 148 // 湿度(%RH)を、Q22.10形式の符号なし32ビット整数として返します。(22個の整数と10個の小数ビット)
j_rocket_boy 0:95f2b96cdc7f 149 // 「47445」の出力値は、47445/1024 = 46.333%RHに相当します。
j_rocket_boy 1:0dbf59c6e564 150 long unsigned int BME280::BME280_compensate_H_int32(long signed int adc_H){
j_rocket_boy 1:0dbf59c6e564 151 long signed int v_x1_u32r;
j_rocket_boy 1:0dbf59c6e564 152 v_x1_u32r = (t_fine - ((long signed int)76800));
j_rocket_boy 1:0dbf59c6e564 153 v_x1_u32r = (((((adc_H << 14) - (((long signed int)dig_H4) << 20) - (((long signed int)dig_H5) * v_x1_u32r)) +
j_rocket_boy 1:0dbf59c6e564 154 ((long signed int)16384)) >> 15) * (((((((v_x1_u32r * ((long signed int)dig_H6)) >> 10) * (((v_x1_u32r *
j_rocket_boy 1:0dbf59c6e564 155 ((long signed int)dig_H3)) >> 11) + ((long signed int)32768))) >> 10) + ((long signed int)2097152)) *
j_rocket_boy 1:0dbf59c6e564 156 ((long signed int)dig_H2) + 8192) >> 14));
j_rocket_boy 1:0dbf59c6e564 157 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((long signed int)dig_H1)) >> 4));
j_rocket_boy 0:95f2b96cdc7f 158 v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
j_rocket_boy 0:95f2b96cdc7f 159 v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
j_rocket_boy 1:0dbf59c6e564 160 return (long unsigned int)(v_x1_u32r>>12);
j_rocket_boy 0:95f2b96cdc7f 161 }
j_rocket_boy 0:95f2b96cdc7f 162 //補正関数終わり
j_rocket_boy 0:95f2b96cdc7f 163
j_rocket_boy 3:df1107ddf502 164 //初期化関数
j_rocket_boy 0:95f2b96cdc7f 165 void BME280::init(void){
j_rocket_boy 3:df1107ddf502 166
j_rocket_boy 3:df1107ddf502 167 char calib[32] = {0}; //補正係数読み取り用
j_rocket_boy 3:df1107ddf502 168 char reg_data; //レジスタ読み取り用
j_rocket_boy 0:95f2b96cdc7f 169
j_rocket_boy 3:df1107ddf502 170 //リセット
j_rocket_boy 3:df1107ddf502 171 sensor.write_reg(BME280_add, BME280_RESET_REG, BME280_RESET_VALUE);
j_rocket_boy 3:df1107ddf502 172
j_rocket_boy 3:df1107ddf502 173 //ID読み込み
j_rocket_boy 3:df1107ddf502 174 reg_data = sensor.read_reg(BME280_add,BME280_ID);
j_rocket_boy 3:df1107ddf502 175 if(reg_data != BME280_ID_VALUE){ //ID不一致エラー
j_rocket_boy 0:95f2b96cdc7f 176 printf("error\n");
j_rocket_boy 0:95f2b96cdc7f 177 while(1);
j_rocket_boy 0:95f2b96cdc7f 178 }
j_rocket_boy 3:df1107ddf502 179
j_rocket_boy 3:df1107ddf502 180 //不揮発メモリのデータのレジスタコピー待ち
j_rocket_boy 3:df1107ddf502 181 while(BME280_STATUS_IS_COPYING);
j_rocket_boy 0:95f2b96cdc7f 182
j_rocket_boy 0:95f2b96cdc7f 183 //ADC補償式用定数読み込み
j_rocket_boy 3:df1107ddf502 184 sensor.read_reg(BME280_add, BME280_CALIB00, &(calib[0]), 24);
j_rocket_boy 3:df1107ddf502 185 sensor.read_reg(BME280_add, BME280_CALIB25, &(calib[24]), 1);
j_rocket_boy 3:df1107ddf502 186 sensor.read_reg(BME280_add, BME280_CALIB26, &(calib[25]), 7);
j_rocket_boy 0:95f2b96cdc7f 187
j_rocket_boy 3:df1107ddf502 188 //ビットシフトして対応する変数に格納(温度補正係数)
j_rocket_boy 0:95f2b96cdc7f 189 dig_T1 = calib[ 0] | (calib[ 1] << 8);
j_rocket_boy 0:95f2b96cdc7f 190 dig_T2 = calib[ 2] | (calib[ 3] << 8);
j_rocket_boy 0:95f2b96cdc7f 191 dig_T3 = calib[ 4] | (calib[ 5] << 8);
j_rocket_boy 0:95f2b96cdc7f 192
j_rocket_boy 3:df1107ddf502 193 //ビットシフトして対応する変数に格納(気圧補正係数)
j_rocket_boy 0:95f2b96cdc7f 194 dig_P1 = calib[ 6] | (calib[ 7] << 8);
j_rocket_boy 0:95f2b96cdc7f 195 dig_P2 = calib[ 8] | (calib[ 9] << 8);
j_rocket_boy 0:95f2b96cdc7f 196 dig_P3 = calib[10] | (calib[11] << 8);
j_rocket_boy 0:95f2b96cdc7f 197 dig_P4 = calib[12] | (calib[13] << 8);
j_rocket_boy 0:95f2b96cdc7f 198 dig_P5 = calib[14] | (calib[15] << 8);
j_rocket_boy 0:95f2b96cdc7f 199 dig_P6 = calib[16] | (calib[17] << 8);
j_rocket_boy 0:95f2b96cdc7f 200 dig_P7 = calib[18] | (calib[19] << 8);
j_rocket_boy 0:95f2b96cdc7f 201 dig_P8 = calib[20] | (calib[21] << 8);
j_rocket_boy 0:95f2b96cdc7f 202 dig_P9 = calib[22] | (calib[23] << 8);
j_rocket_boy 0:95f2b96cdc7f 203
j_rocket_boy 3:df1107ddf502 204 //ビットシフトして対応する変数に格納(湿度補正係数)
j_rocket_boy 0:95f2b96cdc7f 205 dig_H1 = calib[24];
j_rocket_boy 0:95f2b96cdc7f 206 dig_H2 = calib[25] | (calib[26] << 8);
j_rocket_boy 0:95f2b96cdc7f 207 dig_H3 = calib[27];
j_rocket_boy 0:95f2b96cdc7f 208 dig_H4 = (calib[28]<<4) | (calib[29] & 0x0F);
j_rocket_boy 0:95f2b96cdc7f 209 dig_H5 = ((calib[29]>>4) & 0x0F) | (calib[30] << 4);
j_rocket_boy 0:95f2b96cdc7f 210 dig_H6 = calib[31];
j_rocket_boy 0:95f2b96cdc7f 211
j_rocket_boy 0:95f2b96cdc7f 212 //センサ設定
j_rocket_boy 3:df1107ddf502 213 sensor.write_reg(BME280_add, BME280_CTRL_HUM , (_hum_sample & 0x07) );
j_rocket_boy 3:df1107ddf502 214 sensor.write_reg(BME280_add, BME280_CTRL_MEAS, (_press_sample & 0x1C) | (_temp_sample & 0xE0) | (_mode & 0x03) );
j_rocket_boy 3:df1107ddf502 215 sensor.write_reg(BME280_add, BME280_CONFIG , (_stanby & 0xE0) | (_filter & 0x1C) );
j_rocket_boy 0:95f2b96cdc7f 216
j_rocket_boy 0:95f2b96cdc7f 217 }
j_rocket_boy 0:95f2b96cdc7f 218
j_rocket_boy 0:95f2b96cdc7f 219