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

BME280.cpp

Committer:
j_rocket_boy
Date:
2018-07-11
Revision:
8:c5f2c8022931
Parent:
4:4c4e3ec9a2c4

File content as of revision 8:c5f2c8022931:

// -*- coding: utf-8 -*-
/**
 @file      BME280.cpp
 @brief     MBE280のライブラリ
 
 @author    D.Nakayama
 @version   1.0
 @date      2018-07-10  D.Nakayama  Written for C++/mbed.
 
 
 @see 
 Copyright (C) 2018 D.Nakayama.
 Released under the MIT license.
 http://opensource.org/licenses/mit-license.php
 
*/

#include "mbed.h"
#include "BME280.h"
#include "i2c_general_io.h"

//コンストラクタ1
BME280::BME280(PinName sda, PinName scl, 
    char mode,
    char press_sample,
    char temp_sample,
    char hum_sample,
    char filter,
    char stanby)
    :
    i2c_p(new GEN_I2C(sda, scl)), 
    sensor(*i2c_p)
{
    _mode         = mode;
    _press_sample = press_sample;
    _temp_sample  = temp_sample;
    _hum_sample   = hum_sample;
    _filter       = filter;
    _stanby       = stanby;
    init();
}

//コンストラクタ2
BME280::BME280(GEN_I2C &i2c_obj,
    char mode,
    char press_sample,
    char temp_sample,
    char hum_sample,
    char filter,
    char stanby)
    :
    i2c_p(NULL), 
    sensor(i2c_obj)
{
    _mode         = mode;
    _press_sample = press_sample;
    _temp_sample  = temp_sample;
    _hum_sample   = hum_sample;
    _filter       = filter;
    _stanby       = stanby;
    init();
}

//デストラクタ
BME280::~BME280()
{
    if (NULL != i2c_p)
        delete  i2c_p;
}

//センサーからデータ読み取り
void BME280::read_sensor(void){
        char sensor_raw_data[8];
        long signed int T,P,H;         //ADC読み込み後温度,気圧,湿度の生データ
        long signed int T_cor;         //温度の補正データ
        long unsigned int P_cor,H_cor;   //気圧,湿度の補正データ


        //読み込み
        
        //ノーマルモードでないとき
        if( _mode != BME280_NORMAL_MODE ){      
            set_force_mode();                   //強制モードで測定開始
            while(BME280_STATUS_IS_MEASURING);  //測定待ち
        }

        sensor.read_reg(BME280_add, BME280_PRESS_MSB, sensor_raw_data, 8); //PRESS_MSBレジスタから8バイト読み込み

        //ビットシフトしてデータを結合
        T = sensor_raw_data[3] << 12 | sensor_raw_data[4] << 4 | sensor_raw_data[5] >> 4 ;
        P = sensor_raw_data[0] << 12 | sensor_raw_data[1] << 4 | sensor_raw_data[2] >> 4 ;
        H = sensor_raw_data[6] <<  8 | sensor_raw_data[7];


        //補正
        T_cor = BME280_compensate_T_int32(T);
        P_cor = BME280_compensate_P_int64(P);        
        H_cor = BME280_compensate_H_int32(H);


        //不動小数点数に直す        
        press = P_cor / 256.0;      //単位Pa
        temp  = T_cor / 100.0;      //単位℃
        hum   = H_cor / 1024.0;     //単位%

}

//強制測定モードをセットする関数。
inline void BME280::set_force_mode(void){
    sensor.write_reg(BME280_add, BME280_CTRL_MEAS, (_press_sample & 0x1C) | (_temp_sample & 0xE0) | BME280_FORCE_MODE );
}


//データシートより,補正関数
// 温度を℃で返します。分解能は0.01℃です。「5123」の出力値は、51.23℃に相当します。
// t_fineは、グローバル値として細かい温度値を持ちます。
long signed int BME280::BME280_compensate_T_int32(long signed int adc_T){
    long signed int var1, var2, T;
    var1 = ((((adc_T>>3) - ((long signed int)dig_T1<<1))) * ((long signed int)dig_T2)) >> 11;
    var2 = (((((adc_T>>4) - ((long signed int)dig_T1)) * ((adc_T>>4) - ((long signed int)dig_T1))) >> 12) *
    ((long signed int)dig_T3)) >> 14;
    t_fine = var1 + var2;
    T = (t_fine * 5 + 128) >> 8;
    return T;
}

