由 sujingliang 贡献,Ai-Thinker 进行整理
【Ai-WB2评测】ADC采集NTC热敏电阻通过BLE上报温度
通过NTC(负温度系数)热敏电阻采集温度是一种低成本且广泛应用的方案,尤其适合对精度要求不高、预算有限的场景。

NTC热敏电阻的特点
负温度系数:电阻值随温度升高而降低(非线性关系)。
低成本:单价通常仅几元人民币,远低于数字温度传感器(如DS18B20)。
灵敏度高:在低温区电阻变化更显著,适合检测微小温度变化。
非线性响应:需通过公式或查表法进行线性化处理。
用Ai-WB2搭建电路

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

软件部分
在applications\ble_slave例程基础上修改
1、增加temperature.h处理ADC采集NTC数据
📜 点击展开完整代码
java
#ifndef __TEMPERATURE_H__
#define __TEMPERATURE_H__
//temperature.h
void
adc_temp_init
(
void
)
;
int
get_temp_value
(
void
)
;
int
get_temperature
(
void
)
;
#endif📜 点击展开完整代码
c
void adc_temp_init(void);//初始化ADC
int get_temp_value(void);//采集ADC数值(0-4095)
int get_temperature(void);//将ADC数值转化为温度2、temperature.c实现
📜 点击展开完整代码
java
//
#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修改
📜 点击展开完整代码
java
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任务
📜 点击展开完整代码
java
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(友商软件,非安信可)

搜索BLE

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


