2021-02-10, 11:53 PM
hi!
thank you for this great development, sean.
i built weathersensors but i haven't got a bmp280 but instead a bmp180 - so i modified the code to work with it. i don't know if its for common interest, so i attach the diff right here if anybody needs it. would it make sense to extract the bmp280-code from weathersensors.ino into a seperate .c/.h file? so it would be possible to change the sensor with only changing the includes (via #define)...
kind regards....martin.
thank you for this great development, sean.
i built weathersensors but i haven't got a bmp280 but instead a bmp180 - so i modified the code to work with it. i don't know if its for common interest, so i attach the diff right here if anybody needs it. would it make sense to extract the bmp280-code from weathersensors.ino into a seperate .c/.h file? so it would be possible to change the sensor with only changing the includes (via #define)...
kind regards....martin.
Code:
--- weathersensors.ino.orig 2021-02-10 22:28:43.805432769 +0000
+++ weathersensors.ino 2021-02-09 20:25:08.209423143 +0000
@@ -6,7 +6,7 @@
* version 3 of the License, or (at your option) any later version.
*/
-/* this program interfaces with the bmp280 pressure sensor and outputs
+/* this program interfaces with the bmp180 pressure sensor and outputs
calibrated nmea0183 data over serial at 38400 baud
anemometer wires
@@ -56,10 +56,10 @@
int16_t cross_count = 1000; // calibrate range during first 1000 crossings of 0
-uint8_t have_bmp280 = 0;
-uint8_t bmX280_tries = 10; // try 10 times to configure
-uint16_t dig_T1, dig_P1;
-int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
+uint8_t have_bmp180 = 0;
+uint8_t bmp180_tries = 10; // try 10 times to configure
+uint16_t dig_AC4, dig_AC5, dig_AC6;
+int16_t dig_AC1, dig_AC2, dig_AC3, dig_B1, dig_B2, dig_MB, dig_MC, dig_MD;
int16_t cal_wind_min_reading, cal_wind_max_reading;
uint32_t eeprom_write_timeout = 0;
@@ -93,12 +93,12 @@
const uint32_t baro_times[3] = {60000L*5/history_len, 60000L*60/history_len, 60000L*60*24/history_len};
-void bmX280_setup()
+void bmp180_setup()
{
- Serial.println(F("bmX280 setup"));
+ Serial.println(F("bmp180 setup"));
// NOTE: local version of twi does not enable pullup as
- // bmX_280 device is 3.3v and arduino runs at 5v
+ // bmp_180 device is 3.3v and arduino runs at 5v
twi_init();
@@ -108,18 +108,18 @@
pinMode(SCL, INPUT);
delay(1);
- have_bmp280 = 0;
- bmX280_tries--;
+ have_bmp180 = 0;
+ bmp180_tries--;
uint8_t d[24];
d[0] = 0xd0;
- if(twi_writeTo(0x76, d, 1, 1, 1) == 0 &&
- twi_readFrom(0x76, d, 1, 1) == 1 &&
- d[0] == 0x58)
- have_bmp280 = 1;
+ if(twi_writeTo(0x77, d, 1, 1, 1) == 0 &&
+ twi_readFrom(0x77, d, 1, 1) == 1 &&
+ d[0] == 0x55)
+ have_bmp180 = 1;
else {
- Serial.print(F("bmp280 not found: "));
+ Serial.print(F("bmp180 not found: "));
Serial.println(d[0]);
// attempt reset command
//d[0] = 0xe0;
@@ -129,51 +129,44 @@
return;
}
- d[0] = 0x88;
- if(twi_writeTo(0x76, d, 1, 1, 1) != 0)
- have_bmp280 = 0;
-
- uint8_t c = twi_readFrom(0x76, d, 24, 1);
- if(c != 24) {
- Serial.println(F("bmp280 failed to read calibration"));
- have_bmp280 = 0;
+ d[0] = 0xAA;
+ if(twi_writeTo(0x77, d, 1, 1, 1) != 0)
+ have_bmp180 = 0;
+
+ uint8_t c = twi_readFrom(0x77, d, 22, 1);
+ if(c != 22) {
+ Serial.println(F("bmp180 failed to read calibration"));
+ have_bmp180 = 0;
}
- dig_T1 = d[0] | d[1] << 8;
- dig_T2 = d[2] | d[3] << 8;
- dig_T3 = d[4] | d[5] << 8;
- dig_P1 = d[6] | d[7] << 8;
- dig_P2 = d[8] | d[9] << 8;
- dig_P3 = d[10] | d[11] << 8;
- dig_P4 = d[12] | d[13] << 8;
- dig_P5 = d[14] | d[15] << 8;
- dig_P6 = d[16] | d[17] << 8;
- dig_P7 = d[18] | d[19] << 8;
- dig_P8 = d[20] | d[21] << 8;
- dig_P9 = d[22] | d[23] << 8;
+ dig_AC1 = d[0] << 8 | d[1];
+ dig_AC2 = d[2] << 8 | d[3];
+ dig_AC3 = d[4] << 8 | d[5];
+ dig_AC4 = d[6] << 8 | d[7];
+ dig_AC5 = d[8] << 8 | d[9];
+ dig_AC6 = d[10] << 8 | d[11];
+ dig_B1 = d[12] << 8 | d[13];
+ dig_B2 = d[14] << 8 | d[15];
+ dig_MB = d[16] << 8 | d[17];
+ dig_MC = d[18] << 8 | d[19];
+ dig_MD = d[20] << 8 | d[21];
#if 0
- Serial.println("bmp280 pressure compensation:");
- Serial.println(dig_T1);
- Serial.println(dig_T2);
- Serial.println(dig_T3);
- Serial.println(dig_P1);
- Serial.println(dig_P2);
- Serial.println(dig_P3);
- Serial.println(dig_P4);
- Serial.println(dig_P5);
- Serial.println(dig_P6);
- Serial.println(dig_P7);
- Serial.println(dig_P8);
- Serial.println(dig_P9);
+ Serial.println("bmp180 pressure compensation:");
+ Serial.println(dig_AC1);
+ Serial.println(dig_AC2);
+ Serial.println(dig_AC3);
+ Serial.println(dig_AC4);
+ Serial.println(dig_AC5);
+ Serial.println(dig_AC6);
+ Serial.println(dig_B1);
+ Serial.println(dig_B2);
+ Serial.println(dig_MB);
+ Serial.println(dig_MC);
+ Serial.println(dig_MD);
#endif
- // b00011111 // configure
- d[0] = 0xf4;
- d[1] = 0xff;
- if(twi_writeTo(0x76, d, 2, 1, 1) != 0)
- have_bmp280 = 0;
}
volatile unsigned int rotation_count;
@@ -321,7 +314,7 @@
)
Serial.print(F("Warning, fuses set wrong, flash may become corrupted"));
- bmX280_setup();
+ bmp180_setup();
attachInterrupt(0, isr_anemometer_count, CHANGE);
pinMode(analogInPin, INPUT);
@@ -390,36 +383,48 @@
}
int32_t t_fine;
-int32_t bmp280_compensate_T_int32(int32_t adc_T)
+int32_t bmp180_compensate_T_int32(int32_t adc_T)
{
int32_t var1, var2, T;
- 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;
+ var1 = (adc_T - (int32_t)dig_AC6) * ((int32_t)dig_AC5) >> 15;
+ var2 = ((int32_t)dig_MC << 11) / (var1 + (int32_t)dig_MD);
+ T = (((var1 + var2) * 10 + 8) >> 4) ;
t_fine = var1 + var2;
- T = (t_fine * 5 + 128) >> 8;
return T;
}
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
-uint32_t bmp280_compensate_P_int64(int32_t adc_P)
+uint32_t bmp180_compensate_P_int64(int32_t adc_P)
{
- uint64_t var1, var2, p;
- var1 = ((int64_t)t_fine) - 128000;
- var2 = var1 * var1 * (uint64_t)dig_P6;
- var2 = var2 + ((var1*(uint64_t)dig_P5)<<17);
- var2 = var2 + (((uint64_t)dig_P4)<<35);
- var1 = ((var1 * var1 * (uint64_t)dig_P3)>>8) + ((var1 * (uint64_t)dig_P2)<<12);
- var1 = (((((int64_t)1)<<47)+var1))*((uint64_t)dig_P1)>>33;
- if (var1 == 0)
+ int32_t b3, b6, x1, x2, x3, p;
+ uint32_t b4, b7;
+
+ b6 = t_fine - 4000;
+ x1 = ((int32_t)dig_B2 * (b6 * b6) >> 12 ) >> 11 ;
+ x2 = ((int32_t)dig_AC2 * b6) >> 11;
+ x3 = x1 + x2;
+ b3 = ((((int32_t)dig_AC1 * 4 + x3) << 0) + 2) / 4;
+ x1 = ((int32_t)dig_AC3 * b6) >> 13;
+ x2 = ((int32_t)dig_B1 * ((b6 * b6) >> 12)) >> 16;
+ x3 = ((x1 + x2) + 2) >> 2;
+ b4 = ((uint32_t)dig_AC4 * (uint32_t)(x3 + 32768)) >> 15;
+ b7 = ((uint32_t)adc_P - b3) * (uint32_t)(50000UL >> 0);
+ if (b4 == 0)
{
return 0; // avoid exception caused by division by zero
}
- p = 1048576-adc_P;
- p = (((p<<31)-var2)*3125)/var1;
- var1 = (((uint64_t)dig_P9) * (p>>13) * (p>>13)) >> 25;
- var2 = (((uint64_t)dig_P8) * p) >> 19;
- p = ((p + var1 + var2) >> 8) + (((uint64_t)dig_P7)<<4);
+ if (b7 < 0x80000000)
+ p = (b7 * 2) / b4;
+ else
+ p = (b7 / b4) * 2;
+
+ x1 = (p >> 8) * (p >> 8);
+ x1 = (x1 * 3038) >> 16;
+ x2 = (-7357 * p) >> 16;
+ p = p + ((x1 + x2 + (int32_t)3791) >> 4);
+ p = p * 256;
+
return (uint32_t)p;
}
@@ -644,7 +649,7 @@
uint32_t pressure, temperature;
int32_t pressure_comp, temperature_comp;
-int bmp280_count;
+int bmp180_count;
static uint32_t baro_val, baro_count;
void put_baro_history(uint8_t index, int32_t val)
@@ -684,49 +689,73 @@
void read_pressure_temperature()
{
- if(!bmX280_tries)
+ if(!bmp180_tries)
return;
uint8_t buf[6] = {0};
- buf[0] = 0xf7;
- uint8_t r = twi_writeTo(0x76, buf, 1, 1, 1);
- if(r && have_bmp280) {
- Serial.print(F("bmp280 twierror "));
- Serial.println(r);
- }
+ uint8_t r, c;
+ int32_t p, t;
- uint8_t c = twi_readFrom(0x76, buf, 6, 1);
- if(c != 6 && have_bmp280)
- Serial.println(F("bmp280 failed to read 6 bytes from bmp280"));
- int32_t p, t;
-
- p = (int32_t)buf[0] << 16 | (int32_t)buf[1] << 8 | (int32_t)buf[2];
- t = (int32_t)buf[3] << 16 | (int32_t)buf[4] << 8 | (int32_t)buf[5];
-
+ // get raw temperature
+ buf[0] = 0xf4;
+ buf[1] = 0x2E; // control instruction measure temperature
+ r = twi_writeTo(0x77, buf, 2, 1, 1);
+ if(r && have_bmp180) {
+ Serial.println(F("bmp180 twierror "));
+ have_bmp180 = 0;
+ }
+ delay(5);
+ buf[0] = 0xf6; // data register
+ r = twi_writeTo(0x77, buf, 1, 1, 1);
+ c = twi_readFrom(0x77, buf, 2, 1);
+ if(c != 2 && have_bmp180) {
+ Serial.println(F("bmp180 failed to read 2 bytes for temperature"));
+ have_bmp180 = 0;
+ }
+ t = (int32_t)buf[0] << 8 | (int32_t)buf[1];
+
+ // get raw pressure
+ buf[0] = 0xf4;
+ buf[1] = 0x34; // control instruction measure pressure
+ r = twi_writeTo(0x77, buf, 2, 1, 1);
+ if(r && have_bmp180) {
+ Serial.println(F("bmp180 twierror "));
+
+ }
+ delay(5);
+ buf[0] = 0xf6; // data register
+ r = twi_writeTo(0x77, buf, 1, 1, 1);
+ c = twi_readFrom(0x77, buf, 3, 1);
+ if(c != 3 && have_bmp180) {
+ Serial.println(F("bmp180 failed to read 3 bytes for pressure"));
+ have_bmp180 = 0;
+ }
+ p = ((int32_t)buf[0] << 16 | (int32_t)buf[1] << 8 | (int32_t)buf[2]) >> 8;
+
if(t == 0 || p == 0)
- have_bmp280 = 0;
+ have_bmp180 = 0;
- pressure += p >> 2;
- temperature += t >> 2;
- bmp280_count++;
-
- if(!have_bmp280) {
- if(bmp280_count == 256) {
- bmp280_count = 0;
+ pressure += p << 2;
+ temperature += t << 2;
+ bmp180_count++;
+
+ if(!have_bmp180) {
+ if(bmp180_count == 256) {
+ bmp180_count = 0;
/* only re-run setup when count elapse */
- bmX280_setup();
+ bmp180_setup();
}
return;
}
- if(bmp280_count == 1024) {
- bmp280_count = 0;
+ if(bmp180_count == 1024) {
+ bmp180_count = 0;
pressure >>= 12;
temperature >>= 12;
- temperature_comp = bmp280_compensate_T_int32(temperature);
- pressure_comp = bmp280_compensate_P_int64(pressure) >> 8;
+ temperature_comp = bmp180_compensate_T_int32(temperature);
+ pressure_comp = bmp180_compensate_P_int64(pressure) >> 8;
pressure = temperature = 0;
char buf[128];