ADC采集实现温度检测

1 使用nordic库实现 nRF52832ADC采集的一个例子

https://www.cnblogs.com/zzu-liulei/p/6519141.html

2 用nRF52840自带的ADC采集camera内部的温度

   原理图:

ADC采集实现温度检测_第1张图片

3 思路:

1).camera内部的热敏电阻与上拉电阻分压1.8V

2). 通过nRF52840自带ADC采集电压

3). 根据分压关系及热敏电阻与温度的关系,得到camera内部温度

4 公式推导

ADC采集实现温度检测_第2张图片

两个公式,一个可以从热敏电阻规格书中得到(热敏电阻与温度的关系),另一个是分压关系,

从而得到温度与电压的关系

ADC采集实现温度检测_第3张图片

5 代码实现(五个camera)

1) 初始化:初始化ADC,并对每路ADC初始化对应的pin脚及给出参考电压

在源码中给了7路ADC,而我们只用到其中5路,源码pin脚定义涉及到所以pin脚,而我们只关心ADC对应的pin脚,

这样可以使用定义数组的方式来定义专门针对ADC

源码ADC定义
typedef enum {
    NRF52_ADC_0,
    NRF52_ADC_1,
    NRF52_ADC_2,
    NRF52_ADC_3,
    NRF52_ADC_4,
    NRF52_ADC_5,
    NRF52_ADC_6,
    NRF52_ADC_7,
    NUM_NRF52_ADCS
} adc_t;

源码pin脚定义
typedef enum {
    NRF52_GPIO_PIN_0_0,
    NRF52_GPIO_PIN_0_1,
    NRF52_GPIO_PIN_0_2,
    NRF52_GPIO_PIN_0_3,
         。
         。
         。
    NRF52_GPIO_PIN_0_28,
    NRF52_GPIO_PIN_0_29,
    NRF52_GPIO_PIN_0_30,
    NRF52_GPIO_PIN_0_31,
#if defined(NRF52840_XXAA) || defined(NRF52840_XXBB)
    NRF52_GPIO_PIN_1_0,
    NRF52_GPIO_PIN_1_1,
    NRF52_GPIO_PIN_1_2,
         。
         。
         。
    NRF52_GPIO_PIN_1_14,
    NRF52_GPIO_PIN_1_15,
#endif
    NUM_NRF52_GPIO_PINS,
    NRF52_GPIO_PIN_UNUSED
} gpio_pin_t;

自定义数组如下:

const adc_t TEMP_ADCS[CAMERA_NUM_SENSORS] = {
    CAM0_TEMP_ADC,
    CAM1_TEMP_ADC,
    CAM2_TEMP_ADC,
    CAM3_TEMP_ADC,
    CAM4_TEMP_ADC,
};

const gpio_pin_t TEMP_PINS[CAMERA_NUM_SENSORS] = {
    GPIO_PIN_CAM0_TEMP,
    GPIO_PIN_CAM1_TEMP,
    GPIO_PIN_CAM2_TEMP,
    GPIO_PIN_CAM3_TEMP,
    GPIO_PIN_CAM4_TEMP,
};

其中

#define CAMERA_NUM_SENSORS                  5
#define CAM0_TEMP_ADC               NRF52_ADC_0
#define CAM1_TEMP_ADC               NRF52_ADC_1
#define CAM2_TEMP_ADC               NRF52_ADC_5
#define CAM3_TEMP_ADC               NRF52_ADC_6
#define CAM4_TEMP_ADC               NRF52_ADC_7
#define GPIO_PIN_CAM0_TEMP          NRF52_GPIO_PIN_0_2
#define GPIO_PIN_CAM1_TEMP          NRF52_GPIO_PIN_0_3
#define GPIO_PIN_CAM2_TEMP          NRF52_GPIO_PIN_0_29
#define GPIO_PIN_CAM3_TEMP          NRF52_GPIO_PIN_0_30
#define GPIO_PIN_CAM4_TEMP          NRF52_GPIO_PIN_0_31

初始化:

