Naučíme se používat analogově-digitální převodník (zkratka ADC) na Raspberry Pi Pico a zobrazovat výsledky měření na OLED displeji (SSD1306). Nejprve budeme zobrazovat naměřené hodnoty pomocí USB na obrazovce, později připojíme malý OLED displej.

Měření napětí pomocí ADC

Raspberry Pi Pico má v sobě analogově digitální převodník, který umožňuje měřit napětí přivedené na jeho vstup. Tento převodník umožňuje měřit kladné napětí v rozsahu 0 až 3.3V. Maximální napětí přivedené na vstup ADC nesmí překročit 3.3V ! Pokud potřebuje měřit napětí větší než 3.3V, musíme ho snížit odporovým děličem.

Raspberry Pi Pico má k dispozici 4 vstupy pro ADC převodník, na obrázku jsou označeny ADC0, ADC1 a ADC2. Čtvrtý vstup ADC3 je připojen k internímu čidlu teploty.

Zapojení

ADC connection diagram

SAR ADC (Successive Approximation Register Analogue to Digital Converter) je kombinace digitálního řadiče a analogového obvodu, jak je ukázáno na nasledujícím obrázku.

ADC umožňuje:

  • Jednorázový nebo volně běžící režim snímání měřených hodnot.

  • Ukládat vzorky měření do FIFO s rozhraním DMA

    • Stimulační časovač (16 celočíselných bitů, 8 zlomkových bitů) pro nastavení volně běžící vzorkovací frekvence.

    • Round-robin vzorkování více kanálů ve volném režimu snímání.

    • Volitelný pravý posun na 8 bitů ve volně běžícím režimu snímání, takže vzorky mohou být DMA převedeny do bajtové vyrovnávací paměti v systémové paměti.

Převodník je dvanáctibitový, to znamená že napětí 0V na vstupu odpovídá naměřená hodnota 0 a 3.3V odpovídá hodnota 4096 (\(2^{12}\)).

Vnitřní schema SAR ADC

SAR ADC block diagram

Je nutno hned zpočátku říci, že tento převodník je velmi nepřesný a poměrně nestabilní. Je to dáno tím, že nemáme k dispozici stabilní zdroj referenčního napětí 3.3V, ale refereční napětí se získává přímo z měniče 3.3V (pin36 3V3(OUT)). U každého Pica měnič vyrábí poněkud jiné napětí, což lze snadno změřit přesným voltmetrem. Navíc toto napětí kolísá poměrně dost (šumí), protože měnič se snaží být úsporný.

Později ukážeme, jak zlepšit přesnost měření přepnutím měniče do méně úsporného režimu a jak získat stabilní refereční napětí pomocí externí napěťové reference TL431, což nám umožní zpřesnit naše měření. V cvičení naměříte napětí pomocí voltmetru a porovnáte s výstupem vašeho programu.

Nejjednodušší způsob použití ADC

Nejjednodušší cestou začít měřit pomocí ADC je změřit jednu hodnotu z jednoho vstupu. Nejprve musíme ADC převodník nahodit.

Inicializace ADC
adc_init();

Potom potřeba nastavit příslušný pin do analogového režimu vstupu. Je to kvůli tomu, že piny mají sdílené funkce. Například fyzický pin 31 může sloužit jako GPIO26 nebo ADC0.

pico pinout

adc_gpio_init( uint input ) (1)
1 input může mít hodnotu: 26, 27, 28.

Potom je třeba nastavit ADC vstup, který budeme používat:

adc_select_input( uint input ) (1)
1 input může mít hodnotu: 0, 1, 2 nebo 3 (interní teplota).

Pokud chceme měřit teplotu pomocí interního čidla, uděláme to takto:

adc_set_temp_sensor_enabled( bool enabled ) (1)
1 Je-li enabled true, čidlo teploty ze zapnuto. Je-li enabled false je čidlo teploty vypnuto.

Jakmile máme všechno nastaveno, můžeme měřit:

static uint16_t adc_read(void);

Funkce vrací jednorázově naměřenou hodnotu jako 16 bitové číslo bez znaménka v rozsahu (0..4096). Musí se zkonvertovat na hodnotu napětí pomocí výrazu:

