发帖
4 0 0

【Ai-WB2评测】ADC采集NTC热敏电阻通过BLE上报温度

sujingliang
论坛元老

18

主题

15

回帖

5670

积分

论坛元老

积分
5670
Ai-WB2系列 29 4 昨天 09:49

通过NTC(负温度系数)热敏电阻采集温度是一种低成本且广泛应用的方案,尤其适合对精度要求不高、预算有限的场景。

21804115-5294884.jpg

NTC热敏电阻的特点

负温度系数:电阻值随温度升高而降低(非线性关系)。

低成本:单价通常仅几元人民币,远低于数字温度传感器(如DS18B20)。

灵敏度高:在低温区电阻变化更显著,适合检测微小温度变化。

非线性响应:需通过公式或查表法进行线性化处理。

用Ai-WB2搭建电路

14.png

  • 原理:NTC与固定电阻组成分压电路,ADC读取分压值后转换为电阻,再通过公式计算温度。
  • 固定电阻选择:建议与NTC在目标温度范围内的中值电阻匹配(例如NTC在25℃时为10kΩ,则选10kΩ固定电阻)
    这里分压电阻选择了51K,是因为之前错误地以为手头的NTC是50K的,后来发现是150K的,就将错就错了。就是要注意查表法需要按照150K+50K分压计算对应关系。

实际电路:

15.png

软件部分

在applications\ble_slave例程基础上修改

1、增加temperature.h处理ADC采集NTC数据

#ifndef __TEMPERATURE_H__
#define __TEMPERATURE_H__

//temperature.h

void adc_temp_init(void);
int get_temp_value(void);
int get_temperature(void);

#endif

void adc_temp_init(void);//初始化ADC

int get_temp_value(void);//采集ADC数值(0-4095)

int get_temperature(void);//将ADC数值转化为温度

2、temperature.c实现

//
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <hosal_adc.h>
#include <blog.h>

#define GPIO_ADC_PIN 11
#define ADC_CHANNEL 10


const unsigned int tempTable[][2] = {
 {-30,114},
 {-29,121},
 {-28,128},
 {-27,136},
 {-26,144},
 {-25,153},
 {-24,162},
 {-23,172},
 {-22,182},
 {-21,192},
 {-20,203},
 {-19,215},
 {-18,227},
 {-17,240},
 {-16,253},
 {-15,267},
 {-14,281},
 {-13,296},
 {-12,312},
 {-11,328},
 {-10,345},
 {-9,362},
 {-8,381},
 {-7,400},
 {-6,419},
 {-5,440},
 {-4,461},
 {-3,483},
 {-2,505},
 {-1,529},
 {0,553},
 {1,577},
 {2,603},
 {3,629},
 {4,656},
 {5,684},
 {6,713},
 {7,742},
 {8,772},
 {9,803},
 {10,835},
 {11,867},
 {12,900},
 {13,934},
 {14,968},
 {15,1003},
 {16,1039},
 {17,1075},
 {18,1112},
 {19,1149},
 {20,1187},
 {21,1225},
 {22,1264},
 {23,1304},
 {24,1343},
 {25,1383},
 {26,1424},
 {27,1465},
 {28,1506},
 {29,1547},
 {30,1588},
 {31,1630},
 {32,1672},
 {33,1713},
 {34,1755},
 {35,1797},
 {36,1839},
 {37,1881},
 {38,1922},
 {39,1964},
 {40,2005},
 {41,2047},
 {42,2088},
 {43,2128},
 {44,2169},
 {45,2209},
 {46,2249},
 {47,2288},
 {48,2327},
 {49,2366},
 {50,2404},
 {51,2442},
 {52,2479},
 {53,2516},
 {54,2552},
 {55,2588},
 {56,2623},
 {57,2658},
 {58,2692},
 {59,2726},
 {60,2759},
 {61,2791},
 {62,2823},
 {63,2854},
 {64,2885},
 {65,2915},
 {66,2945},
 {67,2973},
 {68,3002},
 {69,3029},
 {70,3056},
 {71,3083},
 {72,3109},
 {73,3134},
 {74,3159},
 {75,3183},
 {76,3207},
 {77,3230},
 {78,3252},
 {79,3274},
 {80,3296},
 {81,3317},
 {82,3337},
 {83,3357},
 {84,3376},
 {85,3395},
 {86,3414},
 {87,3432},
 {88,3449},
 {89,3466},
 {90,3483},
 {91,3499},
 {92,3515},
 {93,3530},
 {94,3545},
 {95,3559},
 {96,3573},
 {97,3587},
 {98,3600},
 {99,3613},
 {100,3626},
 {101,3638},
 {102,3650},
 {103,3662},
 {104,3673},
 {105,3684},
 {106,3695},
 {107,3705},
 {108,3715},
 {109,3725},
 {110,3735},
 {111,3744},
 {112,3753},
 {113,3762},
 {114,3771},
 {115,3779},
 {116,3787},
 {117,3795},
 {118,3802},
 {119,3810},
 {120,3817},
 {121,3824},
 {122,3831},
 {123,3838},
 {124,3844},
 {125,3850},
 {126,3856},
 {127,3862},
 {128,3868},
 {129,3874},
 {130,3879},
 {131,3885},
 {132,3890},
 {133,3895},
 {134,3900},
 {135,3904},
 {136,3909},
 {137,3914},
 {138,3918},
 {139,3922},
 {140,3926},
 {141,3930},
 {142,3934},
 {143,3938},
 {144,3942},
 {145,3946},
 {146,3949},
 {147,3952},
 {148,3956},
 {149,3959},
 {150,3962},
 {151,3965},
 {152,3968},
 {153,3971},
 {154,3974},
 {155,3977},
 {156,3980},
 {157,3982},
 {158,3985},
 {159,3987},
 {160,3990},
 {161,3992},
 {162,3994},
 {163,3997},
 {164,3999},
 {165,4001},
 {166,4003},
 {167,4005},
 {168,4007},
 {169,4009},
 {170,4011},
 {171,4013},
 {172,4015},
 {173,4016},
 {174,4018},
 {175,4020},
 {176,4021},
 {177,4023},
 {178,4024},
 {179,4026},
 {180,4027},
 {181,4029},
 {182,4030},
 {183,4032},
 {184,4033},
 {185,4034},
 {186,4035},
 {187,4037},
 {188,4038},
 {189,4039},
 {190,4040},
 {191,4041},
 {192,4043},
 {193,4044},
 {194,4045},
 {195,4046},
 {196,4047},
 {197,4048},
 {198,4049},
 {199,4050},
 {200,4050},
 {201,4051},
 {202,4052},
 {203,4053},
 {204,4054},
 {205,4055},
 {206,4055},
 {207,4056},
 {208,4057},
 {209,4058},
 {210,4058},
 {211,4059},
 {212,4060},
 {213,4061},
 {214,4061},
 {215,4062},
 {216,4062},
 {217,4063},
 {218,4064},
 {219,4064},
 {220,4065},
 {221,4065},
 {222,4066},
 {223,4067},
 {224,4067},
 {225,4068},
 {226,4068},
 {227,4069},
 {228,4069},
 {229,4070},
 {230,4070},
 {231,4070},
 {232,4071},
 {233,4071},
 {234,4072},
 {235,4072},
 {236,4073},
 {237,4073},
 {238,4073},
 {239,4074},
 {240,4074},
 };

 hosal_adc_dev_t adc0 = {
    .cb = NULL,
    .config = {
        .mode = HOSAL_ADC_ONE_SHOT,
        .pin = GPIO_ADC_PIN,
        .sampling_freq = 340,
    },
    .dma_chan = 0,
    .p_arg = NULL,
    .port = 0,
};
void adc_temp_init(void)
{
    hosal_adc_init(&adc0);
    hosal_adc_add_channel(&adc0, ADC_CHANNEL);
}

