فهرست منبع

bmp280 sensor temperature reading implemented

Victor 3 سال پیش
والد
کامیت
52165f8df0
5فایلهای تغییر یافته به همراه188 افزوده شده و 18 حذف شده
  1. 19 18
      interfaces/I2CSensor.c
  2. 31 0
      interfaces/I2CSensor.h
  3. 87 0
      sensors/BMP280.c
  4. 43 0
      sensors/BMP280.h
  5. 8 0
      sensors/SensorsDriver.h

+ 19 - 18
interfaces/I2CSensor.c

@@ -1,6 +1,7 @@
 #include "I2CSensor.h"
+#include "../sensors/SensorsDriver.h"
 
-static uint8_t readReg(I2CSensor* i2c_sensor, uint8_t reg) {
+uint8_t readReg(I2CSensor* i2c_sensor, uint8_t reg) {
     //Блокировка шины
     furi_hal_i2c_acquire(i2c_sensor->i2c);
     uint8_t buff[1];
@@ -8,7 +9,15 @@ static uint8_t readReg(I2CSensor* i2c_sensor, uint8_t reg) {
     furi_hal_i2c_release(i2c_sensor->i2c);
     return buff[0];
 }
-static void writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value) {
+
+bool readRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data) {
+    furi_hal_i2c_acquire(i2c_sensor->i2c);
+    bool status = furi_hal_i2c_read_mem(
+        i2c_sensor->i2c, i2c_sensor->currentI2CAdr << 1, startReg, data, len, 0xFF);
+    furi_hal_i2c_release(i2c_sensor->i2c);
+    return status;
+}
+void writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value) {
     //Блокировка шины
     furi_hal_i2c_acquire(i2c_sensor->i2c);
     uint8_t buff[1] = {value};
@@ -16,23 +25,15 @@ static void writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value) {
     furi_hal_i2c_release(i2c_sensor->i2c);
 }
 