uint16_t result = adc_read();
float napeti = result * (3.3f / ( 1 << 12 ));

Nejjednodušší program pro měření napětí na vstupu ADC0 bude vypadat takto (budeme přepínat mezi dvěma vstupy ADC1 a ADC2):

/* Měření napětí na diodě na ADC1 a ADC2 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"

int main()
{
stdio_init_all();
adc_init();
adc_gpio_init(27);
adc_gpio_init(28);

while ( 1 ) {
    const float conversion_factor = 3.3f / ( 1 << 12 );
    adc_select_input(1);
    uint16_t result = adc_read();
    printf("Bílá dioda: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    adc_select_input(2);
    result = adc_read();
    printf("Červená dioda: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    sleep_ms(1000);
    }
}
cmake_minimum_required(VERSION 3.13)

set(PICO_BOARD pico)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

project(adc1 C CXX ASM)

pico_sdk_init()

add_executable(adc1
	adc1.c
)


target_link_libraries(adc1
    pico_stdlib
    hardware_adc
)

pico_add_extra_outputs(adc1)
pico_enable_stdio_usb(adc1 1)
pico_enable_stdio_uart(adc1 0)

Výsledky měření si zobrazíme v minicomu:

$ minicom -b 115200 -c on -D /dev/ttyACM0
Při našem programování si terminál s minicomem můžeme nechat otevřený. Minicom umí znovu navázat spojení, i když Pico odpojíme a znovu připojíme.

Výstup bude vypadat takto:

Bílá dioda: raw=0xc8d, napětí=2.588598 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x890, napětí=1.766016 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc8b, napětí=2.586987 V
Červená dioda: raw=0x893, napětí=1.768433 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc86, napětí=2.582959 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x890, napětí=1.766016 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc8d, napětí=2.588598 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc87, napětí=2.583765 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc86, napětí=2.582959 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x891, napětí=1.766821 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc88, napětí=2.584570 V
Červená dioda: raw=0x893, napětí=1.768433 V
Bílá dioda: raw=0xc8c, napětí=2.587793 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x893, napětí=1.768433 V
Bílá dioda: raw=0xc8a, napětí=2.586182 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc8b, napětí=2.586987 V
Červená dioda: raw=0x892, napětí=1.767627 V
Bílá dioda: raw=0xc89, napětí=2.585376 V
Červená dioda: raw=0x893, napětí=1.768433 V
Měření referenčního napětí 3.3V

mereni 3.3V

Měření napětí na červené LED

mereni cervena LED

Měření napětí na bílé LED

mereni bila LED

Šum referenčního napětí 3.3V

scope 3

Z výsledků měření vidíme, že referenční napětí není 3.3V, ale 3.265 V, napětí na červené LED se liší na druhém desetinném místě a napětí na bílé LED také. Z výsledků měření dále vidíme, že naměřené hodnoty napětí na LED kolísají, což by nemělo být. Napětí na LED by mělo být konstantní. Multimetr UNI-T UT61E+ má přesnost 0.01%, takže odchylka je až na 3. desetinném místě. Zkusíme měření zpřesnit. Nastavíme na pinu 23 logickou hodnotu hodnotu 1, čímž přepneme měnič do režimu nešetření energií (bude menší šum měniče), ale zvětší se trochu odběr Pica.

Lepší program

/* Měření 2 napětí na diodě na ADC1 a ADC2 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"

int main()
{
stdio_init_all();
adc_init();
adc_gpio_init(27);
adc_gpio_init(28);
// nastavení měniče na malý šum
gpio_set_function(23, GPIO_FUNC_SIO);
gpio_set_dir( 23, true );
gpio_put( 23, 1 );

while ( 1 ) {
    // oprava konverze pomocí skutečně naměřeného referenčního napětí
    const float conversion_factor = 3.265f / ( 1 << 12 );
    adc_select_input(1);
    uint16_t result = adc_read();
    printf("Bílá dioda: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    adc_select_input(2);
    result = adc_read();
    printf("Červená dioda: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    sleep_ms(1000);
    }
}
Výsledky měření
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc64, napětí=2.528462 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc63, napětí=2.527665 V
Červená dioda: raw=0x879, napětí=1.728951 V
Bílá dioda: raw=0xc62, napětí=2.526868 V
Červená dioda: raw=0x878, napětí=1.728154 V
Bílá dioda: raw=0xc63, napětí=2.527665 V

Je vidět že výsledky měření jsou lepší, naměřená napětí pomocí ADC více odpovídají naměřenému napětí pomocí UNI-T UT61E+. Je to tím, že konverzní faktor je upraven podle skutečného referenčního napětí Pica. Měřené hodnoty ADC také tolik neposkakují, protože byl snížen šum měniče (ale zvětšil se trochu odběr Pica).

Zobrazení naměřených hodnot na OLED displeji s obvodem SDD1306

K zobrazení hodnot použijeme tento malinký displej, který se připojuje pomocí \(I^2C\) sběrnice.

OLED displej SSD1306

displej SSD1306

O \(I^2C\) sběrnici zatím mnoho nevíte, ale je popsána zde: Jak funguje \(I^2C\)sběrnice a z programátorského hlediska \(I^2C\) sběrnice pohledem programátora. I2c sběrnice je jenom komunikační most mezi Picem a vlastním zařízením. Každá periferie připojená k \(I^2C\) sběrnici má svoji adresu (8 bitové číslo) a na této adrese poslouchá o odpovídá na příkazy. Výrobce obvykle udává tuto adresu v datasheetu, pokud ji neudává, tak ji dokážeme jednoduchým prográmkem zjistit. Někdy výrobce umožňuje tuto adresu změnit. Na jednu \(I^2C\) sběrnici můžeme připojit více zařízení, každé zařízení musí mít adresu unikátní. Pico nám umožňuje používat dvě nezávislé \(I^2C\) sběrnice: I2C0 a I2C1. \(I^2C\) sběrnice používá k propojení s Picem dva dráty SDA (data) a SCL (hodiny). Na zařízení jsou obvykle takto označeny, někdy je pro hodinový signál místo SCL použito označení SCK.

Kam zapojíme vodiče SDA a SCL na Picu je celkem jedno, ale musíme to udělat podle obrázku. Například I2C0 bude mít SDA pin na fyzickém pinu 6 (GP4) a SCL na fyzickém pinu 7 (GP5). Tyto piny jsou vždycky u sebe. Nebo třeba I2C1 může mít SDA na pinu 19 (GP14) a SCL na pinu 20 (GP15).

Program pro zjištění \(I^2C\) adresy zařízení je ke stažení zde i2c_bus_scan.uf2. Funguje pro SDA na pinu 6 (GPIO4) a SCL na pinu 7 (GPIO5), bez pull-up rezistorů. Výstup je zobrazován na stdio pře USB (minicom -b 115200 -c on -D /dev/ttyACM0). Zdroj: bus_scan/bus_scan.c bus_scan/CMakeLists.txt. Pokud program nechce fungovat, nebo nezobrazuje nic, máte zařízení špatně připojené.
Schéma zapojení

schema adc3

Každé zařízení, které chceme používat musíme umět nějak ovládat. Naštěstí pro mnoho zařízení to již udělal nějaký programátor za nás, a nám zbývá jenom jeho knihovnu zakomponovat do našeho projektu a začít používat.

Pro OLED displej je knihovna zde: https://sspvc.lixis.cz/pmp/OLED1306/oled_1306.html. Tuto knihovnu naprogramoval pan David Schramm, já jsem do ní doplnil česká písmenka.

Do našeho projektu potřebujeme soubory:

  • ssd1306.h — hlavičkový soubor s deklaracemi funkcí

  • ssd1306.c — implementace funkcí

  • font.h — definice anglického fontu 8x5 pixelů (znaky 32 až 128) od Davida Schramma.

  • font_spleen_8x5.h — definice českého fontu 8x5 pixelů (kódování ISO-8859-2) ode mne.

  • font_spleen_16x8a.h — definice českého fontu 16x8 pixelů (kódování ISO-8859-2) ode mne.

Hlavičkové soubory s nepoužívanými fonty můžeme vynechat.

Do CMakeLists.txt zařadíme knihovnu hardware_i2c a ssd1306 takto:

cmake_minimum_required(VERSION 3.13)

set(PICO_BOARD pico)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

project(adc3 C CXX ASM)
pico_sdk_init()

add_executable(adc3
	adc3.c
	ssd1306.c
)

target_link_libraries(adc3
    pico_stdlib
    hardware_adc
    hardware_i2c
)

pico_add_extra_outputs(adc3)
pico_enable_stdio_usb(adc3 1)
pico_enable_stdio_uart(adc3 0)

Do C programu zařadíme knihovny takto:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"

#include "ssd1306.h"
#include "font_spleen_8x5.h"
#include "font_spleen_16x8a.h"

Celý program:

/* Měření 2 napětí na diodě na ADC2 a ADC2 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/i2c.h"
#include "lib/ssd1306.h"
#include "lib/font_spleen_8x5.h"
#include "lib/font_spleen_16x8a.h"

const uint8_t num_chars_per_disp[]={20,20,20,20,20};
const uint8_t *fonts[2]= {font_spleen_8x5, font_spleen_16x8a};

#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 32
#define I2C_ADDRESS 0x3C
#define I2C_FREQ 400000

// nastavení I2C sběrnice
void setup_i2c(void) {
    // nelze použít i2c_default -- aplikace bude chodit nekorektně (zajímavá chyba)
    i2c_init(i2c0, I2C_FREQ);
    gpio_set_function(4, GPIO_FUNC_I2C);
    gpio_set_function(5, GPIO_FUNC_I2C);
    // Pull-up rezistory jsou v displeji, netřeba nastavovat
    // gpio_pull_up(4);
    // gpio_pull_up(5);
}


int main()
{
char buf[128];
ssd1306_t disp;
const float conversion_factor = 3.265f / ( 1 << 12 );
uint16_t result;
    gpio_set_function( 25, GPIO_FUNC_SIO );
    gpio_set_dir( 25, true );
    gpio_put(25,1);
    sleep_ms(200);
    stdio_init_all();
    setup_i2c();
    adc_init();
    adc_gpio_init(27); // červená LED   ADC1
    adc_gpio_init(28); // bílá LED      ADC2
    adc_gpio_init(26); // potenciometr  ADC0
// nastavení měniče na malý šum
    gpio_set_function(23, GPIO_FUNC_SIO);
    gpio_set_dir( 23, true );
    gpio_put( 23, 1 );

// nastavení displeje SSD1306
    disp.external_vcc = false;
    ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, i2c0); // inicializace
    ssd1306_poweron(&disp); // zapnutí dipleje
    //ssd1306_clear(&disp);   // vymazání displeje

while ( 1 ) {

    gpio_put(25,0);
    adc_select_input(1);
    result = adc_read();
    // výstup na stdio
    printf("Bílá dioda: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    // výstup na displej
    ssd1306_clear(&disp);
    sprintf(buf, "D1: 0x%03x %5.3f V", result, result * conversion_factor);
    ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_8x5, buf);
    //ssd1306_show(&disp); // zobrazíme písmenka na displeji

    adc_select_input(2);
    result = adc_read();
    // výstup na stdio
    printf("Červená dioda: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    // výstup na druhý řádek displeje
    sprintf(buf, "D2: 0x%03x %5.3f V", result, result * conversion_factor);
    ssd1306_draw_string_with_font(&disp, 0, 10, 1, font_spleen_8x5, buf);
    //ssd1306_show(&disp); // zobrazíme písmenka na displeji

    adc_select_input(0);
    result = adc_read();
    // výstup na stdio
    printf("Potenciometr: raw=0x%03x, napětí=%f V\n", result, result * conversion_factor);
    // výstup na třetí řádek displeje velkým fontem
    sprintf(buf, "0x%03x %5.3f V", result, result * conversion_factor);
    ssd1306_draw_string_with_font(&disp, 0, 18, 1, font_spleen_16x8a, buf);
    ssd1306_show(&disp); // zobrazíme písmenka na displeji
    gpio_put(25,1);
    sleep_ms(1000);
    }
}
Je velmi zvláštní, že pokud program nahrajeme na Pico, tak funguje bez problémů. Displej ukazuje co má. Pokud však Pico restartujeme, tak je displej tmavý a nic na něm není. U této chyby zatím neznám příčinu. Vyřešil jsem to tak, že jsem nechal blikat interní LED. Bez blikání program nefunguje pořádně.

Měření teploty interním čidlem

Kondenzátory C1 (keramický) a C2 (elektrolytický) stabilizuje napětí 3.3V, snižuje šum referenčního napětí a zlepšuje tak stabilitu čtení teploty.

link:teplota/teplota.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* Měření teplota na ADC3 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/i2c.h"
#include "lib/ssd1306.h"
#include "lib/font_spleen_8x5.h"
#include "lib/font_spleen_16x8a.h"

const uint8_t num_chars_per_disp[]={20,20,20,20,20};
const uint8_t *fonts[2]= {font_spleen_8x5, font_spleen_16x8a};

#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 32
#define I2C_ADDRESS 0x3C
#define I2C_FREQ 400000

// nastavení I2C sběrnice
void setup_i2c(void)
{
    // nelze použít i2c_default -- aplikace bude chodit nekorektně (zajímavá chyba)
    i2c_init(i2c0, I2C_FREQ);
    gpio_set_function(4, GPIO_FUNC_I2C);
    gpio_set_function(5, GPIO_FUNC_I2C);
    // Pull-up rezistory jsou v displeji, netřeba nastavovat
}


int main()
{
char buf[128];
ssd1306_t disp;
const float conversion_factor = 3.3f / ( 1 << 12 );
uint16_t result;
float teplota;
float adc;
    // bez blikání LEDkou nechce displej zobrazovat
    gpio_set_function( 25, GPIO_FUNC_SIO );
    gpio_set_dir( 25, true );
    gpio_put(25,1);
    sleep_ms(200);
    stdio_init_all();
    setup_i2c();
// nastavení a výběr interního čidla
    adc_init();
    adc_set_temp_sensor_enabled(true);
    adc_select_input(4);

// nastavení měniče na malý šum
    gpio_set_function(23, GPIO_FUNC_SIO);
    gpio_set_dir( 23, true );
    gpio_put( 23, 1 );

// nastavení displeje SSD1306
    disp.external_vcc = false;
    ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, i2c0); // inicializace
    ssd1306_poweron(&disp); // zapnutí dipleje


while ( 1 ) {
    gpio_put(25,0); // bez blikání LEDkou nechce displej zobrazovat
    result = adc_read();
    adc = result * conversion_factor;
    // teplota bez korekce
    teplota = 27.0f - (adc - 0.706f) / 0.001721f;
    // korekce pro moje konkrétní Pico
    // teplota = 26.5f - (adc - 0.706f) / 0.001721f;
    // výstup na stdio
    printf("Teplota: raw=0x%03x, teplota=%f ˚C\n", result, teplota);
    // výstup na displej
    ssd1306_clear(&disp);
    sprintf(buf, "Sensor: 0x%03x", result);
    ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_16x8a, buf);
    sprintf(buf, "Teplota:%3.1f\xb0" "C", teplota);
    ssd1306_draw_string_with_font(&disp, 0, 16, 1, font_spleen_16x8a, buf);
    ssd1306_show(&disp); // zobrazíme písmenka na displeji
    sleep_ms(100);
    gpio_put(25,1);
    sleep_ms(900);
    }
}

Korekci pro moje konkrétní Pico jsem udělal podle přesného teploměru s čidlem BME280 viz :\(I^2C\) sběrnice pohledem programátorana — konci článku:

    teplota = 26.5f - (adc - 0.706f) / 0.001721f;

Moje Pico ukazovalo o 0.5˚C větší hodnotu.

Fungující teploměr

fungujici teplomer

Fungující teploměr

fungujici teplomer2

Zdroje a odkazy