2022-03-02 11:25:14 +00:00
'use strict' ;
2023-08-18 02:16:52 +00:00
this . rg = null ;
2022-03-02 11:25:14 +00:00
this . i2cBusNo = null ;
this . i2cAddress = null ;
this . i2cHand = null ;
this . I2C _ADDRESS _B = 0x76 ;
this . I2C _ADDRESS _A = 0x77 ;
this . CHIP _ID = 0x58 ;
this . REGISTER _DIG _T1 = 0x88 ;
this . REGISTER _DIG _T2 = 0x8A ;
this . REGISTER _DIG _T3 = 0x8C ;
this . REGISTER _DIG _P1 = 0x8E ;
this . REGISTER _DIG _P2 = 0x90 ;
this . REGISTER _DIG _P3 = 0x92 ;
this . REGISTER _DIG _P4 = 0x94 ;
this . REGISTER _DIG _P5 = 0x96 ;
this . REGISTER _DIG _P6 = 0x98 ;
this . REGISTER _DIG _P7 = 0x9A ;
this . REGISTER _DIG _P8 = 0x9C ;
this . REGISTER _DIG _P9 = 0x9E ;
this . REGISTER _DIG _H1 = 0xA1 ;
this . REGISTER _DIG _H2 = 0xE1 ;
this . REGISTER _DIG _H3 = 0xE3 ;
this . REGISTER _DIG _H4 = 0xE4 ;
this . REGISTER _DIG _H5 = 0xE5 ;
this . REGISTER _DIG _H6 = 0xE7 ;
this . REGISTER _CHIPID = 0xD0 ;
this . REGISTER _RESET = 0xE0 ;
this . REGISTER _CONTROL _HUM = 0xF2 ;
this . REGISTER _CONTROL = 0xF4 ;
this . REGISTER _PRESSURE _DATA = 0xF7 ;
this . REGISTER _TEMP _DATA = 0xFA ;
this . REGISTER _HUMIDITY _DATA = 0xFD ;
2023-08-18 02:16:52 +00:00
exports . init = async ( rg , options ) => {
this . rg = rg ;
2022-03-02 11:25:14 +00:00
this . i2cBusNo = ( options && options . hasOwnProperty ( 'i2cBusNo' ) ) ? options . i2cBusNo : 1 ;
this . i2cAddress = ( options && options . hasOwnProperty ( 'i2cAddress' ) ) ? options . i2cAddress : this . BME280 _DEFAULT _I2C _ADDRESS ( ) ;
2023-08-18 02:16:52 +00:00
this . i2cHand = await this . rg . i2c _open ( this . i2cBusNo , this . i2cAddress , 0 ) ;
2022-03-02 11:25:14 +00:00
let r ;
2023-08-18 02:16:52 +00:00
r = await this . rg . i2c _write _byte _data ( this . i2cHand , this . REGISTER _CHIPID , 0 ) ;
2022-03-02 11:25:14 +00:00
if ( r < 0 ) return r ;
2023-08-18 02:16:52 +00:00
let chipId = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _CHIPID ) ;
2022-03-02 11:25:14 +00:00
if ( chipId !== this . CHIP _ID _BME280 ( ) &&
chipId !== this . CHIP _ID1 _BMP280 ( ) &&
chipId !== this . CHIP _ID2 _BMP280 ( ) &&
chipId !== this . CHIP _ID3 _BMP280 ( ) ) {
return ` Unexpected BMx280 chip ID: 0x ${ chipId . toString ( 16 ) . toUpperCase ( ) } ` ;
}
// console.log(`Found BMx280 chip ID 0x${chipId.toString(16).toUpperCase()} on bus i2c-${this.i2cBusNo}, address 0x${this.i2cAddress.toString(16).toUpperCase()}`);
await this . loadCalibration ( async ( err ) => {
if ( err ) {
return err ;
}
// Humidity 16x oversampling
//
2023-08-18 02:16:52 +00:00
let r = await this . rg . i2c _write _byte _data ( this . i2cHand , this . REGISTER _CONTROL _HUM , 0b00000101 ) ;
2022-03-02 11:25:14 +00:00
if ( r < 0 ) return ` Humidity 16x oversampling error: ${ r } ` ;
// Temperture/pressure 16x oversampling, normal mode
//
2023-08-18 02:16:52 +00:00
r = await this . rg . i2c _write _byte _data ( this . i2cHand , this . REGISTER _CONTROL , 0b10110111 ) ;
2022-03-02 11:25:14 +00:00
if ( r < 0 ) return ` Temperture/pressure 16x oversampling error: ${ r } ` ;
return 0 ;
} ) ;
}
// reset()
//
// Perform a power-on reset procedure. You will need to call init() following a reset()
//
exports . reset = async ( ) => {
const POWER _ON _RESET _CMD = 0xB6 ;
2023-08-18 02:16:52 +00:00
let r = await this . rg . i2c _write _byte _data ( this . i2cHand , this . REGISTER _RESET , POWER _ON _RESET _CMD ) ;
2022-03-02 11:25:14 +00:00
if ( r < 0 ) return ` cannot power-on reset: ${ r } ` ;
else return 0 ;
}
// cancel()
//
// Cancels the sensor and releases resources.
//
exports . cancel = async ( ) => {
if ( this . i2cHand >= 0 ) {
2023-08-18 02:16:52 +00:00
await this . rg . i2c _close ( this . i2cHand ) ;
2022-03-02 11:25:14 +00:00
this . i2cHand = null ;
}
}
exports . readSensorData = async ( ) => {
if ( ! this . cal ) {
return 'You must first call bme280.init()' ;
}
// Grab temperature, humidity, and pressure in a single read
//
2023-08-18 02:16:52 +00:00
let buffer = await this . rg . i2c _read _i2c _block _data ( this . i2cHand , this . REGISTER _PRESSURE _DATA , 8 ) ;
2022-03-02 11:25:14 +00:00
if ( ! buffer ) return ` couldn't grab data ` ;
// Temperature (temperature first since we need t_fine for pressure and humidity)
//
let adc _T = this . uint20 ( buffer [ 3 ] , buffer [ 4 ] , buffer [ 5 ] ) ;
let tvar1 = ( ( ( ( adc _T >> 3 ) - ( this . cal . dig _T1 << 1 ) ) ) * this . cal . dig _T2 ) >> 11 ;
let tvar2 = ( ( ( ( ( adc _T >> 4 ) - this . cal . dig _T1 ) * ( ( adc _T >> 4 ) - this . cal . dig _T1 ) ) >> 12 ) * this . cal . dig _T3 ) >> 14 ;
let t _fine = tvar1 + tvar2 ;
let temperature _C = ( ( t _fine * 5 + 128 ) >> 8 ) / 100 ;
// Pressure
//
let adc _P = this . uint20 ( buffer [ 0 ] , buffer [ 1 ] , buffer [ 2 ] ) ;
let pvar1 = t _fine / 2 - 64000 ;
let pvar2 = pvar1 * pvar1 * this . cal . dig _P6 / 32768 ;
pvar2 = pvar2 + pvar1 * this . cal . dig _P5 * 2 ;
pvar2 = pvar2 / 4 + this . cal . dig _P4 * 65536 ;
pvar1 = ( this . cal . dig _P3 * pvar1 * pvar1 / 524288 + this . cal . dig _P2 * pvar1 ) / 524288 ;
pvar1 = ( 1 + pvar1 / 32768 ) * this . cal . dig _P1 ;
let pressure _hPa = 0 ;
if ( pvar1 !== 0 ) {
let p = 1048576 - adc _P ;
p = ( ( p - pvar2 / 4096 ) * 6250 ) / pvar1 ;
pvar1 = this . cal . dig _P9 * p * p / 2147483648 ;
pvar2 = p * this . cal . dig _P8 / 32768 ;
p = p + ( pvar1 + pvar2 + this . cal . dig _P7 ) / 16 ;
pressure _hPa = p / 100 ;
}
// Humidity (available on the BME280, will be zero on the BMP280 since it has no humidity sensor)
//
let adc _H = this . uint16 ( buffer [ 6 ] , buffer [ 7 ] ) ;
let h = t _fine - 76800 ;
h = ( adc _H - ( this . cal . dig _H4 * 64 + this . cal . dig _H5 / 16384 * h ) ) *
( this . cal . dig _H2 / 65536 * ( 1 + this . cal . dig _H6 / 67108864 * h * ( 1 + this . cal . dig _H3 / 67108864 * h ) ) ) ;
h = h * ( 1 - this . cal . dig _H1 * h / 524288 ) ;
let humidity = ( h > 100 ) ? 100 : ( h < 0 ? 0 : h ) ;
return {
temperature _C : temperature _C ,
humidity : humidity ,
pressure _hPa : pressure _hPa
} ;
}
exports . loadCalibration = async ( callback ) => {
2023-08-18 02:16:52 +00:00
let buffer = await this . rg . i2c _read _i2c _block _data ( this . i2cHand , this . REGISTER _DIG _T1 , 24 ) ;
2022-03-02 11:25:14 +00:00
if ( buffer ) {
2023-08-18 02:16:52 +00:00
let h1 = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _DIG _H1 ) ;
let h2 = await this . rg . i2c _read _word _data ( this . i2cHand , this . REGISTER _DIG _H2 ) ;
let h3 = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _DIG _H3 ) ;
let h4 = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _DIG _H4 ) ;
let h5 = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _DIG _H5 ) ;
let h5 _1 = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _DIG _H5 + 1 ) ;
let h6 = await this . rg . i2c _read _byte _data ( this . i2cHand , this . REGISTER _DIG _H6 ) ;
2022-03-02 11:25:14 +00:00
this . cal = {
dig _T1 : this . uint16 ( buffer [ 1 ] , buffer [ 0 ] ) ,
dig _T2 : this . int16 ( buffer [ 3 ] , buffer [ 2 ] ) ,
dig _T3 : this . int16 ( buffer [ 5 ] , buffer [ 4 ] ) ,
dig _P1 : this . uint16 ( buffer [ 7 ] , buffer [ 6 ] ) ,
dig _P2 : this . int16 ( buffer [ 9 ] , buffer [ 8 ] ) ,
dig _P3 : this . int16 ( buffer [ 11 ] , buffer [ 10 ] ) ,
dig _P4 : this . int16 ( buffer [ 13 ] , buffer [ 12 ] ) ,
dig _P5 : this . int16 ( buffer [ 15 ] , buffer [ 14 ] ) ,
dig _P6 : this . int16 ( buffer [ 17 ] , buffer [ 16 ] ) ,
dig _P7 : this . int16 ( buffer [ 19 ] , buffer [ 18 ] ) ,
dig _P8 : this . int16 ( buffer [ 21 ] , buffer [ 20 ] ) ,
dig _P9 : this . int16 ( buffer [ 23 ] , buffer [ 22 ] ) ,
dig _H1 : h1 ,
dig _H2 : h2 ,
dig _H3 : h3 ,
dig _H4 : ( h4 << 4 ) | ( h5 & 0xF ) ,
dig _H5 : ( h5 _1 << 4 ) | ( h5 >> 4 ) ,
dig _H6 : h6
} ;
// console.log('BME280 cal = ' + JSON.stringify(this.cal, null, 2));
await callback ( ) ;
}
}
exports . BME280 _DEFAULT _I2C _ADDRESS = ( ) => {
return 0x77 ;
}
exports . CHIP _ID1 _BMP280 = ( ) => {
return 0x56 ;
}
exports . CHIP _ID2 _BMP280 = ( ) => {
return 0x57 ;
}
exports . CHIP _ID3 _BMP280 = ( ) => {
return 0x58 ;
}
exports . CHIP _ID _BME280 = ( ) => {
return 0x60 ;
}
exports . int16 = ( msb , lsb ) => {
let val = this . uint16 ( msb , lsb ) ;
return val > 32767 ? ( val - 65536 ) : val ;
}
exports . uint16 = ( msb , lsb ) => {
return msb << 8 | lsb ;
}
exports . uint20 = ( msb , lsb , xlsb ) => {
return ( ( msb << 8 | lsb ) << 8 | xlsb ) >> 4 ;
}
exports . convertCelciusToFahrenheit = ( c ) => {
return c * 9 / 5 + 32 ;
}
exports . convertHectopascalToInchesOfMercury = ( hPa ) => {
return hPa * 0.02952998751 ;
}
exports . convertMetersToFeet = ( m ) => {
return m * 3.28084 ;
}
exports . calculateHeatIndexCelcius = ( temperature _C , humidity ) => {
return - 8.784695 + 1.61139411 * temperature _C + 2.33854900 * humidity +
- 0.14611605 * temperature _C * humidity + - 0.01230809 * Math . pow ( temperature _C , 2 ) +
- 0.01642482 * Math . pow ( humidity , 2 ) + 0.00221173 * Math . pow ( temperature _C , 2 ) * humidity +
0.00072546 * temperature _C * Math . pow ( humidity , 2 ) +
- 0.00000358 * Math . pow ( temperature _C , 2 ) * Math . pow ( humidity , 2 ) ;
}
exports . calculateDewPointCelcius = ( temperature _C , humidity ) => {
return 243.04 * ( Math . log ( humidity / 100.0 ) + ( ( 17.625 * temperature _C ) / ( 243.04 + temperature _C ) ) ) /
( 17.625 - Math . log ( humidity / 100.0 ) - ( ( 17.625 * temperature _C ) / ( 243.04 + temperature _C ) ) ) ;
}
exports . calculateAltitudeMeters = ( pressure _hPa , seaLevelPressure _hPa ) => {
if ( ! seaLevelPressure _hPa ) {
seaLevelPressure _hPa = 1013.25 ;
}
return ( 1.0 - Math . pow ( pressure _hPa / seaLevelPressure _hPa , ( 1 / 5.2553 ) ) ) * 145366.45 * 0.3048 ;
}
/ *
* This code was forked from skylarstein ' s bme280 - sensor : https : //github.com/skylarstein/bme280-sensor
* /