// 圧力(Pa)を、Q24.8形式の符号なし32ビット整数として返します。(24個の整数ビットと8個の小数ビット)
// 「24674867」の出力値は、24674867/256 = 96386.2Pa = 963.862hPaに相当します。
long unsigned int BME280::BME280_compensate_P_int64(long signed int adc_P){
    long long signed int var1, var2, p;
    var1 = ((long long signed int)t_fine) - 128000;
    var2 = var1 * var1 * (long long signed int)dig_P6;
    var2 = var2 + ((var1*(long long signed int)dig_P5)<<17);
    var2 = var2 + (((long long signed int)dig_P4)<<35);
    var1 = ((var1 * var1 * (long long signed int)dig_P3)>>8) + ((var1 * (long long signed int)dig_P2)<<12);
    var1 = (((((long long signed int)1)<<47)+var1))*((long long signed int)dig_P1)>>33;
    if (var1 == 0){
        return 0; // ゼロ除算による例外を避ける。
    }
    p = 1048576-adc_P;
    p = (((p<<31)-var2)*3125)/var1;
    var1 = (((long long signed int)dig_P9) * (p>>13) * (p>>13)) >> 25;
    var2 = (((long long signed int)dig_P8) * p) >> 19;
    p = ((p + var1 + var2) >> 8) + (((long long signed int)dig_P7)<<4);
    return (long unsigned int)p;
}

// 湿度(%RH)を、Q22.10形式の符号なし32ビット整数として返します。(22個の整数と10個の小数ビット)
// 「47445」の出力値は、47445/1024 = 46.333%RHに相当します。
long unsigned int BME280::BME280_compensate_H_int32(long signed int adc_H){
    long signed int v_x1_u32r;
    v_x1_u32r = (t_fine - ((long signed int)76800));
    v_x1_u32r = (((((adc_H << 14) - (((long signed int)dig_H4) << 20) - (((long signed int)dig_H5) * v_x1_u32r)) +
    ((long signed int)16384)) >> 15) * (((((((v_x1_u32r * ((long signed int)dig_H6)) >> 10) * (((v_x1_u32r *
    ((long signed int)dig_H3)) >> 11) + ((long signed int)32768))) >> 10) + ((long signed int)2097152)) *
    ((long signed int)dig_H2) + 8192) >> 14));
    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((long signed int)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 (long unsigned int)(v_x1_u32r>>12);
}
//補正関数終わり

//初期化関数
void BME280::init(void){

    char calib[32] = {0};   //補正係数読み取り用
    char reg_data;          //レジスタ読み取り用

    //リセット
    sensor.write_reg(BME280_add, BME280_RESET_REG, BME280_RESET_VALUE);
    
    //ID読み込み
    reg_data = sensor.read_reg(BME280_add,BME280_ID);  
    if(reg_data != BME280_ID_VALUE){               //ID不一致エラー
        printf("error\n");
        while(1);
    }

    //不揮発メモリのデータのレジスタコピー待ち    
    while(BME280_STATUS_IS_COPYING);

    //ADC補償式用定数読み込み
    sensor.read_reg(BME280_add, BME280_CALIB00, &(calib[0]), 24);
    sensor.read_reg(BME280_add, BME280_CALIB25, &(calib[24]), 1);
    sensor.read_reg(BME280_add, BME280_CALIB26, &(calib[25]), 7);

    //ビットシフトして対応する変数に格納(温度補正係数)
    dig_T1 = calib[ 0] | (calib[ 1] << 8);
    dig_T2 = calib[ 2] | (calib[ 3] << 8);
    dig_T3 = calib[ 4] | (calib[ 5] << 8);

    //ビットシフトして対応する変数に格納(気圧補正係数)
    dig_P1 = calib[ 6] | (calib[ 7] << 8);
    dig_P2 = calib[ 8] | (calib[ 9] << 8);
    dig_P3 = calib[10] | (calib[11] << 8);
    dig_P4 = calib[12] | (calib[13] << 8);
    dig_P5 = calib[14] | (calib[15] << 8);
    dig_P6 = calib[16] | (calib[17] << 8);
    dig_P7 = calib[18] | (calib[19] << 8);
    dig_P8 = calib[20] | (calib[21] << 8);
    dig_P9 = calib[22] | (calib[23] << 8);

    //ビットシフトして対応する変数に格納(湿度補正係数)
    dig_H1 = calib[24];
    dig_H2 = calib[25] | (calib[26] << 8);
    dig_H3 = calib[27];
    dig_H4 = (calib[28]<<4) | (calib[29] & 0x0F);
    dig_H5 = ((calib[29]>>4) & 0x0F) | (calib[30] << 4);
    dig_H6 = calib[31];

    //センサ設定
    sensor.write_reg(BME280_add, BME280_CTRL_HUM , (_hum_sample & 0x07) );
    sensor.write_reg(BME280_add, BME280_CTRL_MEAS, (_press_sample & 0x1C) | (_temp_sample & 0xE0) | (_mode & 0x03) );
    sensor.write_reg(BME280_add, BME280_CONFIG   , (_stanby & 0xE0) | (_filter & 0x1C) );

}