В микроконтроллер RP2040 на плате Raspberry Pi Pico встроен аналоговый датчик температуры. Датчик температуры внутри микроконтроллера подключён к ADC4 (четвёртый канал аналогово-цифрового преобразователя АЦП) микроконтроллера.

4.9.5. Датчик температуры

Датчик температуры измеряет напряжение Vbe смещённого биполярного диода, подключённого к пятому каналу АЦП (AINSEL=4).
Как правило, Vbe = 0,706 В при 27 градусах Цельсия, с температурным градиентом -1,721 мВ на градус. Следовательно, температуру можно аппроксимировать следующим образом:

T = 27 - (ADC_voltage - 0,706) / 0,001721

Поскольку значения Vbe и его градиента могут варьироваться в рабочем температурном диапазоне и от экземпляра к экземпляру устройства, для получения точных измерений может потребоваться дополнительная калибровка пользователем.

Перед использованием источник смещения датчика температуры должен быть включён через бит CS.TS_EN. Это увеличивает потребление тока от источника ADC_AVDD примерно на 40 мкА.

"Datasheet RP2040". Перевод с английского стр. 584.

Чтобы измерить температуру кристалла микроконтроллера RP2040 с помощью встроенного в микроконтроллер аналогового датчика температуры необходимо воспользоваться встроенным в микроконтроллер аналогово-цифровым преобразователем АЦП (ADC). Вывод данных из программы будет происходить в монитор последовательного порта компьютера через USB интерфейс.  С учётом изложенного файл CMakeLists.txt будет иметь вид представленный в листинге 1.

cmake_minimum_required(VERSION 3.13)        # Минимальная версия CMake

include(pico_sdk_import.cmake)              # Импорт Pico SDK

project(CPUtemperature)                     # Имя проекта

pico_sdk_init()                             # Инициализация SDK

add_executable(CPUtemperature main.c)       # Создание исполняемого файла из указанного исходника

target_link_libraries(CPUtemperature        # Подключение обязательных библиотек
    pico_stdlib                             # Базовая функциональность
    hardware_adc                            # Работа с АЦП
)

pico_enable_stdio_uart(CPUtemperature 0)    # Настройка вывода: отключить UART
pico_enable_stdio_usb(CPUtemperature 1)     # Настройка вывода: включить USB

pico_add_extra_outputs(CPUtemperature)      # Генерация UF2/BIN/HEX файлов

Лист. 1. Файл CMakeLists.txt

В программе лист. 2 настроим микроконтроллер на вывод значений измерений напряжения выполняемых АЦП по четвёртому каналу ADC4.

#include <stdio.h>              // Стандартный ввод/вывод
#include "pico/stdlib.h"        // Базовые функции Pico SDK
#include "hardware/adc.h"       // Работа с АЦП (аналогово-цифровым преобразователем)

int main() {
    stdio_init_all();           // Инициализация USB/UART для printf
    adc_init();                 // Включение блока АЦП
    adc_select_input(4);        // Выбор 4-го канала АЦП (встроенный датчик температуры)

    while (true) {              // Бесконечный цикл
        sleep_ms(1000);         // Пауза 1 секунда между измерениями
        int adc = adc_read();   // Чтение сырого значения АЦП (0-4095)
        
        // Вывод результата преобразования:
        printf("Значение, полученное в результате АЦП преобразования: %d\n", adc);
    }
}

Лист. 2. Файл main.c

Результат работы программы лист. 2 показан на рис. 1.

Рис. 1. Serial Monitor.

Аналогово-цифровой преобразователь

  • Характеристики АЦП RP2040:
  • Разрешение 12-битное (диапазон 0-4095)
  • Скорость: до 500 тыс. выборок/сек (500 kSPS)
  • 5 аналоговых каналов:
    • GPIO26-28: внешние каналы 0-2
    • GPIO29: измерение напряжения питания (ADC_VREF)
    • Канал 4: встроенный датчик температуры
  • Фиксированное опорное напряжение 3.3V (изменяется только через внешний делитель)

Практический совет: При работе с датчиком температуры включайте источник смещения (adc_set_temp_sensor_enabled(true))

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"

int main() {
    stdio_init_all();
    adc_init();
    adc_select_input(4);
    adc_set_temp_sensor_enabled(true);      // Включение встроенного датчика температуры

    while (true) {
        sleep_ms(1000);
        int adc = adc_read();
        printf("Значение, полученное в результате АЦП преобразования: %d\n", adc);
    }
}

Лист. 3. Файл main.c

В программе лит. 2 включён источник смещения датчика температуры. Это увеличивает потребление тока от источника ADC_AVDD примерно на 40 мкА.

Результат работы программы лист. 3 показан на рис. 2.

Рис. 2. Serial Monitor.

Микроконтроллер RP2040, работающий под управлением программы лист. 3 измеряет напряжение на входе АЦП ADC4 и выдаёт цифровые значения, например 882. Напомним, к ADC4 подключён смещённый биполярный диод напряжение на котором имеет некоторый температурный дрейф. Разберёмся, как преобразовать значение, возвращаемое АЦП в значение измеренного напряжения.

