BME280をI2CとSPIで使用するためのライブラリ。
Dependents: BNO055_BME280_ Yabusame2_gyro GRhanawaizman
BME280.cpp
- Committer:
- Yajirushi
- Date:
- 2016-11-29
- Revision:
- 0:2baa0f77d4d2
File content as of revision 0:2baa0f77d4d2:
#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; }