M5Paper and BME280 Sensor
-
Because the BME280 library didn't want to work with the M5Paper Wire1 I2c connection, I changed the routines so that they now work.
The adjustment now works for M5Stack, the M5Paper and for the Core2.
I post the complete code here, because I cannot upload a zip file.
he whole consists of:- M5Paper_BME280.uno
- BME280.h
- BME280_routines
1. M5Paper_BME280.uno
/* * BME280 Sensor (Temperature,Pressure, and Humidity) * Is working now also for M5Paper, and testest on all M5Stack devices * Rewritten by J.Kromhout (NL) * Version 1.0 * Date : 24-02-2021 * * Todo: Beter input for smapling etc. * Making the routine universal for BME280 and BMP280 */ #include <M5EPD.h> #include <Wire.h> #include "BME280.h" /* definition file */ double p,t,h; /* pressure,temperature and humidity */ void setup() { M5.begin(); Wire1.begin(25,32); /* start Wire1 on M5Paper */ getBME280(&Wire1, &t, &p, &h); /* get messurment*/ Serial.println("-------------------------"); Serial.printf("Temperature : %6.1f °C\n", t); Serial.printf("Barometer : %6.1f hPa\n", p); Serial.printf("Humidity : %6.1f %%\n", h); Serial.println("-------------------------"); } void loop() { // put your main code here, to run repeatedly: } void getBME280(TwoWire *theWire, double *t, double *p, double *h) { _i2c = theWire; /* check of BME280 is avilable */ uint8_t value = read8(0xD0); if (value == 0x60) Serial.println("BME280 found"); else { Serial.println("No BME280 found! Check your device........"); while(true); } reset_BME280(); // Reset BME280 write8(BME280_REGISTER_CONTROLHUMID,(uint8_t)0x01); // Select control humidity register write8(BME280_REGISTER_CONTROL, (uint8_t)0x27); // Select control measurement register write8(BME280_REGISTER_CONFIG, (uint8_t)0xA0); // Select config register readCoefficients(); // Read coefficients from BME280 *t = get_Temperature(); // Get temperature *p = get_Pressure()/100.0; // Get pressure *h = get_Humidity(); // Get Humidity }
2. BME280.h
#define BME280_ADDRESS 0x77 /* Primary I2C Address */ TwoWire *_i2c; uint8_t _i2caddr = BME280_ADDRESS; int32_t t_fine; /* tempory variable */ /* calibration data, need for calculation */ uint16_t dig_T1; int16_t dig_T2; int16_t dig_T3; uint16_t dig_P1; int16_t dig_P2; int16_t dig_P3; int16_t dig_P4; int16_t dig_P5; int16_t dig_P6; int16_t dig_P7; int16_t dig_P8; int16_t dig_P9; uint8_t dig_H1; int16_t dig_H2; uint8_t dig_H3; int16_t dig_H4; int16_t dig_H5; int8_t dig_H6; /* Calibrate registers addresses */ #define BME280_REGISTER_DIG_T1 0x88 #define BME280_REGISTER_DIG_T2 0x8A #define BME280_REGISTER_DIG_T3 0x8C #define BME280_REGISTER_DIG_P1 0x8E #define BME280_REGISTER_DIG_P2 0x90 #define BME280_REGISTER_DIG_P3 0x92 #define BME280_REGISTER_DIG_P4 0x94 #define BME280_REGISTER_DIG_P5 0x96 #define BME280_REGISTER_DIG_P6 0x98 #define BME280_REGISTER_DIG_P7 0x9A #define BME280_REGISTER_DIG_P8 0x9C #define BME280_REGISTER_DIG_P9 0x9E #define BME280_REGISTER_DIG_H1 0xA1 #define BME280_REGISTER_DIG_H2 0xE1 #define BME280_REGISTER_DIG_H3 0xE3 #define BME280_REGISTER_DIG_H4 0xE4 #define BME280_REGISTER_DIG_H5 0xE5 #define BME280_REGISTER_DIG_H6 0xE7 /* ontrol registers */ #define BME280_REGISTER_CHIPID 0xD0 #define BME280_REGISTER_VERSION 0xD1 #define BME280_REGISTER_SOFTRESET 0xE0 #define BME280_REGISTER_CAL26 0xE1 #define BME280_REGISTER_CONTROLHUMID 0xF2 #define BME280_REGISTER_STATUS 0xF3 #define BME280_REGISTER_CONTROL 0xF4 #define BME280_REGISTER_CONFIG 0xF5 #define BME280_REGISTER_PRESSUREDATA 0xF7 #define BME280_REGISTER_TEMPDATA 0xFA #define BME280_REGISTER_HUMIDDATA 0xFD
3. BME280_routines
uint8_t read8(byte reg) { uint8_t value; _i2c->beginTransmission((uint8_t)BME280_ADDRESS); _i2c->write((uint8_t)reg); _i2c->endTransmission(); _i2c->requestFrom((uint8_t)BME280_ADDRESS,(uint8_t)1); value = _i2c->read(); return value; } void write8(byte reg , byte value) { _i2c->beginTransmission((uint8_t)BME280_ADDRESS); _i2c->write((uint8_t)reg); _i2c->write((uint8_t)value); _i2c->endTransmission(); } uint16_t read16(byte reg) { uint16_t value; _i2c->beginTransmission((uint8_t) BME280_ADDRESS); _i2c->write((uint8_t)reg); _i2c->endTransmission(); _i2c->requestFrom((uint8_t)BME280_ADDRESS,(uint8_t)2); value = (_i2c->read() << 8) | _i2c->read(); return value; } uint32_t read24(byte reg) { uint32_t value; _i2c->beginTransmission((uint8_t)BME280_ADDRESS); _i2c->write((uint8_t)reg); _i2c->endTransmission(); _i2c->requestFrom((uint8_t)BME280_ADDRESS,(uint8_t)3); value = _i2c->read(); value <<= 8; value |= _i2c->read(); value <<= 8; value |= _i2c->read(); return value; } uint16_t read16_LE(byte reg) { uint16_t temp = read16(reg); return (temp >> 8) | (temp << 8); } int16_t readS16(byte reg) { return (int16_t) read16(reg); } int16_t readS16_LE(byte reg) { return (int16_t) read16_LE(reg); } void readCoefficients() { dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); dig_H1 = read8(BME280_REGISTER_DIG_H1); dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); dig_H3 = read8(BME280_REGISTER_DIG_H3); dig_H4 = ((int8_t)read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF); dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4); dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); } double get_Temperature() { int32_t var1, var2; int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); adc_T >>= 4; var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11; var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14; t_fine = var1 + var2; double T = (t_fine * 5 + 128) >> 8; return T / 100; } double get_Pressure() { int64_t var1, var2, p; // Must be done first to get the t_fine variable set up get_Temperature(); int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); adc_P >>= 4; var1 = ((int64_t)t_fine) - 128000; var2 = var1 * var1 * (int64_t)dig_P6; var2 = var2 + ((var1 * (int64_t)dig_P5) << 17); var2 = var2 + (((int64_t)dig_P4) << 35); var1 = ((var1 * var1 * (int64_t)dig_P3) >> 8) + ((var1 * (int64_t)dig_P2) << 12); var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)dig_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 = (((int64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25; var2 = (((int64_t)dig_P8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)dig_P7) << 4); return (double)p / 256; } double get_Humidity(void) { get_Temperature(); // must be done first to get t_fine int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); if (adc_H == 0x8000) // value in case humidity measurement was disabled return NAN; int32_t v_x1_u32r; v_x1_u32r = (t_fine - ((int32_t)76800)); v_x1_u32r = (((((adc_H << 14) - (((int32_t)dig_H4) << 20) - (((int32_t)dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)dig_H2) + 8192) >> 14)); v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)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; double h = (v_x1_u32r >> 12); return h / 1024.0; } void reset_BME280() { write8(BME280_REGISTER_SOFTRESET , (uint8_t)0xB6); }
Have fun with it. Let us know when there are improvements.
Cheers,Jan
-
Make an improvement in the main call routine. The return value of getBME280 is a boolean.
now it is possible to check whether a BME280 is connected correctly.bool getBME280(TwoWire *theWire, double *t, double *p, double *h) { _i2c = theWire; /* check of BME280 is avilable */ uint8_t value = read8(0xD0); if (value == 0x60) // BME280 detected { reset_BME280(); // Reset BME280 write8(BME280_REGISTER_CONTROLHUMID,(uint8_t)0x01); // Select control humidity register write8(BME280_REGISTER_CONTROL, (uint8_t)0x27); // Select control measurement register write8(BME280_REGISTER_CONFIG, (uint8_t)0xA0); // Select config register readCoefficients(); // Read coefficients from BME280 *t = get_Temperature(); // Get temperature *p = get_Pressure()/100.0; // Get pressure *h = get_Humidity(); // Get Humidity return true; } else { return false; // No BME280 detected } }
Cheers,
Jan