Poslední vylepšená verze měření teploty pomocí interního termistoru a ADC na Raspberry Pi Pico. Teploměr je ocejchovaný podle přesnějšího teploměru. Naměřená hodnota je zobrazena na OLED displeji s čipem SDD1306.
Konstrukce
Teploměr ver. 8

Program
main.c
/* Cejchovaný teploměr main.c
* (c) Jirka Chráska 2025; <jirka@lixis.cz>
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/adc.h"
#include "ssd1306.h"
#include "font_spleen_8x5.h"
#include "font_spleen_16x8a.h"
// definice dipleje
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 50000
#define SLEEPTIME 55
void setup_gpios(void);
void animation(void);
// nastavení I2C i2c0
// SDA pin GP4
// SCL pin GP5
// https://i.sstatic.net/P4Mkp.jpg
// https://raspberrypi.stackexchange.com/questions/106482/rpi3b-ssd1306-oled-i2c-interface-problem
void setup_i2c_gpios(void) {
// nelze používat i2c_default, je tam zajímavá chyba kdy aplikace běží bez problémů po nahrání,
// ale po restartu Pica se displej neinicializuje a je temný
i2c_init(i2c0, I2C_FREQ);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
// gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); // pull up rezistory jsou na displeji
// gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
}
// vraci prumernou hotnotu ADC interniho termistoru * 10
uint32_t cteni_teploty(void)
{
uint32_t sum = 0;
uint32_t avg = 0;
uint16_t h[64] = {0};
for(int i=0; i<64; i++) {
h[i] = adc_read();
sum += h[i];
}
avg = sum*10/64;
return avg;
}
void teplota(void) {
// inicializace ADC
// nastavení PWM měniče na malý šum
gpio_set_function( 23, GPIO_FUNC_SIO );
gpio_set_dir( 23, true );
gpio_put(23, 1);
gpio_set_function( 25, GPIO_FUNC_SIO );
gpio_set_dir( 25, true );
sleep_ms(200);
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
// inicializace dipleje
ssd1306_t disp;
char buf[128];
gpio_put(25,1);
disp.external_vcc = false;
ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, i2c0);
ssd1306_poweron(&disp);
ssd1306_clear(&disp);
sprintf(buf,"%s","(c) Jiří Chráska 2025");
ssd1306_draw_string_with_font(&disp, 0, 1, 1, font_spleen_8x5, buf);
ssd1306_draw_line(&disp, 0, 13, 127, 13);
sprintf(buf,"%s","jirka@lixis.cz");
ssd1306_draw_string_with_font(&disp, 0, 15, 1, font_spleen_8x5, buf);
ssd1306_show(&disp);
sleep_ms(4000);
gpio_put(25,0);
uint32_t raw=0, rawold=0;
float temp=0, tempold=0;
for(;;) {
rawold = raw;
tempold = temp;
raw = cteni_teploty();
// spočítané hodnoty konverze podle etalonového teploměru
temp = -0.036824*raw + 348.5;
sprintf(buf, "%5u; %2.1f C", raw, temp);
printf("%4u; %2.1f C\n", raw, temp);
ssd1306_clear(&disp);
ssd1306_draw_string_with_font(&disp, 0, 0, 1, font_spleen_16x8a, buf);
sprintf(buf, "%5u; %2.1f C", rawold, tempold);
ssd1306_draw_string_with_font(&disp, 0, 16, 1, font_spleen_16x8a, buf);
ssd1306_show(&disp);
gpio_put(25,1);
sleep_ms(2000);
gpio_put(25,0);
}
}
int main() {
stdio_init_all();
printf("Konfigurace pinů dipleje...\n");
setup_i2c_gpios();
printf("Jedeme měřit teplotu...\n");
teplota();
return 0;
}