Měření teploty pomocí vnitřního teplotního senzoru a zobrazení výsledků na dvouřádkovém displeji 1602.
Použité součástky
-
Raspberry Pi Pico
-
LCD displej s obvodem HD44780 a I2c převodníkem PCF8574
-
rezistor 10 kOhm 2 kusy ( rezistor 610 Ohm 5ks, LED 5ks pro ver. 1.1 )
-
powerbanka 5V/10000 mAh
-
drátky
Schéma zapojení
Zdrojové soubory
Popis
Využijeme vnitřní teplotní čidlo, které převádí teplotu na napětí a analogově digitální převodník (ADC), který převádí napětí ně číselnou hodnotu. Výsledné hodnoty budeme zobrazovat na dvouřádkovém dipleji 1602 a využijeme hotový modul pro zobrazení českých znaků src/lcd_czech_chars.c a k němu hlavičkový soubor src/lcd_czech_chars.h (je malinko upraven a přidán hlavičkový soubor).
/* teplota.c
* Měření teploty RPi Pico ver. 1.0
* (c) Jirka Chráska 2024, <jirka@lixis.cz> All rights reserved.
*
* Licence BSD
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "lcd_czech_chars.h"
int main(void)
{
char buffer[40];
// konfigurace debugování pře USB
stdio_init_all();
// konfigurace displeje
init_gpio();
stdio_init_all();
lcd_characters_init();
lcd_init();
lcd_clear();
// konfigurace analogově digitálního převodníku ADC
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
// nekonečná smyčka měření
while(1){
uint16_t raw = adc_read();
const float conversion_factor = 3.3f / (1<<12);
float result = raw * conversion_factor;
float temp = 27 - (result -0.706)/0.001721;
snprintf(buffer,40,"%2.1f °C ",temp);
printf("%s\n",buffer);
lcd_home();
lcd_set_cursor(0,0);
if(temp < -0.5) {
cz_print("Pozor námraza! ");
}
else if (temp > -0.5 && temp < 0.5) {
cz_print("Klouže to! ");
}
else if (temp >= 0.5 && temp < 10) {
cz_print("Venkovní teplota ");
}
else if (temp >= 10 && temp < 30){
cz_print("Vnitřní teplota ");
}
else {
cz_print("Tropické vedro ");
}
lcd_set_cursor(1,0);
cz_print(buffer);
sleep_ms(2000);
}
}
Výsledky měření


Srovnáním našeho teploměru s komerčním teploměrem dopadlo mizerně. Problém je v přesnosti měření, kde se naměřená teplota na Picu liší od komerčního teploměru i měříčího přístroje MUSTOOL MDS8207 s termočlánkem, který je kalibrován a má přesnost 2%+2°C.
| Pico teploměr | WEE HG7904 | Mustool MDS8207 |
|---|---|---|
13.1 |
17.6 |
19.5 |
13.1 |
17.9 |
20.9 |
13.1 |
17.5 |
20.9 |
Výsledky měření ukazují, že pro zlepšení přesnosti měření bude potřeba použít externí termistor se změřenou charakteristikou a udělat kalibraci. Problém je v tom že interní referenční napětí na RPi Pico není moc přesné, a měřící sensor má velmi malou odchylku napětí v závislosti na teplotě. Viz diskuse na Raspberry Pi forum.
V datasheetu na straně 566 je poznámka:
| The on board temperature sensor is very sensitive to errors in the reference voltage. If the ADC returns a value of 891 this would correspond to a temperature of 20.1°C. However if the reference voltage is 1% lower than 3.3V then the same reading of 891 would correspond to 24.3°C. You would see a change in temperature of over 4°C for a small 1% change in reference voltage. Therefore if you want to improve the accuracy of the internal temperature sensor it is worth considering adding an external reference voltage |
Bude potřeba změřit refereční napětí 3.3V přesným voltmetrem a provést korekci nebo připojit přesnější externí referenci 3.3V. V mém případě jsem změřil referenční napětí 3.239 V, což je odchylka -1.8 %. Pes je zakopaný tady.

Rovnice pro určení teploty:
Vhodný sensor by mohl být třeba Waveshare 20232, ale je drahý (979 Kč). Nebo levnější čidla: DS18B20 Digitální vodotěsné čidlo teploty 1m datasheet UMW DS18B20 Keyes KY-028 NTC Čidlo teploty datasheet LM393
Doplněné zapojení (verze 1.1)
Zapojení doplněno o indikaci úrovně teploty.
/* teplota.c
* Měření teploty RPi Pico, ver. 1.1
* (c) Jirka Chráska 2024, <jirka@lixis.cz> All rights reserved.
*
* BSD licence
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/gpio.h"
#include "lcd_czech_chars.h"
const uint LEDR = 11;
const uint LEDY = 12;
const uint LEDG = 13;
const uint LEDB = 14;
const uint LEDW = 15;
int main(void)
{
char buffer[40];
// konfigurace debugování pře USB
stdio_init_all();
// konfigurace displeje
init_gpio();
stdio_init_all();
lcd_characters_init();
lcd_init();
lcd_clear();
// konfigurace analogově digitálního převodníku ADC
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
// inicializace LED
gpio_init(LEDR);
gpio_init(LEDY);
gpio_init(LEDG);
gpio_init(LEDB);
gpio_init(LEDW);
gpio_set_dir(LEDR,GPIO_OUT);
gpio_set_dir(LEDY,GPIO_OUT);
gpio_set_dir(LEDG,GPIO_OUT);
gpio_set_dir(LEDB,GPIO_OUT);
gpio_set_dir(LEDW,GPIO_OUT);
gpio_put(LEDR,0);
gpio_put(LEDY,0);
gpio_put(LEDG,0);
gpio_put(LEDB,0);
gpio_put(LEDW,0);
sleep_ms(250);
// test LED
gpio_put(LEDR,1);
gpio_put(LEDY,1);
gpio_put(LEDG,1);
gpio_put(LEDB,1);
gpio_put(LEDW,1);
sleep_ms(1000);
// nekonečná měřící smyčka
while(1){
uint16_t raw = adc_read();
const float conversion_factor = 3.27f / (1<<12); (1)
float result = raw * conversion_factor;
float temp = 27 - (result -0.706)/0.001721;
snprintf(buffer,40,"%2.1f °C ",temp);
printf("%s\n",buffer);
lcd_home();
lcd_set_cursor(0,0);
if(temp < -0.5) {
cz_print("Pozor námraza! ");
gpio_put(LEDR,0);
gpio_put(LEDY,0);
gpio_put(LEDG,0);
gpio_put(LEDB,0);
gpio_put(LEDW,1);
}
else if (temp > -0.5 && temp < 0.5) {
cz_print("Klouže to! ");
gpio_put(LEDR,0);
gpio_put(LEDY,0);
gpio_put(LEDG,0);
gpio_put(LEDB,1);
gpio_put(LEDW,0);
}
else if (temp >= 0.5 && temp < 10) {
cz_print("Venkovní teplota ");
gpio_put(LEDR,0);
gpio_put(LEDY,0);
gpio_put(LEDG,1);
gpio_put(LEDB,0);
gpio_put(LEDW,0);
}
else if (temp >= 10 && temp < 30){
cz_print("Vnitřní teplota ");
gpio_put(LEDR,0);
gpio_put(LEDY,1);
gpio_put(LEDG,0);
gpio_put(LEDB,0);
gpio_put(LEDW,0);
}
else {
cz_print("Tropické vedro ");
gpio_put(LEDR,1);
gpio_put(LEDY,0);
gpio_put(LEDG,0);
gpio_put(LEDB,0);
gpio_put(LEDW,0);
}
lcd_set_cursor(1,0);
cz_print(buffer);
sleep_ms(2000);
}
}
| 1 | Konstanta 3.27 byla určena experimentálně pomocí teploměru. |
