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í

Pico 1602 LCD I2C schema
Figure 1. Schema 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
/* 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í

IMG 20240113 031144

IMG 20240113 031603

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.

Závislost naměřeného napětí na teplotě vnitřního teplotního čidla při referenčním napětí 3.3V přesně.

Vbe vs temperature 1024x576

Rovnice pro určení teploty:

\[\begin{aligned} V - V_1 &= m\cdot(T - T_1) \\ V - 0.706 &= -0.001721\cdot(T - 27) \\ \end{aligned}\]
\[\boxed{T = 27 - \frac{V-0.706}{0.001721} [°C]}\]

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.

Doplněné schéma zapojení

Pico 1602 LCD I2C schema LED

teplota.c
/* 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.
Lepší teploměr (přesnost +/- 1°C)

cejchovany teplomer

Zdroje a odkazy