void camera_temp_init(void)
{
    // initialize the ADC for each camera temperature sensor
    for (int i = 0; i < CAMERA_NUM_SENSORS; i++) {
        const adc_init_t init_adc = {
            .gpio_pin = TEMP_PINS[i],
            .reference_voltage_mv = 1800,
        };
        adc_init(TEMP_ADCS[i], &init_adc);
    }
}adc_init_t init_adc = {
            .gpio_pin = TEMP_PINS[i],
            .reference_voltage_mv = 1800,
        };
        adc_init(TEMP_ADCS[i], &init_adc);
    }
}

其中:

typedef struct {
    //! \brief The GPIO pin to connect to the ADC
    gpio_pin_t gpio_pin;
    //! \brief The reference (max) voltage for the ADC in mV
    uint32_t reference_voltage_mv;
} adc_init_t;adc_init_t;

2)电压采集:根据采集到的ADC数据值,换算成电压

比如MCU是12位,然后参考电压是1800mv,那么,当MCU采出来的ADC值是2^12时,对应的电压是1800mv,

则,当MCU采出的ADC值为 X 时,对应的电压为 X*1800/(2^12)

uint32_t adc_get_value(adc_t adc)
{
    static nrf_saadc_value_t sample;
    APP_ERROR_CHECK(nrf_drv_saadc_sample_convert(adc, &sample));
    uint32_t result = (sample < 0) ? 0 : sample;

    // convert result into mV
    return result * MAX_VOLTAGE_MV/ ADC_MAX_VALUE;
}

其中:

#define ADC_MAX_VALUE               (1 << 12)
#define MAX_VOLTAGE_MV              1800

3)根据电压,得到五个camera温度

即将上面推导的电压与温度的关系写成代码实现

ADC采集实现温度检测_第4张图片

static int16_t temp_mv_to_deg_c(uint32_t value_mv)
{
    float temp_sample = 0;
    temp_sample = (RESISTENCEUP * 1.0) / RESISTENCENORMAL; //R/R0
    temp_sample = temp_sample * value_mv / (REFERENCEVOLTAGE - value_mv);//* V/(VDD-V)
    temp_sample = log(temp_sample);
    temp_sample /= BCOEFFICIENT;  //  /B
    temp_sample *= TEMPERATURENOMINAL;  // *(T0+273.15)
    temp_sample = TEMPERATURENOMINAL / (temp_sample+1); //T
    temp_sample -= ABSOLUTEZERO;  //  -273.15
    return temp_sample + 0.5;
}

其中:

#define TEMPERATURENOMINAL      (25+273.15)
#define RESISTENCENORMAL        (100)
#define RESISTENCEUP            (51)
#define REFERENCEVOLTAGE        (1800)
#define BCOEFFICIENT            (4250)
#define ABSOLUTEZERO            (273.15)

注意点:

1  上面代码紫色部分必须要乘以1.0,才能得到浮点数0.51,否则得到的数值为0

因为:整型/整型=整型,而无法得到浮点型 

即 51/100 = 0 ; 而51*1.0/100 = 0.51

2  最后标蓝色部分对最后温度值进行四舍五入,因为要得到一个整型的温度值

4)更新camera温度

static int16_t read_temp_sensor(uint8_t camera_id)
{
    UHAL_ASSERT(camera_id < CAMERA_NUM_SENSORS, "Invalid camera index");
    const uint32_t value_mv = adc_get_value(TEMP_ADCS[camera_id]);
    return temp_mv_to_deg_c(value_mv);
}
void camera_temp_update(void)
{
    for (int i = 0; i < CAMERA_NUM_SENSORS; ++i) {
        int16_t t = read_temp_sensor(i);
        __atomic_store_n(&m_cached_temps[i], &t, __ATOMIC_RELAXED);
    }}

其中:

static int16_t m_cached_temps[CAMERA_NUM_SENSORS] = {0};

 __atomic_store_n是原子队列,将获取的温度值t,依次存到缓存区数组中,相当于一个缓存区存储,如果用这个温度值的时候,从这个缓存区中将温度值取出来

int16_t camera_temp_get(uint8_t camera_id)
{
    UHAL_ASSERT(camera_id < CAMERA_NUM_SENSORS, "Invalid camera index");
    return __atomic_load_n(&m_cached_temps[camera_id], __ATOMIC_RELAXED);}

 

 

 

 

你可能感兴趣的:(嵌入式)