-bool unitemp_I2C_sensorInit(void* sensor) {
-    I2CSensor* i2c_sensor = (I2CSensor*)((Sensor*)sensor)->instance;
+bool unitemp_I2C_sensorInit(void* s) {
+    Sensor* sensor = (Sensor*)s;
+    I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance;
     //BMP280
-    if(((Sensor*)sensor)->type == BMP280) {
-        //Перезагрузка
-        writeReg(i2c_sensor, 0xE0, 0xB6);
-        //Чтение ID датчика
-        uint8_t id = readReg(i2c_sensor, 0xD0);
-        if(id != 0x58) {
-            ((Sensor*)sensor)->status = UT_ERROR;
-            return false;
+    if(sensor->type == BMP280) {
+        if(BMP280_init(i2c_sensor)) {
+            sensor->status = UT_OK;
+            return true;
         }
-
-        //TODO: Дальнейшая инициализация
-
-        ((Sensor*)sensor)->status = UT_OK;
-        return true;
     }
     return false;
 }
@@ -47,7 +48,7 @@ UnitempStatus unitemp_I2C_updateData(void* sensor) {
     if(((Sensor*)sensor)->status == UT_ERROR || ((Sensor*)sensor)->status == UT_TIMEOUT) {
         if(((Sensor*)sensor)->initializer(sensor) != true) return UT_ERROR;
     }
-    //I2CSensor* i2c_sensor = (I2CSensor*)((Sensor*)sensor)->instance;
+    BMP280_updateData(sensor);
     return UT_OK;
 }
 

+ 31 - 0
interfaces/I2CSensor.h

@@ -22,6 +22,8 @@ typedef struct I2CSensor {
     uint8_t maxI2CAdr;
     //Текущий адрес устройства на шине I2C
     uint8_t currentI2CAdr;
+    //Указатель на собственный экземпляр датчика
+    void* sensorInstance;
 
 } I2CSensor;
 
@@ -41,4 +43,33 @@ bool unitemp_I2C_sensorInit(void* sensor);
  */
 bool unitemp_I2C_sensorAlloc(Sensor* sensor, SensorType st, uint16_t* anotherValues);
 
+/**
+ * @brief Прочитать значение регистра reg
+ * 
+ * @param i2c_sensor Указатель на датчик
+ * @param reg Номер регистра
+ * @return Значение регистра
+ */
+uint8_t readReg(I2CSensor* i2c_sensor, uint8_t reg);
+
+/**
+ * @brief Прочитать масссив значений из памяти 
+ * 
+ * @param i2c_sensor 
+ * @param startReg 
+ * @param len 
+ * @param data 
+ * @return Истина если устройство вернуло данные
+ */
+bool readRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data);
+
+/**
+ * @brief Записать значение в регистр
+ * 
+ * @param i2c_sensor Указатель на датчик
+ * @param reg Номер регистра
+ * @param value Значение для записи
+ */
+void writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value);
+
 #endif

+ 87 - 0
sensors/BMP280.c

@@ -0,0 +1,87 @@
+#include "SensorsDriver.h"
+#include "BMP280.h"
+
+#define TEMP_CAL_START_ADDR 0x88
+#define PRESS_CAL_START_ADDR 0x8E
+
+static double bmp280_compensate_T_double(I2CSensor* i2c_sensor, int32_t adc_T) {
+    BMP280_instance* bmp280_instance = (BMP280_instance*)i2c_sensor->sensorInstance;
+    double var1, var2, T;
+    var1 = (((double)adc_T) / (double)16384.0 -
+            ((double)bmp280_instance->temp_cal.dig_T1) / (double)1024.0) *
+           ((double)bmp280_instance->temp_cal.dig_T2);
+    var2 = ((((double)adc_T) / (double)131072.0 -
+             ((double)bmp280_instance->temp_cal.dig_T1) / (double)8192.0) *
+            (((double)adc_T) / (double)131072.0 -
+             ((double)bmp280_instance->temp_cal.dig_T1) / (double)8192.0)) *
+           ((double)bmp280_instance->temp_cal.dig_T3);
+    T = (var1 + var2) / (double)5120.0;
+    return T;
+}
+
+static bool readCalValues(I2CSensor* i2c_sensor) {
+    BMP280_instance* bmp280_instance = (BMP280_instance*)i2c_sensor->sensorInstance;
+    if(!readRegArray(i2c_sensor, TEMP_CAL_START_ADDR, 6, (uint8_t*)&bmp280_instance->temp_cal))
+        return false;
+
+    if(!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);
+    return true;
+}
+
+bool BMP280_init(I2CSensor* i2c_sensor) {
+    //Перезагрузка
+    writeReg(i2c_sensor, 0xE0, 0xB6);
+    //Чтение ID датчика
+    if(readReg(i2c_sensor, 0xD0) != 0x58) {
+        return false;
+    }
+    i2c_sensor->sensorInstance = malloc(sizeof(BMP280_instance));
+    //Чтение калибровочных значений
+    if(!readCalValues(i2c_sensor)) {
+        return false;
+    }
+
+    writeReg(i2c_sensor, 0xF4, 0b01010111);
+    writeReg(i2c_sensor, 0xF5, 0b10110100);
+
+    return true;
+}
+
+bool BMP280_updateData(Sensor* sensor) {
+    I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance;
+    if(furi_get_tick() - i2c_sensor->lastPollingTime < 500) {
+        sensor->status = UT_EARLYPOOL;
+        return false;
+    }
+    i2c_sensor->lastPollingTime = furi_get_tick();
+
+    while(readReg(i2c_sensor, 0xF3) & 0b00001001) {
+        if(furi_get_tick() - i2c_sensor->lastPollingTime > 100) {
+            sensor->status = UT_TIMEOUT;
+            return false;
+        }
+    }
+
+    uint8_t buff[3];
+    if(!readRegArray(i2c_sensor, 0xFA, 3, buff)) return false;
+    int32_t adc_T = ((int32_t)buff[2] << 12) | ((int32_t)buff[1] << 4) | ((int32_t)buff[2] >> 4);
+    sensor->temp = bmp280_compensate_T_double(i2c_sensor, adc_T);
+    return true;
+}

+ 43 - 0
sensors/BMP280.h

@@ -0,0 +1,43 @@
+#ifndef UNITEMP_BMP280
+#define UNITEMP_BMP280
+#include "../unitemp.h"
+#include "../Sensors.h"
+#include "../interfaces/I2CSensor.h"
+#include "SensorsDriver.h"
+
+typedef struct {
+    uint16_t dig_T1;
+    int16_t dig_T2;
+    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 {
+    BMP280_temp_cal temp_cal;
+    BMP280_press_cal press_cal;
+
+} BMP280_instance;
+
+/**
+ * @brief Инициализация датчика
+ * 
+ * @param i2c_sensor Указатель на датчик
+ * @return Инстина если инициализация успешная
+ */
+
+bool BMP280_init(I2CSensor* i2c_sensor);
+
+bool BMP280_updateData(Sensor* sensor);
+
+#endif

+ 8 - 0
sensors/SensorsDriver.h

@@ -0,0 +1,8 @@
+#ifndef UNITEMP_SENSORSDRIVER
+#define UNITEMP_SENSORSDRIVER
+#include "../unitemp.h"
+#include "../Sensors.h"
+#include "../interfaces/I2CSensor.h"
+#include "BMP280.h"
+
+#endif