Просмотр исходного кода

Added pressure measurement for BMP280

Victor 3 лет назад
Родитель
Сommit
c6560a416b
7 измененных файлов с 91 добавлено и 39 удалено
  1. 4 1
      Sensors.c
  2. 2 0
      Sensors.h
  3. 55 21
      sensors/BMP280.c
  4. 14 12
      sensors/BMP280.h
  5. 4 1
      unitemp.c
  6. 8 0
      unitemp.h
  7. 4 4
      views/General_view.c

+ 4 - 1
Sensors.c

@@ -412,7 +412,7 @@ Sensor* unitemp_sensor_alloc(char* name, const SensorType* type, char* args) {
 
     sensor->temp = -128.0f;
     sensor->hum = -128.0f;
-
+    sensor->pressure = -128.0f;
     //Выделение памяти под инстанс датчика в зависимости от его интерфейса
     status = sensor->type->interface->allocator(sensor, args);
 
@@ -529,6 +529,9 @@ UnitempStatus unitemp_sensor_updateData(Sensor* sensor) {
     FURI_LOG_D(APP_NAME, "Sensor %s update status %d", sensor->name, sensor->status);
     if(app->settings.unit == FAHRENHEIT && sensor->status == UT_OK)
         uintemp_celsiumToFarengate(sensor);
+    if(sensor->status == UT_OK) {
+        unitemp_pascalToMmHg(sensor);
+    }
     return sensor->status;
 }
 

+ 2 - 0
Sensors.h

@@ -83,6 +83,8 @@ typedef struct Sensor {
     float temp;
     //Относительная влажность
     float hum;
+    //Атмосферное давление
+    float pressure;
     //Тип датчика
     const SensorType* type;
     //Статус последнего опроса датчика

+ 55 - 21
sensors/BMP280.c

@@ -14,7 +14,7 @@ const SensorType BMP280 = {
 #define BMP280_CAL_UPDATE_INTERVAL 60000
 
 #define TEMP_CAL_START_ADDR 0x88
-//#define PRESS_CAL_START_ADDR 0x8E
+#define PRESS_CAL_START_ADDR 0x8E
 #define BMP280_ID 0x58
 
 #define BMP280_REG_STATUS 0xF3
@@ -27,6 +27,13 @@ const SensorType BMP280 = {
 #define BMP280_TEMP_OVERSAMPLING_4 0b01100000
 #define BMP280_TEMP_OVERSAMPLING_8 0b10000000
 #define BMP280_TEMP_OVERSAMPLING_16 0b10100000
+//Преддескретизация давления
+#define BMP280_PRESS_OVERSAMPLING_SKIP 0b00000000
+#define BMP280_PRESS_OVERSAMPLING_1 0b00000100
+#define BMP280_PRESS_OVERSAMPLING_2 0b00001000
+#define BMP280_PRESS_OVERSAMPLING_4 0b00001100
+#define BMP280_PRESS_OVERSAMPLING_8 0b00010000
+#define BMP280_PRESS_OVERSAMPLING_16 0b00010100
 //Режимы работы датчика
 #define BMP280_MODE_SLEEP 0b00000000 //Спит и мало кушает
 #define BMP280_MODE_FORCED 0b00000001 //Обновляет значения 1 раз, после чего уходит в сон
@@ -61,10 +68,33 @@ static double bmp280_compensate_T_double(I2CSensor* i2c_sensor, int32_t adc_T) {
             (((double)adc_T) / (double)131072.0 -
              ((double)bmp280_instance->temp_cal.dig_T1) / (double)8192.0)) *
            ((double)bmp280_instance->temp_cal.dig_T3);
+    bmp280_instance->t_fine = var1 + var2;
     T = (var1 + var2) / (double)5120.0;
     return T;
 }
 
+static double bmp280_compensate_P_double(I2CSensor* i2c_sensor, int32_t adc_P) {
+    BMP280_instance* bmp280_instance = (BMP280_instance*)i2c_sensor->sensorInstance;
+    double var1, var2, p;
+    var1 = ((double)bmp280_instance->t_fine / (double)2.0) - (double)64000.0;
+    var2 = var1 * var1 * ((double)bmp280_instance->press_cal.dig_P6) / (double)32768.0;
+    var2 = var2 + var1 * ((double)bmp280_instance->press_cal.dig_P5) * (double)2.0;
+    var2 = (var2 / (double)4.0) + (((double)bmp280_instance->press_cal.dig_P4) * (double)65536.0);
+    var1 = (((double)bmp280_instance->press_cal.dig_P3) * var1 * var1 / (double)524288.0 +
+            ((double)bmp280_instance->press_cal.dig_P2) * var1) /
+           (double)524288.0;
+    var1 = ((double)1.0 + var1 / (double)32768.0) * ((double)bmp280_instance->press_cal.dig_P1);
+    if(var1 == (double)0.0) {
+        return 0; // avoid exception caused by division by zero
+    }
+    p = (double)1048576.0 - (double)adc_P;
+    p = (p - (var2 / (double)4096.0)) * (double)6250.0 / var1;
+    var1 = ((double)bmp280_instance->press_cal.dig_P9) * p * p / (double)2147483648.0;
+    var2 = p * ((double)bmp280_instance->press_cal.dig_P8) / (double)32768.0;
+    p = p + (var1 + var2 + ((double)bmp280_instance->press_cal.dig_P7)) / (double)16.0;
+    return p;
+}
+
 static bool bmp280_readCalValues(I2CSensor* i2c_sensor) {
     BMP280_instance* bmp280_instance = (BMP280_instance*)i2c_sensor->sensorInstance;
     if(!unitemp_i2c_readRegArray(
@@ -77,24 +107,22 @@ static bool bmp280_readCalValues(I2CSensor* i2c_sensor) {
         bmp280_instance->temp_cal.dig_T1,
         bmp280_instance->temp_cal.dig_T2,
         bmp280_instance->temp_cal.dig_T3);
-    // if(!unitemp_i2c_readRegArray(i2c_sensor, PRESS_CAL_START_ADDR, 18, (uint8_t*)&bmp280_instance->press_cal))
-    //     return false;
-    // FURI_LOG_D(
-    //     APP_NAME,
-    //     "Sensor BMP280 (0x%02X): T1-3: %d, %d, %d; P1-9: %d, %d, %d, %d, %d, %d, %d, %d, %d",
-    //     i2c_sensor->currentI2CAdr,
-    //     bmp280_instance->temp_cal.dig_T1,
-    //     bmp280_instance->temp_cal.dig_T2,
-    //     bmp280_instance->temp_cal.dig_T3,
-    //     bmp280_instance->press_cal.dig_P1,
-    //     bmp280_instance->press_cal.dig_P2,
-    //     bmp280_instance->press_cal.dig_P3,
-    //     bmp280_instance->press_cal.dig_P4,
-    //     bmp280_instance->press_cal.dig_P5,
-    //     bmp280_instance->press_cal.dig_P6,
-    //     bmp280_instance->press_cal.dig_P7,
-    //     bmp280_instance->press_cal.dig_P8,
-    //     bmp280_instance->press_cal.dig_P9);
+    if(!unitemp_i2c_readRegArray(
+           i2c_sensor, PRESS_CAL_START_ADDR, 18, (uint8_t*)&bmp280_instance->press_cal))
+        return false;
+    FURI_LOG_D(
+        APP_NAME,
+        "Sensor BMP280 (0x%02X): P1-9: %d, %d, %d, %d, %d, %d, %d, %d, %d",
+        i2c_sensor->currentI2CAdr,
+        bmp280_instance->press_cal.dig_P1,
+        bmp280_instance->press_cal.dig_P2,
+        bmp280_instance->press_cal.dig_P3,
+        bmp280_instance->press_cal.dig_P4,
+        bmp280_instance->press_cal.dig_P5,
+        bmp280_instance->press_cal.dig_P6,
+        bmp280_instance->press_cal.dig_P7,
+        bmp280_instance->press_cal.dig_P8,
+        bmp280_instance->press_cal.dig_P9);
     bmp280_instance->last_cal_update_time = furi_get_tick();
     return true;
 }
@@ -141,7 +169,9 @@ bool unitemp_BMP280_init(Sensor* sensor) {
     }
     //Настройка режимов работы
     unitemp_i2c_writeReg(
-        i2c_sensor, BMP280_REG_CTRL_MEAS, BMP280_TEMP_OVERSAMPLING_2 | BMP280_MODE_NORMAL);
+        i2c_sensor,
+        BMP280_REG_CTRL_MEAS,
+        BMP280_TEMP_OVERSAMPLING_2 | BMP280_PRESS_OVERSAMPLING_4 | BMP280_MODE_NORMAL);
     //Настройка периода опроса и фильтрации значений
     unitemp_i2c_writeReg(
         i2c_sensor,
@@ -169,7 +199,7 @@ UnitempStatus unitemp_BMP280_update(Sensor* sensor) {
     }
 
     while(bmp280_isMeasuring(sensor)) {
-        if(furi_get_tick() - t > 10) {
+        if(furi_get_tick() - t > 100) {
             return UT_TIMEOUT;
         }
     }
@@ -177,7 +207,11 @@ UnitempStatus unitemp_BMP280_update(Sensor* sensor) {
     uint8_t buff[3];
     if(!unitemp_i2c_readRegArray(i2c_sensor, 0xFA, 3, buff)) return UT_TIMEOUT;
     int32_t adc_T = ((int32_t)buff[0] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4);
+    if(!unitemp_i2c_readRegArray(i2c_sensor, 0xF7, 3, buff)) return UT_TIMEOUT;
+    int32_t adc_P = ((int32_t)buff[0] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4);
     sensor->temp = bmp280_compensate_T_double(i2c_sensor, adc_T);
+    sensor->pressure = bmp280_compensate_P_double(i2c_sensor, adc_P);
+    FURI_LOG_D(APP_NAME, "pressure: %d pa ", (int)sensor->pressure);
     return UT_OK;
 }
 

+ 14 - 12
sensors/BMP280.h

@@ -10,25 +10,27 @@ typedef struct {
     int16_t dig_T3;
 } BMP280_temp_cal;
 
-// typedef struct {
-//     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;
-// } BMP280_press_cal;
+typedef struct {
+    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;
+} BMP280_press_cal;
 
 typedef struct {
     //Калибровочные значения температуры
     BMP280_temp_cal temp_cal;
     //Калибровочные значения давления
-    // BMP280_press_cal press_cal;
+    BMP280_press_cal press_cal;
     //Время последнего обновления калибровочных значений
     uint32_t last_cal_update_time;
+    //Корректировочное значение температуры
+    uint32_t t_fine;
 } BMP280_instance;
 
 extern const SensorType BMP280;

+ 4 - 1
unitemp.c

@@ -8,7 +8,6 @@
 
 //TODO: Реализовать ограничение на добавление датчиков если интерфейс недоступен
 //TODO: Не выкидывать датчик в ошибку при первом же неудачном опросе
-//TODO: Динамический размер массива с датчиками
 
 /* Переменные */
 //Данные приложения
@@ -18,6 +17,10 @@ void uintemp_celsiumToFarengate(Sensor* sensor) {
     sensor->temp = sensor->temp * (9.0 / 5.0) + 32;
 }
 
+void unitemp_pascalToMmHg(Sensor* sensor) {
+    sensor->pressure = sensor->pressure * 0.00750061683f;
+}
+
 bool unitemp_saveSettings(void) {
     //Выделение памяти для потока
     app->file_stream = file_stream_alloc(app->storage);

+ 8 - 0
unitemp.h

@@ -75,6 +75,14 @@ typedef struct {
  */
 void uintemp_celsiumToFarengate(Sensor* sensor);
 
+/**
+ * @brief Конвертация давления из паскалей в мм/рт
+ * 
+ * @param sensor Указатель на датчик
+ * @return Давление в мм рт.ст.
+ */
+void unitemp_pascalToMmHg(Sensor* sensor);
+
 /**
  * @brief Сохранение настроек на SD-карту
  * 

+ 4 - 4
views/General_view.c

@@ -14,7 +14,7 @@ static void _draw_temp(Canvas* canvas, float temp, uint8_t pos) {
     //Рисование рамки
     canvas_draw_rframe(canvas, temp_positions[pos][0], temp_positions[pos][1], 54, 20, 3);
     canvas_draw_rframe(canvas, temp_positions[pos][0], temp_positions[pos][1], 54, 19, 3);
-    int8_t temp_int = temp;
+    int16_t temp_int = temp;
     int8_t temp_dec = abs((int16_t)(temp * 10) % 10);
 
     //Рисование иконки
@@ -24,7 +24,7 @@ static void _draw_temp(Canvas* canvas, float temp, uint8_t pos) {
         temp_positions[pos][1] + 3,
         (app->settings.unit == CELSIUS ? &I_temp_C_11x14 : &I_temp_F_11x14));
 
-    if((int8_t)temp == -128) {
+    if((int16_t)temp == -128) {
         snprintf(buff, 5, "--");
         canvas_set_font(canvas, FontBigNumbers);
         canvas_draw_str_aligned(
@@ -47,7 +47,7 @@ static void _draw_temp(Canvas* canvas, float temp, uint8_t pos) {
     }
 
     //Целая часть температуры
-    snprintf(buff, 5, "%d", temp_int);
+    snprintf(buff, 7, "%d", temp_int);
     canvas_set_font(canvas, FontBigNumbers);
     canvas_draw_str_aligned(
         canvas,
@@ -139,7 +139,7 @@ static void _draw_sensorsCarousel(Canvas* canvas) {
     }
 
     //Печать значения температуры
-    _draw_temp(canvas, app->sensors[sensor_index]->temp, 1);
+    _draw_temp(canvas, app->sensors[sensor_index]->pressure, 1);
     _draw_hum(canvas, app->sensors[sensor_index]->hum, 0);
 }