АЦП измеряет напряжения в диапазоне от 0 Вольт до напряжения на выводе 34 микроконтроллера обозначаемого на схемах как ADC_VREF/AVDD. На плате Raspberrry Pi Pico  напряжение на выводе ADC_VREF/AVDD равно 3.3 Вольта. И так, мы имеем преобразователь значений напряжения от 0 до 3.3 Вольт в 12 битное число в диапазоне от 0 до 4095 (4096 значений).

Коэффициент преобразования АЦП, его масштаб, можно посчитать по формуле:

k = 3.3 Вольта / 4096 = 0,000805664 Вольта

Если умножить на этот коэффициент значение полученное АЦП, мы получим значение измеряемого напряжения в Вольтах.

Изменим программу лист. 3 таким образом, чтобы она выводила на монитор последовательного порта напряжение измеренное на входе ADC4 в Вольтах:

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"

int main() {
    stdio_init_all();
    adc_init();
    adc_select_input(4);
    adc_set_temp_sensor_enabled(true);

    while (true) {
        sleep_ms(1000);
        float voltage = adc_read() * 3.3f / 4096;      // Единица измерения Вольт
        printf("Напряжение, измеренное АЦП на входе ADC4: %.4f Вольт\n", voltage);
    }
}

Лист. 4. Файл main.c

Рис. 3. Serial Monitor.

Осталось перевести напряжение, измеренное АЦП на датчике температуры в градусы Цельсия. Вставим в программу листинг 4 формулу из datasheet микроконтроллера RP2040. Смотрите формулу в начале этой статьи.

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"

int main() {
    stdio_init_all();
    adc_init();
    adc_select_input(4);
    adc_set_temp_sensor_enabled(true);

    while (true) {
        sleep_ms(1000);
        float voltage = adc_read() * 3.3f / 4096;      // Единица измерения Вольт
        float temp = 27.0f - (voltage - 0.706f) / 0.001721f; // Единица измерения C
        printf("Температура кристалла мк, измеренная АЦП: %.1f °C\n", temp);
    }
}

Лист. 5. Файл main.c

Рис. 4. Serial Monitor.

Задание. Переведите температуру микроконтроллера из градусов Цельсия в градусы по Фаренгейту. Формула:

F = C × 9/5 + 32

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"

int main() {
    stdio_init_all();
    adc_init();
    adc_select_input(4);
    adc_set_temp_sensor_enabled(true);

    while (true) {
        sleep_ms(1000);
        float voltage = adc_read() * 3.3f / 4096;      // Единица измерения Вольт
        float temp = 27.0f - (voltage - 0.706f) / 0.001721f; // Единица измерения C
        float temp_f = temp * 9.0f / 5 + 32;           // Единица измерения Фаренгейты F
        printf("Температура кристалла мк: %.1f °C (%.1f °F)\n", temp, temp_f);
    }
}

Лист. 6. Файл main.c

Рис. 5. Serial Monitor.

Задание. Перепишите программу листинг 6 дополнив её подробными комментариями.

#include <stdio.h>               // Стандартная библиотека ввода/вывода
#include "pico/stdlib.h"         // Библиотека специфичных для Pico функций
#include "hardware/adc.h"        // Библиотека работы с АЦП

int main() {
    // Инициализация средств вывода (USB/UART для printf)
    stdio_init_all();
    
    // Инициализация АЦП (включает блок аналого-цифрового преобразователя)
    adc_init();
    
    // Выбор 4-го канала АЦП (встроенный датчик температуры)
    adc_select_input(4);
    
    // Включение источника смещения для датчика температуры
    // (необходимо для корректной работы, потребляет ~40 мкА)
    adc_set_temp_sensor_enabled(true);

    // Бесконечный цикл измерений
    while (true) {
        // Пауза 1 секунда между измерениями
        sleep_ms(1000);
        
        /* 
        [ШАГ 1] Чтение и преобразование сырого значения АЦП
        - adc_read() возвращает 12-битное значение (0-4095)
        - 3.3f: опорное напряжение АЦП (3.3 Вольта)
        - 4096: количество шагов АЦП (2^12 = 4096)
        Формула: напряжение = (значение_АЦП * Vref) / 4096
        */
        float voltage = adc_read() * 3.3f / 4096;      // Результат в Вольтах

        /* 
        [ШАГ 2] Расчет температуры в Цельсиях
        Стандартная формула для встроенного датчика RP2040:
        T = 27.0 - (Vbe - 0.706) / 0.001721
        Где:
        - 27.0: калибровочная температура (в °C)
        - 0.706: напряжение Vbe при 27°C (в Вольтах)
        - 0.001721: температурный коэффициент (1.721 мВ/°C)
        */
        float temp = 27.0f - (voltage - 0.706f) / 0.001721f;

        // [ШАГ 3] Конвертация в Фаренгейты: F = C × 9/5 + 32
        float temp_f = temp * 9.0f / 5 + 32;

        // Вывод результатов с одним знаком после запятой
        printf("Температура кристалла мк: %.1f °C (%.1f °F)\n", temp, temp_f);
    }
}

Лист. 7. Файл main.c