int get_temp_value(void)
{
    int ret = hosal_adc_value_get(&adc0, ADC_CHANNEL, 100);
    blog_info("ADC = %ld \r\n", ret);
    return ret;

}

int get_temperature(void)
{
    int adc_value;
    const unsigned int tableSize = sizeof(tempTable) / sizeof(tempTable[0]);
    unsigned int i;

    adc_value=get_temp_value();

    // 边界检查(注意与采样NTC时方向相反)
    if(adc_value <= tempTable[0][1]) {
        return tempTable[0][0];  // 低于最低温度-30℃
    }
    if(adc_value >= tempTable[tableSize-1][1]) {
        return tempTable[tableSize-1][0];  // 高于最高温度50℃
    }

    // 查表(ADC值随温度升高而增大)
    for(i = 0; i < tableSize-1; i++) {
        if(adc_value >= tempTable[i][1] && adc_value < tempTable[i+1][1]) {
            // 线性插值计算温度
            return tempTable[i][0] + (int)((float)(tempTable[i+1][0] - tempTable[i][0]) *
                   (float)(adc_value - tempTable[i][1]) /
                   (float)(tempTable[i+1][1] - tempTable[i][1]));
        }
    }

    return 0xFFFF;  // 错误代码(正常情况不会执行到这里)
}


3、main.c修改

void main()
{
    bl_sys_init();

    adc_temp_init();
    pwm_led_init();

    puts("[OS] proc_main_entry task...\r\n");
    xTaskCreate(TaskUart, "TaskUart", 2048, NULL, 15, NULL);
    xTaskCreate(TaskTemp, "TempAdc", 1024, NULL, 15, NULL);
    xTaskCreate(proc_main_entry, (char *)"main_entry", 1024, NULL, 15, NULL);
}

增加adc_temp_init();//ADC初始化

RTOS建立一个新的TASK,用于处理温度采集:

xTaskCreate(TaskTemp, "TempAdc", 1024, NULL, 15, NULL);

4、TaskTemp任务

void TaskTemp(void *param)
{
    int tempval;
    uint8_t data[5] = {0x4e,0x4f,0x60,0x01,0x00};
    while (1)
    {
        tempval=get_temperature();
        data[4]=(uint8_t)tempval;
        UUID1_SendNotify(strlen((char *)data), data);
        vTaskDelay(1000);
    }

}

通过get_temperature()采集到温度数据

调用UUID1_SendNotify函数发送数据到已订阅UUID1的BLE主机设备(手机)

数据格式为

固定数据头 固定数据头 标识(表示后面是温度) 未知 温度值
0x4e 0x4f 0x60 0x01 0x00

手机运行APP(友商软件,非安信可)

5.jpg

搜索BLE

6.jpg

连接后可以看到上报的温度数据

4.jpg

──── 0人觉得很赞 ────

使用道具 举报

看电路板就知道是高手,赞~👍
棒~
不错,可以参考你蓝牙部分😄
做一下低功耗看看,可以用电池供电
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28290 个
  • 话题数: 40266 篇