BME280をI2CとSPIで使用するためのライブラリ。

Dependents:   BNO055_BME280_ Yabusame2_gyro GRhanawaizman

Revision:
0:2baa0f77d4d2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BME280.cpp	Tue Nov 29 02:58:53 2016 +0000
@@ -0,0 +1,722 @@
+#include "BME280.h"
+
+//ショートカット
+#define CS_ACTIVE cs->write(0)
+#define CS_INACTIVE cs->write(1)
+
+BME280_CTRL::BME280_CTRL(){
+    interface_mode = 0;
+}
+
+BME280_CTRL::~BME280_CTRL(){}
+
+char BME280_CTRL::getInterfaceMode(){
+    return interface_mode;
+}
+
+void BME280_CTRL::init(){}
+char BME280_CTRL::rr(char regAddr){return 0x00;}
+char BME280_CTRL::rrc(char startRegAddr, char *receiveBytes, char length){return 0x00;}
+char BME280_CTRL::wr(char regAddr, char wBytes){return 0x00;}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+BME280_SPI_CTRL::BME280_SPI_CTRL(SPI* si, DigitalOut* spi_cs, unsigned int speedHz){
+    iface = si;
+    cs = spi_cs;
+    speed = speedHz;
+    interface_mode = 1;
+}
+
+BME280_SPI_CTRL::~BME280_SPI_CTRL(){
+    delete iface;
+    delete cs;
+}
+
+void BME280_SPI_CTRL::init(){
+    CS_INACTIVE;
+
+    iface->format(8, 3);
+    iface->frequency(speed);
+    wait_ms(5);
+}
+
+char BME280_SPI_CTRL::rr(char regAddr){
+    char ret = 0xFF;
+
+    //CS立ち下げ
+    CS_ACTIVE;
+
+    //読み取りモードでレジスタ指定
+    iface->write(0x80 | (regAddr & 0x7F));
+
+    //返答のためダミー送信
+    ret = iface->write(0x00);
+
+    //CS立ち上げ
+    CS_INACTIVE;
+
+    return ret;
+}
+
+char BME280_SPI_CTRL::rrc(char startRegAddr, char *receiveBytes, char length){
+    //最大連続読み取りは42byteまで
+    if(length < 0 || length > 42) return -1;
+
+    //CS立ち下げ
+    CS_ACTIVE;
+
+    //読み取りモードでレジスタ指定
+    iface->write(0x80 | (startRegAddr & 0x7F));
+
+    //返答のためlengthの数だけダミー送信
+    for(int i=0; i<length; i++){
+        receiveBytes[i] = iface->write(0x00);
+    }
+
+    //CS立ち上げ
+    CS_INACTIVE;
+
+    return 1;
+}
+
+char BME280_SPI_CTRL::wr(char regAddr, char wBytes){
+    char ret = 0xFF;
+
+    //CS立ち下げ
+    CS_ACTIVE;
+
+    //書き込みモードでレジスタ指定
+    iface->write(regAddr & 0x7F);
+
+    //値を書き込み
+    ret = iface->write(wBytes);
+
+    //CS立ち上げ
+    CS_INACTIVE;
+
+    //3-WIRE SPI判定
+    if(regAddr == BME280R_CONFIG){
+        interface_mode = (wBytes & 0x01)? 2 : 1;
+    }
+
+    return ret;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+BME280_I2C_CTRL::BME280_I2C_CTRL(I2C* iic, char addr, unsigned int freq){
+    iface = iic;
+    i2c_writeAddr = addr << 1;
+    i2c_readAddr = i2c_writeAddr + 1;
+    i2c_freq = freq;
+}
+
+BME280_I2C_CTRL::~BME280_I2C_CTRL(){
+    delete iface;
+}
+
+void BME280_I2C_CTRL::init(){
+    iface->frequency(i2c_freq);
+    wait_ms(5);
+}
+
+char BME280_I2C_CTRL::rr(char regAddr){
+    char ary[2];
+
+    ary[0] = regAddr;
+    ary[1] = 0x00;
+
+    iface->write(i2c_writeAddr, ary, 1);
+    iface->read(i2c_readAddr, ary, 1);
+
+    return ary[0];
+}
+
+char BME280_I2C_CTRL::rrc(char startRegAddr, char *receiveBytes, char length){
+    //最大連続読み取りは42byteまで
+    if(length < 0 || length > 42) return -1;
+
+    char ary[2];
+
+    ary[0] = startRegAddr;
+    ary[1] = 0x00;
+
+    iface->write(i2c_writeAddr, ary, 1);
+    iface->read(i2c_readAddr, receiveBytes, length);
+
+    return 1;
+}
+
+char BME280_I2C_CTRL::wr(char regAddr, char wBytes){
+    char ary[2];
+
+    ary[0] = regAddr;
+    ary[1] = wBytes;
+
+    iface->write(i2c_writeAddr, ary, 2);
+
+    return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+BOARDC_BME280::BOARDC_BME280(PinName mosi, PinName miso, PinName sck, PinName scs, unsigned int spdHz){
+    ctrl = new BME280_SPI_CTRL(new SPI(mosi, miso, sck), new DigitalOut(scs), spdHz);
+}
+
+BOARDC_BME280::BOARDC_BME280(SPI* spi, PinName scs, unsigned int spdHz){
+    ctrl = new BME280_SPI_CTRL(spi, new DigitalOut(scs), spdHz);
+}
+
+BOARDC_BME280::BOARDC_BME280(SPI* spi, DigitalOut* spi_cs, unsigned int spdHz){
+    ctrl = new BME280_SPI_CTRL(spi, spi_cs, spdHz);
+}
+
+BOARDC_BME280::BOARDC_BME280(PinName sda, PinName scl, char addr, unsigned int freq){
+    ctrl = new BME280_I2C_CTRL(new I2C(sda, scl), addr, freq);
+}
+
+BOARDC_BME280::BOARDC_BME280(I2C* iic, char addr, unsigned int freq){
+    ctrl = new BME280_I2C_CTRL(iic, addr, freq);
+}
+
+void BOARDC_BME280::initialize(bool initIface){
+    if(initIface){
+        ctrl->init();
+    }
+
+    //設定書き込み(必ずCTRL_HUM→CTRL_MEAS→CONFIGの順に設定)
+    ctrl->wr(BME280R_CTRL_HUM, 0x01); //湿度:オーバーサンプリングx1
+    ctrl->wr(BME280R_CTRL_MEAS, 0x27); //温度:オーバーサンプリングx1,気圧:オーバーサンプリングx1,ノーマルモード
+    ctrl->wr(BME280R_CONFIG, 0xD4); //データ抽出可能時間1000ms,フィルターサンプリングx4
+
+    //3-WIRE SPI使用時(BME280R_CONFIGに設定する値の最下位ビットを1にすると3-WIRE SPIモード)
+    //ctrl->wr(BME280R_CONFIG, 0xD5);
+
+    //データがレジスタにコピーされるまで待つ
+    while(!isReady()) wait_ms(500);
+
+    //補正データ更新
+    updateCalib();
+}
+
+char BOARDC_BME280::getInterfaceMode(){
+    return ctrl->getInterfaceMode();
+}
+
+char BOARDC_BME280::getChipID(){
+    return ctrl->rr(BME280R_ID);
+}
+
+void BOARDC_BME280::reset(){
+    ctrl->wr(BME280R_RESET, 0xB6);
+    wait_ms(1500);
+    initialize();
+}
+
+char BOARDC_BME280::getCTRL_humidity(){
+    return ctrl->rr(BME280R_CTRL_HUM);
+}
+
+void BOARDC_BME280::setCTRL_humidity(char regVal){
+    char meas = ctrl->rr(BME280R_CTRL_MEAS);
+    char config = ctrl->rr(BME280R_CONFIG);
+
+    //必ずCTRL_HUM>CTRL_MEAS>CONFIGの順番
+    ctrl->wr(BME280R_CTRL_HUM, regVal & 0x07);
+    ctrl->wr(BME280R_CTRL_MEAS, meas);
+    ctrl->wr(BME280R_CONFIG, config & 0xFD);
+}
+
+char BOARDC_BME280::getCTRL_measuring(){
+    return ctrl->rr(BME280R_CTRL_MEAS);
+}
+
+void BOARDC_BME280::setCTRL_measuring(char regVal){
+    char hum = ctrl->rr(BME280R_CTRL_HUM);
+    char config = ctrl->rr(BME280R_CONFIG);
+
+    //必ずCTRL_HUM>CTRL_MEAS>CONFIGの順番
+    ctrl->wr(BME280R_CTRL_HUM, hum & 0x07);
+    ctrl->wr(BME280R_CTRL_MEAS, regVal);
+    ctrl->wr(BME280R_CONFIG, config & 0xFD);
+}
+
+unsigned int BOARDC_BME280::getOverSample_P(){
+    char val = (ctrl->rr(BME280R_CTRL_MEAS) >> 2) & 0x07;
+
+    switch(val){
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 2;
+        case 3:
+            return 4;
+        case 4:
+            return 8;
+        case 5:
+            return 16;
+        default:
+            return 16;
+    }
+}
+
+unsigned int BOARDC_BME280::getOverSample_T(){
+    char val = (ctrl->rr(BME280R_CTRL_MEAS) >> 5) & 0x07;
+
+    switch(val){
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 2;
+        case 3:
+            return 4;
+        case 4:
+            return 8;
+        case 5:
+            return 16;
+        default:
+            return 16;
+    }
+}
+
+unsigned int BOARDC_BME280::getOverSample_H(){
+    char val = ctrl->rr(BME280R_CTRL_HUM) & 0x07;
+
+    switch(val){
+        case 0:
+            return 0;
+        case 1:
+            return 1;
+        case 2:
+            return 2;
+        case 3:
+            return 4;
+        case 4:
+            return 8;
+        case 5:
+            return 16;
+        default:
+            return 16;
+    }
+}
+
+void BOARDC_BME280::setOverSample_P(unsigned int oversampling){
+    char hum = ctrl->rr(BME280R_CTRL_HUM);
+    char meas = ctrl->rr(BME280R_CTRL_MEAS);
+    char config = ctrl->rr(BME280R_CONFIG);
+
+    char ovs = 0;
+    switch(oversampling){
+        case 0:
+            ovs = 0;
+            break;
+        case 1:
+            ovs = 1;
+            break;
+        case 2:
+            ovs = 2;
+            break;
+        case 4:
+            ovs = 3;
+            break;
+        case 8:
+            ovs = 4;
+            break;
+        case 16:
+            ovs = 5;
+            break;
+        default:
+            ovs = 0;
+    }
+
+    meas = (meas & 0xE3) | (ovs << 2);
+
+    //必ずCTRL_HUM>CTRL_MEAS>CONFIGの順番
+    ctrl->wr(BME280R_CTRL_HUM, hum & 0x07);
+    ctrl->wr(BME280R_CTRL_MEAS, meas);
+    ctrl->wr(BME280R_CONFIG, config & 0xFD);
+}
+
+void BOARDC_BME280::setOverSample_T(unsigned int oversampling){
+    char hum = ctrl->rr(BME280R_CTRL_HUM);
+    char meas = ctrl->rr(BME280R_CTRL_MEAS);
+    char config = ctrl->rr(BME280R_CONFIG);
+
+    char ovs = 0;
+    switch(oversampling){
+        case 0:
+            ovs = 0;
+            break;
+        case 1:
+            ovs = 1;
+            break;
+        case 2:
+            ovs = 2;
+            break;
+        case 4:
+            ovs = 3;
+            break;
+        case 8:
+            ovs = 4;
+            break;
+        case 16:
+            ovs = 5;
+            break;
+        default:
+            ovs = 0;
+    }
+
+    meas = (meas & 0x1F) | (ovs << 5);
+
+    //必ずCTRL_HUM>CTRL_MEAS>CONFIGの順番
+    ctrl->wr(BME280R_CTRL_HUM, hum & 0x07);
+    ctrl->wr(BME280R_CTRL_MEAS, meas);
+    ctrl->wr(BME280R_CONFIG, config & 0xFD);
+}
+
+void BOARDC_BME280::setOverSample_H(unsigned int oversampling){
+    char meas = ctrl->rr(BME280R_CTRL_MEAS);
+    char config = ctrl->rr(BME280R_CONFIG);
+
+    char ovs = 0;
+    switch(oversampling){
+        case 0:
+            ovs = 0;
+            break;
+        case 1:
+            ovs = 1;
+            break;
+        case 2:
+            ovs = 2;
+            break;
+        case 4:
+            ovs = 3;
+            break;
+        case 8:
+            ovs = 4;
+            break;
+        case 16:
+            ovs = 5;
+            break;
+        default:
+            ovs = 0;
+    }
+
+    //必ずCTRL_HUM>CTRL_MEAS>CONFIGの順番
+    ctrl->wr(BME280R_CTRL_HUM, ovs);
+    ctrl->wr(BME280R_CTRL_MEAS, meas);
+    ctrl->wr(BME280R_CONFIG, config & 0xFD);
+}
+
+char BOARDC_BME280::getConfig(){
+    return ctrl->rr(BME280R_CONFIG);
+}
+
+void BOARDC_BME280::setConfig(char regVal){
+    char hum = ctrl->rr(BME280R_CTRL_HUM);
+    char meas = ctrl->rr(BME280R_CTRL_MEAS);
+
+    //必ずCTRL_HUM>CTRL_MEAS>CONFIGの順番
+    ctrl->wr(BME280R_CTRL_HUM, hum & 0x07);
+    ctrl->wr(BME280R_CTRL_MEAS, meas);
+    ctrl->wr(BME280R_CONFIG, regVal & 0xFD);
+}
+
+char BOARDC_BME280::getStatus(){
+    return ctrl->rr(BME280R_STATUS);
+}
+
+bool BOARDC_BME280::isReady(){
+    return (ctrl->rr(BME280R_STATUS) == 0x00);
+}
+
+char BOARDC_BME280::getMode(){
+    return ctrl->rr(BME280R_CTRL_MEAS) & 0x03;
+}
+
+void BOARDC_BME280::updateCalib(){
+    char ary[33];
+    memset(ary, 0, 33);
+
+    //26byte+7byte連続読み取り
+    //使用されないものはそのまま捨てる
+    ctrl->rrc(BME280R_CALIB00, ary, 26);
+    ctrl->rrc(BME280R_CALIB26, ary + 26, 7);
+
+    T1 = (ary[1] << 8) | ary[0];
+    T2 = (ary[3] << 8) | ary[2];
+    T3 = (ary[5] << 8) | ary[4];
+
+    P1 = (ary[7] << 8) | ary[6];
+    P2 = (ary[9] << 8) | ary[8];
+    P3 = (ary[11] << 8) | ary[10];
+    P4 = (ary[13] << 8) | ary[12];
+    P5 = (ary[15] << 8) | ary[14];
+    P6 = (ary[17] << 8) | ary[16];
+    P7 = (ary[19] << 8) | ary[18];
+    P8 = (ary[21] << 8) | ary[20];
+    P9 = (ary[23] << 8) | ary[22];
+
+    H1 = ary[25];
+    H2 = (ary[27] << 8) | ary[26];
+    H3 = ary[28];
+    H4 = (ary[30] & 0x0F) | (ary[29] << 4); //順番注意
+    H5 = (ary[31] << 4) | (ary[30] >> 4);
+    H6 = ary[32];
+}
+
+void BOARDC_BME280::updateCalibT(){
+    char ary[6];
+    memset(ary, 0, 6);
+
+    //6byte連続読み取り
+    ctrl->rrc(BME280R_CALIB00, ary, 6);
+
+    T1 = (ary[1] << 8) | ary[0];
+    T2 = (ary[3] << 8) | ary[2];
+    T3 = (ary[5] << 8) | ary[4];
+}
+
+void BOARDC_BME280::updateCalibP(){
+    char ary[18];
+    memset(ary, 0, 18);
+
+    //18byte連続読み取り
+    ctrl->rrc(BME280R_CALIB06, ary, 18);
+
+    P1 = (ary[1] << 8) | ary[0];
+    P2 = (ary[3] << 8) | ary[2];
+    P3 = (ary[5] << 8) | ary[4];
+    P4 = (ary[7] << 8) | ary[6];
+    P5 = (ary[9] << 8) | ary[8];
+    P6 = (ary[11] << 8) | ary[10];
+    P7 = (ary[13] << 8) | ary[12];
+    P8 = (ary[15] << 8) | ary[14];
+    P9 = (ary[17] << 8) | ary[16];
+}
+
+void BOARDC_BME280::updateCalibH(){
+    char ary[7];
+    memset(ary, 0, 7);
+
+    //7byte連続読み取り
+    ctrl->rrc(BME280R_CALIB26, ary, 7);
+
+    H1 = ctrl->rr(BME280R_CALIB25);
+    H2 = (ary[1] << 8) | ary[0];
+    H3 = ary[2];
+    H4 = (ary[4] & 0x0F) | (ary[3] << 4); //順番注意
+    H5 = (ary[5] << 4) | (ary[4] >> 4);
+    H6 = ary[6];
+}
+
+float BOARDC_BME280::getTemp(unsigned int mode){
+    switch(mode){
+        case 0:
+            return getTemp_Celsius();
+        case 1:
+            return getTemp_Fahrenheit();
+        case 2:
+            return getTemp_Kelvin();
+        default:
+            return getTemp_Celsius();
+    }
+}
+
+float BOARDC_BME280::getTemp_Celsius(){
+    char ary[3];
+    memset(ary, 0, 3);
+
+    //3byte連続読み取り
+    ctrl->rrc(BME280R_TEMP_MSB, ary, 3);
+    signed int adc_T = (ary[0] << 12) | (ary[1] << 4) | (ary[2] >> 4);
+
+    //Compensation formulas(データシートより)
+    signed int var1, var2, T;
+    var1 = ((((adc_T >> 3) - ((signed int)T1 << 1))) * ((signed int)T2)) >> 11;
+    var2 = (((((adc_T >> 4) - ((signed int)T1)) * ((adc_T >> 4) - ((signed int)T1))) >> 12) * ((signed int)T3)) >> 14;
+    t_fine = var1 + var2;
+    T = (t_fine * 5 + 128) >> 8;
+
+    return (((float)T) / 100.0f);
+}
+
+float BOARDC_BME280::getTemp_Fahrenheit(){
+    return ((getTemp_Celsius() * 9.0f) / 5.0f) + 32.0f;
+}
+
+float BOARDC_BME280::getTemp_Kelvin(){
+    return getTemp_Celsius() + 273.15f;
+}
+
+float BOARDC_BME280::getPress(unsigned int mode){
+    switch(mode){
+        case 0:
+            return getPress_Pascal();
+        case 1:
+            return getPress_hPa();
+        case 2:
+            return getPress_psi();
+        default:
+            return getPress_hPa();
+    }
+}
+
+float BOARDC_BME280::getPress_Pascal(){
+    char ary[3];
+    memset(ary, 0, 3);
+
+    //3byte連続読み取り
+    ctrl->rrc(BME280R_PRESS_MSB, ary, 3);
+    signed int adc_P = (ary[0] << 12) | (ary[1] << 4) | (ary[2] >> 4);
+
+    //Compensation formulas(データシートより)
+    signed int var1, var2;
+    unsigned int p;
+    var1 = (((signed int)t_fine) >> 1) - (signed int)64000;
+    var2 = (((var1 >> 2) * (var1 >> 2)) >> 11 ) * ((signed int)P6);
+    var2 = var2 + ((var1 * ((signed int)P5)) << 1);
+    var2 = (var2 >> 2)+(((signed int)P4) << 16);
+    var1 = (((P3 * (((var1 >> 2) * (var1 >> 2)) >> 13 )) >> 3) + ((((signed int)P2) * var1) >> 1)) >> 18;
+    var1 =((((32768 + var1)) * ((signed int)P1)) >> 15);
+    if (var1 == 0){
+        return 0; // avoid exception caused by division by zero
+    }
+    p = (((unsigned int)(((signed int)1048576) - adc_P) - (var2 >> 12))) * 3125;
+    if (p < 0x80000000){
+        p = (p << 1) / ((unsigned int)var1);
+    }else{
+        p = (p / (unsigned int)var1) * 2;
+    }
+    var1 = (((signed int)P9) * ((signed int)(((p >> 3) * (p >> 3)) >> 13))) >> 12;
+    var2 = (((signed int)(p >> 2)) * ((signed int)P8)) >> 13;
+    p = (unsigned int)((signed int)p + ((var1 + var2 + P7) >> 4));
+
+    return (float)(p * 1.0f);
+}
+
+float BOARDC_BME280::getPress_hPa(){
+    return getPress_Pascal() / 100.0f;
+}
+
+float BOARDC_BME280::getPress_psi(){
+    return getPress_Pascal() / 6894.757293168;
+}
+
+float BOARDC_BME280::getHum(){
+    char ary[2];
+    memset(ary, 0, 2);
+
+    //2byte連続読み取り
+    ctrl->rrc(BME280R_HUM_MSB, ary, 2);
+    signed int adc_H = (ary[0] << 8) | ary[1];
+
+    //Compensation formulas(データシートより)
+    signed int v_x1_u32r;
+    v_x1_u32r = (t_fine - ((signed int)76800));
+    v_x1_u32r =
+        (((((adc_H << 14) - (((signed int)H4) << 20) - (((signed int)H5) * v_x1_u32r)) +
+        ((signed int)16384)) >> 15) * (((((((v_x1_u32r * ((signed int)H6)) >> 10) * (((v_x1_u32r *
+        ((signed int)H3)) >> 11) + ((signed int)32768))) >> 10) + ((signed int)2097152)) *
+        ((signed int)H2) + 8192) >> 14));
+    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((signed int)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 (float)(((unsigned int)(v_x1_u32r >> 12)) / 1024.0f);
+}
+
+double BOARDC_BME280::getPress64(unsigned int mode){
+    switch(mode){
+        case 0:
+            return getPress64_Pascal();
+        case 1:
+            return getPress64_hPa();
+        case 2:
+            return getPress64_psi();
+        default:
+            return getPress64_hPa();
+    }
+}
+
+double BOARDC_BME280::getPress64_Pascal(){
+    char ary[3];
+    memset(ary, 0, 3);
+
+    //3byte連続読み取り
+    ctrl->rrc(BME280R_PRESS_MSB, ary, 3);
+    signed int adc_P = (ary[0] << 16) | (ary[1] << 8) | ary[2];
+
+    //倍精度での算出(データシートより)
+    signed long long var1, var2, p;
+    var1 = ((signed long long)t_fine) - 128000;
+    var2 = var1 * var1 * (signed long long)P6;
+    var2 = var2 + ((var1 * (signed long long)P5) << 17);
+    var2 = var2 + (((signed long long)P4)<<35);
+    var1 = ((var1 * var1 * (signed long long)P3) >> 8) + ((var1 * (signed long long)P2) << 12);
+    var1 = (((((signed long long)1) << 47) + var1)) * ((signed long long)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 = (((signed long long)P9) * (p >> 13) * (p >> 13)) >> 25;
+    var2 = (((signed long long)P8) * p) >> 19;
+    p = ((p + var1 + var2) >> 8) + (((signed long long)P7) << 4);
+
+    return (double)((unsigned int)p / 256.0);
+}
+
+double BOARDC_BME280::getPress64_hPa(){
+    return getPress64_Pascal() / 100.0;
+}
+
+double BOARDC_BME280::getPress64_psi(){
+    return getPress64_Pascal() / 6894.757293168;
+}