Применение Raspberry Pi Pico

Применение Raspberry Pi Pico | Буркхард Каинка
Raspberry Pi Pico - это недорогая высокопроизводительная плата микроконтроллера с гибкими цифровыми интерфейсами. Он включает в себя собственный чип микроконтроллера RP2040 Raspberry Pi с процессором двухъядерной коры Arm Cortex М0+, работающим до 133 МГц, встроенным 264 КБ SRAM и 2 МБ на борту флэш-памяти, а также 26х многофункциональных контактов GPIO.
Для разработки программного обеспечения доступен либо Raspberry Pi C/C++ SDK, либо микропитон. Существуют также полные ресурсы разработки и учебные пособия, которые помогут вам легко начать работу и быстро интегрировать их в
конечные продукты.
Функции:
- Микроконтроллер RP2040, разработанный Raspberry Pi в Великобритании.
- Процессор двухъядерной коры Arm Cortex M0+, гибкие часы, работающие до 133 МГц.
- 264 КБ SRAM и 2 МБ бортовой флэш-памяти.
- Модуль позволяет пайки прямо на нем.
- USB 1.1 с поддержкой устройства и хоста.
- Низко-мощный сон и неактивные моды.
- Программирование перетаскивания с использованием массового хранения над USB.
- 26x многофункциональные контакты GPIO.
- 2xSPI, 2xl2C, 2xUART, 3x12-битный ADC, 16x управляемые ШИМ-каналы.
- Точные часы и таймер на чипе.
- Датчик температуры.
- Ускоренные библиотеки с плавающей запятой в чипе.
- 8x программируемые машины ввода/вывода (РЮ) для пользовательской периферийной поддержки.
1 Подготовка
Устройства, описанью далее требуют очень мало компонентов. Все, что вам действительно нужно, это Raspberry Pi Pico и кабель microUSB, и вы можете начинать прямо сейчас. Два впаянных 20-контактных разъема и макетная плата удобны для постановки простых экспериментов. Однако схемы можно собрать и пайкой.
Если подключить RPi Pico к ПК с помощью USB-кабеля, сразу же запустится последняя загруженная программа. Альтернативно вы также можете использовать другой источник питания, например USB-блок питания.
Если вы хотите загрузить новую программу, вам необходимо подключить USB- кабель, удерживая кнопку BOOT на плате Pico. Затем Pico образует диск, похожий на USB-накопитель. Внутри находится текстовый файл INF0_UF2.TXT, который можно открыть текстовым редактором:
UF2 Bootloader vl.0 Model: Raspberry Pi RP2
Идентификатор платы: RPI-RP2.
Идентификатор платы: RPI-RP2.
Кроме того, существует HTML-файл, который можно открыть в браузере и который содержит ссылку на страницу Raspberry. Там вы найдете всю необходимую информацию.
Если вы хотите загрузить новую программу, вам достаточно скопировать в каталог соответствующий файл с расширением UF2. Это происходит автоматически в Arduino IDE. Как только файл оказывается на диске, Pico Bootloader использует его и программирует сам.

Если вы пишете программу, и вам часто приходится загружать новую версию, отключение USB-кабеля раздражает. Альтернативно вы можете использовать кнопку сброса, которую вы подключаете между RUN и GND. Для загрузки одновременно нажмите Reset и BOOT и отпустите Reset, удерживая кнопку Boot.

Расширение платы для Arduino IDE, представленное ниже, требует только первого ручного запуска загрузчика. После этого появляется виртуальный последовательный интерфейс, который можно использовать для остановки работающей программы и запуска загрузчика. Переключатель сброса понадобится только в случае ошибки, например, если установлен неправильный COM. Если все работает гладко, для компиляции и загрузки программы достаточно щелчка мыши.
Если кнопка сброса больше не нужна, вместо нее можно вставить конденсатор емкостью 100 нФ, чтобы предотвратить случайный сброс. Если вы поэкспериментируете во время работы контроллера, случайного прикосновения может быть достаточно, чтобы вызвать небольшой помеховый импульс и, таким образом, вызвать сброс. Конденсатор предотвращает такие импульсы и делает эксплуатацию более безопасной.
Большинство читателей, вероятно, уже работали с интерфейсом Arduino. Тогда Arduino IDE уже доступна. В противном случае последнюю версию можно загрузить с домашней страницы Arduino. Когда вы запускаете программу в первый раз, вы устанавливаете используемое оборудование в разделе «Инструменты/Плата». Помимо различных версий Arduino, часто уже установлены другие системы. Однако Пико обычно все еще отсутствует. Если вы выполните поиск в Инструменты/Плата/ Диспетчер плат, вы найдете множество контроллеров, но не расширение платы Raspberry Pi Pico/RP2040 от Эрла Ф. Филхауэра, III. Это не одно из уже предложенных расширений, и его необходимо сначала сообщить в IDE. Расширение можно найти на Github: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
Эту ссылку необходимо ввести в разделе «Файл/Настройки». Об этом сообщает менеджер плат, который затем предлагает её для установки.

После установки Raspberry Pi Pico можно выбрать в разделе «Инструменты/Плата». Это приводит к правильным настройкам, за исключением используемого COM-портаг поскольку Pico еще не сформировал COM-интерфейс. Однако теперь уже можно загрузить первую программу: Pico_Blink.ino. Предполагается, что светодиод на плате начнет мигать. Исходный код компилируется и передается нажатием на символ стрелки (загрузить). При первой загрузке загрузчик все равно необходимо запустить вручную кнопкой BOOT и выполнить сброс или перезагрузку.

Если все работает правильно, светодиод платы 2теперь мигает каждую секунду. Исходный код содержит типичные для Arduino функции setup() и 1oop(), за которыми скрывается нечто большее, чем кажется на первый взгляд. Помимо прочего,
создается виртуальный последовательный интерфейс, хотя в самой программе он пока не используется. Однако он нужен для автоматического запуска загрузчика при следующей загрузке программы.
Как только программа будет успешно запущена, вы услышите типичный звук при входе в систему USB-устройства. Теперь вы можете выбрать COM-порт пико в разделе «Инструменты/Порт». В моем случае это был COM13, но на других компьютерах обычно это другой COM.

Внеся небольшое изменение в исходный код, вы теперь можете проверить, все ли работает так, как хотелось бы. Для этого измените, например, время ожидания для функций задержки. Теперь программа должна скомпилироваться и загрузиться одним щелчком мыши. Измененная скорость перепрошивки подтверждает успех.
Теперь виртуальный последовательный интерфейс также будет использоваться для отправки сообщений на ПК. Программа генерирует возрастающую последовательность чисел и текст. Оба записываются в одной строке, поскольку только вторая команда печати называется Serial.println и, таким образом, создает разрыв строки.
Последовательный интерфейс инициализирован со скоростью передачи 115200 бод. Соответственно, эта скорость также задается в последовательном мониторе. Однако это происходит только по формальным причинам, поскольку виртуальный
COM-интерфейс на самом деле работает намного быстрее и работает с любыми настройками . Это сильно отличается от Arduino, поскольку там микроконтроллер использует реальный последовательный интерфейс, где установленная скорость передачи данных должна быть правильной.
//Pico_Serial
int ne;
void setup () {
Serial.begin(115200);
}
void loop() {
n++;
Serial.print(n);
Serial.printing("hallo");
delay(500);
}

Основная цель расширения заключалась в том, чтобы сделать возможным использование RPi Pico как обычного Arduino. Знакомые функции, такие как digitalWrite, digitalRead, AnalogWrite и AnalogRead, теперь также работают и на Pico.
Кроме того, однако, можно использовать и функции SDK с их значительно расширенными возможностями. Комплект разработки программного обеспечения (SDK) гораздо более обширен и сложен, чем обычное программирование Arduino. Полную документацию по всем функциям можно найти в этом документе:
raspberry-pi-pico-c-sdk.pdf
Её можно скачать со страницы Raspberry
https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html#raspberry-pi-pico-cc-sdk
Новичку документация может показаться слишком обширной и сложной. Это также имело место и для меня. Я хотел решить определенные задачи и поначалу не мог понять, какие опции доступны, и какие функции и настройки для них нужно использовать . Тогда помогли готовые примеры из сети. Теперь я смог найти в документации используемые там функции и постепенно правильно их классифицировать. Возможно, вы чувствуете то же самое. Вначале используйте готовые программы. А там, где вы хотите что-то изменить или адаптировать для других целей , изучите документацию повнимательнее.
Если ваша цель — правильно выучить С и разработать хороший стиль программирования , эта публикация не подойдет. Мой стиль программирования не является образцовым, программы не снабжены подробными комментариями, а также нуждаются в доработке по другим параметрам. Мне просто было интересно решить определенные задачи как можно более коротким путем. Публикация написана с точки зрения инженера-электронщика, для которого программирование — лишь средство для достижения цели.
Когда вы увидите решение, которое я использую для точного расчета времени в микросекундах, некоторые программисты на C скажут, что вы можете узнать стиль старых программ на языке Basic.
Я запрашиваю микросекундный таймер и жду, пока не будет достигнуто определенное время. Профессионал, возможно, предпочтет использовать прерывание по таймеру. В других местах я заполняю области данных циклично, а профи для этого использовал бы функцию DMA (Direct Memory Access) . По программам в этой публикации вы можете сказать, что они не были написаны программистом на языке C. Но они компактны и выполняют свою работу. В некоторых местах я осознавал, что большего можно достичь другими средствами. Но исходные тексты стали намного длиннее и труднее для понимания.
Большинство проектов в этой публикации относятся к области измерительной техники. Это опять-таки связано с моей точкой зрения как инженера-электронщика. Когда я просматриваю технические характеристики микроконтроллера , первое, что я вижу, — это возможные применения в измерительной технике. Pico может измерять частоты до 100 МГц - надо попробовать! Если я захочу решить эту задачу с помощью цифровых микросхем, это потребует огромных усилий.
С Pico это очень просто и недорого. Если вас меньше интересует техника измерений, у вас могут быть совершенно другие задачи, но со схожими проблемами. Так что, возможно, вы сможете использовать представленные программы как карьер, брать на себя мелкие детали и решать с их помощью совершенно разные свои задачи.
2 Управление светодиодом
Первый тест уже показал, как можно управлять светодиодом на плате, но теперь должен мигать другой светодиод. Для этого к P0 (вывод 1) подключается светодиод с последовательно подключенным резистором сопротивлением 1 кОм.

//Pico_Blink2
int led = 25;
void setup() {
pinMode(led, OUTPUT);
pinMode(0, OUTPUT);
}
void loop() {
digitalWrite(led,HIGH);
digitalWrite(0 , 1);
delay(500);
digitalWrite(led, LOW);
digitalWrite(0, 0);
delay(500);
}
С pinMode(0, OUTPUT); вывод P0 становится выходом. В функции цикла он включается с помощью digitalWrite (0, 1); а затем выключился с помощью digitalWrite (0, 0);. Обозначения HIGH и 1, а также LOW и 0 эквивалентны. Таким образом, BoardLED и внешний светодиод теперь управляются в одной фазе. Командные строки выполняются одна за другой, но результирующие задержки составляют менее микросекунды и поэтому остаются невидимыми.
У вас есть совершенно другие возможности с функциями из SDK (С-Software Development Kit). Чтобы использовать их, вам необходимо включить заголовочный файл pico/stdlib.h и, в других случаях, другие заголовочные файлы. Функции теперь имеют немного другие имена. Чтобы использовать порт, вам необходимо инициализировать его с помощью gpio_init и переключить его как выходной с помощью gpio_set_dir. На этот раз используется P2.
Кроме того, можно установить выходной ток порта. С помощью функции gpio_set_drive_strength (2, GPIO_DRIVE_STRENGTH_2MA) выходной ток снижается до такой степени, что можно подключить светодиод без последовательного резистора. Однако спецификацию 2 мА следует интерпретировать с осторожностью. Согласно техпаспорту, при указанном токе все равно гарантировано напряжение 2,62 В. Фактически при такой настройке у зеленого светодиода был измерен ток короткого замыкания 20 мА и рабочий ток 13 мА.

//Pico_Blink3
#include "pico/stdlib.h"
void setup() {
gpio_init(2);
gpio_set_dir(2, 1);
gpio_set_drive_strength(2, GPIO_DRIVE_STRENGTH_2MA);
while (true) {
gpio_put(2, 1);
sleep_ms(500);
gpio_put(2, 0);
sleep ms (500);
}
}
void loop() {}
В техпаспорте RP2040 есть графики ожидаемого тока в зависимости от напряжения на порту. Они подтверждают, что светодиод с настройкой 2 мА можно подключить напрямую.

3 Быстрый выходной порт
До сих пор функция задержки Arduino или функция сна SDK sleep__ms использовались для создания определенных задержек в несколько миллисекунд или секунд. Также имеется sleep__us для задержки на микросекунды. Однако это не обеспечивает точное время выполнения, поскольку оно добавляется к другому, неизвестному времени выполнения.
Лучшим вариантом является использование микросекундного таймера в пико. Это 64-битный счетчик, который считает с циклом 1 мкс. Функция time_us_32() считывает младшие 32 бита, чего обычно достаточно.
Следующая программа ждет следующей микросекунды, чтобы переключить состояние порта.
//Pico_time_us
#include "pico/stdlib.h"
void setup() {
gpio_init(2);
gpio_set_dir(2, true);
uint32_t t = time_us_32 ();
while (true) {
t+=l ;
while (t>time_us_32 () );
gpio_put(2, 1);
t+=l;
while (t>time_us_32 () );
gpio_put(2, 0);
}
}

Программа генерирует прямоугольный сигнал частотой 500 000 кГц на порту P2. Однако если вы внимательно изучите сигнал, вы заметите небольшие задержки в несколько микросекунд после каждой миллисекунды. Вероятно, они связаны с активным интерфейсом USB. Тот факт, что частотомер, тем не менее, измеряет ровно 500 кГц, обусловлен использованием микросекундного таймера. Если импульс пропущен, следующие импульсы следуют быстрее, пока часы снова не станут точными.
Если вы посмотрите на сигнал или его гармоники в спектре коротковолнового приемника, вы увидите, например, сильный сигнал на частоте 3500 кГц, но сопровождаемый на 40 дБ более слабым количеством побочных излучений с интервалом ровно 1 кГц каждое.

Далее ниже будет показано, как эту проблему можно решить за счет аутсорсинга второго ядра процессора. Другая возможность — генерировать сигналы с выходом ШИМ.
4 ШИМ-управление
Обычный язык Arduino включает в себя аналог Write. Это формирует выход ШИМ с разрешением 8 бит. Никакой специальной инициализации не требуется.
//Pico_PWM
unsigned char t = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
t++;
unsigned int al = 120+110*sin(t/128.0*3.1415);
Serial.printin(al);
al = (al*al)/256;
analogWrite (0, al);
unsigned int a2 = 120+110*sin(t/128.0*3.1415-1)
a2 = (a2*a2)/256;
analogWrite (1, a2);
unsigned int a3 = 120+110*sin(t/128.0*3.1415-2)
аЗ = (аЗ*аЗ)/256;
analogWrite (2, аЗ);
unsigned int a4 = 120+110*sin(t/128.0*3.1415-3)
a4 = (a4*a4)/256;
analogWrite (3, a4);
unsigned int a5 = 120+110*sin(t/128.0*3.1415-4)
a5 = (a5*a5)/256;
analogWrite (4, a5);
unsigned int a6 = 120+110*sin(t/128.0*3.1415-5)
аб = (аб*аб)/256;
analogWrite (5, аб);
delay(5);
}
Здесь квазианалоговые выходы ШИМ используются для управления яркостью шести светодиодов. Через ряд должна пройти синусоидальная волна. Поскольку глаз не воспринимает яркость линейно, вычисленные синусоидальные значения возводятся в квадрат, а затем смещаются обратно в диапазон от 0 до 255.

Для шести светодиодов достаточно общего резистора, с помощью которого можно регулировать общую яркость. В зависимости от типа светодиода может оказаться полезным резистор сопротивлением от 100 Ом до 1 кОм.
Кстати, выход ШИМ работает на частоте 1 кГц. К одному из выходов можно подключить пьезопреобразователь и услышать звук. Поскольку длина импульса постоянно меняется, звук также меняется. Короткие импульсы обеспечивают более высокую долю гармоник, в то время как сигнал с коэффициентом заполнения 50 % обеспечивает только нечетные гармоники, которые уменьшаются с частотой.
Здесь снова расширены возможности функций SDK. На этот раз также необходимо включить заголовочный файл hardware/pwm.h. Теперь вы можете устанавливать частоту ШИМ, разрешение и ширину импульса в широких пределах.

Модули ШИМ Pico состоят из 16-разрядных счетчиков прямого преобразования, которые работают на системной частоте или на частоте, деленной на нее. С помощью gpio_set_function вы определяете, какой порт должен стать выходом ШИМ, в данном случае порт РО. pwm_set_wrap определяет, до какого уровня должен работать счетчик, прежде чем он снова начнет работать с нуля. В этом случае счетчик должен работать от 0 до 1249, т.е. отсчитывать 1250 шагов. Поскольку пико работает на частоте 125 МГц, частота ШИМ составляет 100 кГц. pwm_set_gpio_level устанавливает ширину импульса, в данном случае 250 шагов счета, т.е. 20 % от общей ширины. Таким образом, порт включен на 2 мкс и выключен на 8 мкс. С помощью pwm_set_enabled вы включаете или выключаете выход ШИМ.
//Pico_PWM2
#include "pico/stdlib.h"
#include "hardware/pwm.h"
void setup() {
gpio_set_function(0, GPIO_FUNC_PWM);
pwm_set_wrap(0, 1249);
pwm_set_gpio_level (0 , 250);
pwm_set_enabled(0, true);
}
void loop() {}
Выход ШИМ очень универсален благодаря функциям SDK. Вы можете выбрать генерацию определенной частоты или задать определенное разрешение, например 8-битное, 10-битное или 16-битное. Это дает вам очень гибкий генератор прямоугольных импульсов, работающий на частотах до нескольких МГц. Наименьшая частота без использования прескалера составляет 125 МГц/65 536 = 1907,35 Гц.
Весь программный код находится в функции setup(). Кроме того, необходимо использовать пустую функцию 1оор(). В качестве альтернативы можно также использовать функцию int main(). Но тогда никакого СОМ не образуется и при сле-
дующей программе автоматический вызов загрузчика уже не работает, поэтому придется запускать его с ресетом и загрузочным ключом.
5 Цифровые входы
Каждый порт RPi Pico можно использовать как цифровой выход или как цифровой вход. Запрос с помощью digitalRead затем возвращает либо 1, либо 0, в зависимости от того, присутствует ли высокое напряжение (3,3 В) или низкое напряже-
ние (0 В).
Особенностью RPi Pico являются его внутренние понижающие резисторы, которые активируются на каждом порту после сброса. Таким образом, в отличие от других контроллеров, у вас нет входов с высоким сопротивлением, которые могут принимать случайные состояния, но вы надежно считываете ноль (низкий уровень) на всех неиспользуемых входах. Соответственно, коммутатор должен быть подключен к 3V3. В первом примере порт Р15 опрашивается на контакте 20. При нажатии переключатель поднимает порт до 3,3 В.

//Pico_Din
void setup() {
pinMode(25, OUTPUT);
}
void loop() {
int i = digitalRead (15);
digitalWrite(25, i);
}
Программа предназначена для включения светодиода платы на GP1025 при нажатии кнопки. Поэтому порт 25 инициализируется как выход. Вход не обязательно должен быть инициализирован, поскольку каждый порт после сброса переключается как вход. В функции цикла порт 15 запрашивается снова и снова. Результат (1 или 0) попадает в i. Затем i выводится на порт 25 и, таким образом, светодиод на плате включается при нажатии переключателя.
Часто лучше размещать внешние кнопки напротив земли. Тогда порт должен быть снабжен подтягивающим резистором, который подтягивает его в состоянии ожидания. При инициализации Р15 с помощью pinMode(15, INPUT_PULLUP), он выключается . Это приводит к состоянию ожидания порта 1. Теперь кнопка должен быть замкнута на GND, чтобы переключить состояние на 0. Возможна также инициализация полностью без подтягивающего резистора.
//Pico_Din2 Pullup
void setup() {
pinMode(25, OUTPUT);
pinMode(15, INPUTPULLUP);
}
void loop() {
int i = digitalRead (15);
digitalWrite(25, i) ;
}

Таким образом, функция кнопки меняется на противоположную. В режиме ожидания на плате светится светодиод. При нажатии кнопки он гаснет. Однако при необходимости результат запроса можно инвертировать:
int i = !digitalRead(15);
Если вам нужен вход с высоким импедансом, уберите ограничение напряжения. Тогда инициализация называется pinMode(15, INPUT). Активное включение подтягивающего резистора в данной среде невозможно, для этого нужны расширенные функции SDK.

//Pico_Din3 Pulls
#include "pico/stdlib.h"
void setup() {
gpio_init(0) ;
gpio_se t_dir (0 , 1) ;
gpio_init(4) ;
gpio_se t_dir (4 , 0) ;
gpio_pull_up(4);
//gpio_pull_down (4) ;
//gpio_set_pulls(4 r0,0) ;
while (true) {
gpio_put (0 , gpio_get (4) ) ;
}
}
void loop() {}
Здесь P4 запрашивается с помощью внутреннего подтягивания, и РО переключается соответствующим образом. В исходном коде показаны закомментированные строки с дополнительными функциями для подтягивающих резисторов.
Когда одновременно включены как подтягивание, так и ограничение напряжения, вход имеет совершенно особое поведение: gpio_set_pulls (4,1,1). Фактически, одновременно активен только один из двух, но тот, который удерживает достигнутое цифровое состояние, включен. Тогда вход ведет себя как RS-триггер. Его можно поднять или опустить короткими контактными действиями, после чего порт останется в соответствующем состоянии.

Здесь используются две кнопки. Правая подтягивает порт к GND, другой — до 3,3 В. Для этого включается порт P2. С одной стороны, это имеет то преимущество, что соединение к положительному полюсу короче. А с другой стороны, это
повышает безопасность при коротком замыкании. Ведь если обе кнопки случайно нажаты одновременно, порт Р2 ограничивает ток прибл. 30 мА.
//Pico_Din4 Pullup+Pulldown
#include "pico/stdlib.h"
void setup() {
gpio_init(0);
gpio_se t_dir (0 , 1);
gpio_init(2);
gpio_set_dir (2, 1);
gpio_put(2,l);
gpio_init(4) ; gpio_set_dir (4 , 0);
gpio_set_pulls(4,1,1);
while (true) {
gpio_put(0,gpio_get(4));
}
}
void loop() {}
Фактически, Pico теперь ведет себя как триггер RS. Короткого нажатия на одну из двух кнопок достаточно, чтобы привести в нужное состояние. Это поведение не видно программе, поскольку это только поведение входа Р4, при котором оба притягивающих резистора были активированы с помощью gpio_set_pulls(4,1,1).
Просто для сравнения вы можете соединить два порта вместе, один из которых будет получать активное подтягивание, а другой — ограничение. Фактически, то-гда у вас есть делитель напряжения с примерно половиной рабочего напряжения
на обоих портах.
Вы можете измерить включенный подтягивающий или понижающий резистор с помощью омметра и найти сопротивление около 20 кОм относительно GND или 3V3. Однако в паспорте указано, что она должна составлять от 50 до 80 тысяч. Если вы измерите ток относительно +3,3 В, вы обнаружитезначение около 58 мкА, что указывает на понижение сопротивления 57 кОм. Таким образом, понижение напряжения не является постоянным, а увеличивается с увеличением напряжения. Ха-
рактеристическая кривая, кажется, больше соответствует полевому транзистору, который все больше и больше приближается к источнику постоянного тока с более высоким напряжением.
6 Измерение напряжения
RPi Pico имеет три аналоговых входа от ADC0 до ADC2 и два других, которые недоступны снаружи. По линии REF подается опорное напряжение, которое подключается к 3,3 В через RC-фильтр нижних частот. Таким образом, диапазон измере-
ния АЦП составляет от О В до 3,3 В.
На этот раз контакт 33, AGND (аналоговое заземление) используется в качестве соединения GND, чтобы свести к минимуму помехи при измерениях регулятором напряжения на плате. В первом тесте измеряется рабочее напряжение 3,3 В. Резистор сопротивлением 1 кОм встроен в измерительный вход в качестве меры предосторожности и для предотвращения повреждения в случае, если кто-то случайно подаст более высокое или отрицательное напряжение.

//Pico_voltage ADO
unsigned int ad, u;
void setup() {
Serial.begin(115200)
}
void loop () {
ad =analogRead(A0);
u = (unsigned int) ad*3300/1023;
Serial, print(ad);
Serial.print(" ");
Serial.print(u);
Serial.printing mV");
delay(500);
}
Программа считывает напряжение на АО с помощью AnalogRead(АО) и преобразует его в 10-битное числовое значение, т.е. в диапазон от 0 до 1023. Затем оно преобразуется в напряжение в диапазоне от 0 мВ до 3300 мВ. Поскольку результаты вычислений представлены десятичными знаками, результат преобразуется в целое число, т. е. округляется в меньшую сторону. На выходе отображается цифровое измеренное значение и напряжение в мВ.

Измерение на ADC__VREF показало цифровое значение 1019 и напряжение 3287 мВ, при этом небольшие отклонения являются нормальными. Непосредственно на 3V3 измеряется максимальное значение в диапазоне измерения 1023 или 3300 мВ. На GND можно было бы ожидать ноль, но цифровое значение около 2 и измеренное напряжение около 9 мВ. Таким образом, на обоих концах диапазона измерения имеются небольшие ошибки смещения. Наивысшая точность достигается при средних напряжениях.
С функциями SDK программирование АЦП выглядит несколько иначе. Сначала его необходимо инициализировать с помощью adc_init. adc_gpio_init переключает соответствующий вывод на высокий импеданс. Кроме того, канал АЦП должен быть выбран с помощью adc_select_input. Здесь был выбран ADC0 на P26. Фактическое измерение использует запрос adc_read() и возвращает 12-битное значение от 0 до 4095.
В этом примере также было включено подтягивание входного контакта Р26 для измерения прямого напряжения на различных диодах. Подтягивающее напряжение обеспечивает низкий ток около 50 мкА без необходимости использования дополнительного резистора.
Для обеспечения стабильного отображения десять измеренных значений усредняются. Для этого формируется IIR-фильтр (бесконечная импульсная характеристика) . Последнее измеренное значение влияет на результат измерения только на 10
%. При несколько колеблющихся результатах АЦП это позволяет добиться значительного увеличения разрешения.
Аналогичную функцию измерения можно найти в некоторых цифровых мультиметрах, которые также отображают прямое напряжение диодов в диапазоне измерения сопротивления. Таким образом, можно распознать тип диода и, например, отличить диоды Шоттки от обычных кремниевых диодов.

//Pico_AD2 diode test
#include "pico/stdlib.h"
#include "hardware/adc.h"
void setup() {
int iir=0;
Serial.begin(115200);
adc_init();
adc_gpio_init (26);
gpio_pull_up(26);
adc_select_input (0);
uint32_t t = time_us_32 ();
while (true) {
uint32_t ad = adc_read()*3300/4095;
for (int n=0; n<10; n++) {
ad = adc_read 0*3300/4095;
iir = (iir*9+ad)/10;
}
Serial.println(iir);
sleep_ms(500);
}
}
void loop() {
}
Светодиоды невозможно проверить с помощью цифровых приборов, поскольку их прямое напряжение (светодиодов) слишком велико. Однако с Pico это работает, поскольку напряжение может достигать 3,3 В. При подключении желтого светодиода было измерено напряжение 1770 мВ. При этом видно очень слабое свечение. Для сравнения: диод 1N4148 показал всего 490 мВ. Поразительно низкое напряжение обусловлено большим сопротивлением подтяжки. При сопротивлении 1 кОм против VCC напряжение выросло до 670 мВ.
Помимо диодов можно исследовать и транзисторы. На неизвестном транзисторе это можно использовать для идентификации PN-переходов. В случае NPN-транзистора ВС547В на переходе БЭ было измерено напряжение 620 мВ, а на переходе БК — 618 мВ. Однако в основном прямое напряжение зависит от температуры и уменьшается со скоростью 2 мВ/к. Просто прикоснувшись рукой, напряжение падает прибл. 10 мВ.

Если коллектор также подключен к базе, напряжение падает прибл. 570 мВ. Транзистор имеет 300-кратное усиление тока. Следовательно, через базу протекает только в 300 раз меньший ток, что приводит к соответственно меньшему
прямому напряжению. Инвертированный транзистор с коллектором на отрицательном полюсе тоже работает, но с гораздо меньшим усилением тока. Тем не менее, напряжение ок. 560 мВ было измерено даже в инвертированном режиме с соединенными базой и эмиттером. В аналогичной схеме можно исследовать и полевой транзистор. При подключенных затворе и стоке BS170 показал напряжение 1770 мВ. Это дает вам представление о напряжении, при котором полевой транзистор начинает проводить ток, и о том, как им нужно управлять.
8 Входные пороги и гистерезис
Какое входное напряжение цифрового порта читается как 1, а какое как 0? Чтобы рассмотреть это более подробно, напряжение теперь измеряется одновременно с помощью аналогового входа АО. Электролитический конденсатор емкостью 100 мкФ обеспечивает медленное изменение. Он подключается через выход Р21 и 100 кОм либо к 3V3, либо к GND.

//Pico_Din5 Hyteresis
void setup() {
pinMode(22, INPUT);
pinMode(21, OUTPUT);
Serial.begin(115200)
}
void loop () {
int u = analogRead(AO)*3300/1023;
if (u<800)
digitalWrite(21,1);
if (u>2500)
digitalWrite(21,0);
Serial.print(digitalRead(22)*3300);
Serial.print(" ");
Serial.print(u);
Serial.println(" mV");
delay(500);
}
Состояние на Din на этот раз выводится как напряжение 0 мВ или 3300 мВ и, таким образом, имеет тот же диапазон, что и измерение напряжения. Это позволяет отображать реакцию входа на цифровом плоттере.

При измерении зарядный резистор всегда подключался к земле, когда электролитический конденсатор заряжался до напряжения 2,5 В, и наоборот к 3V3, когда он разряжался до 0,8 В. Измерение напряжения показывает типичные экспоненциальные кривые зарядки конденсатора. Цифровой вход реагирует на небольшое смещение и включается прибл. 1,5 В, но выключается только ниже приблиз. 1,2 В. Расстояние между двумя точками переключения представляет собой гистерезис. В этом диапазоне всегда сохраняется последнее считанное состояние.
Гистерезис цифрового входа полезен для постоянного считывания уникальных состояний. Это означает, что напряжение на цифровом входе не может быть настолько близко к порогу, чтобы состояние иногда считывал ось как 1, а иногда
как 0. Если вход управляется синусоидальным напряжением, гистерезис превращает его в уникальный прямоугольный сигнал.
У RP2040 есть возможность отключения гистерезиса, но для этого требуется функция SDK. С помощью функции gpio_set_input_hysteresis_enabled(22,0) гистерезис на входе Р22 отключается. Измерение ясно показывает, что точки переключения теперь находятся на одном уровне.

//Pico_Din6 Hyteresis off
#include "pico/stdlib.h"
void setup() {
pinMode(22 , INPUT);
gpio_set_input_hysteresis_enabled(22,0);
pinMode(21, OUTPUT);
Serial.begin(115200);
}
void loop() {
int u = analogRead(AO)*3300/1023;
if (u<800)
digitalWrite(21,l);
if (u>2500)
digitalWrite(21,0);
Serial.print(digitalRead(22)*3300);
Serial.print(" ");
Serial.print(u);
Serial.printing (" mV");
delay(500);
}
Для некоторых задач полезно более точно знать точки гистерезиса. Поэтому теперь необходимо выполнить автоматическое измерение, которое выводит только точки переключения, но не всю кривую напряжения. Порт 21 управляет процессом зарядки и разрядки электролитического конденсатора в качестве выхода. Напряжения измеряются и выводятся в обеих точках переключения.

//Pico_Din7 Hysteresis points
unsigned int u;
void setup() {
Serial.begin(115200);
pinMode(22, INPUT);
pinMode(21, OUTPUT);
}
void loop () {
digitalWrite(21,l);
while (!digitalRead(22)){
u = (int) analogRead(AO)*3300/1023;
}
Serial.print(u);
Serial.print(" mV");
digitalWrite(21,0);
while (digitalRead(22)){
u = (int) analogRead(AO)*3300/1023;
}
Serial.print(u);
Serial.printing (" mV");
}
1587 mV 1177 mV
1590 mV 1180 mV
1590 mV 1180 mV
1587 mV 1180 mV
1587 mV 1177 mV
1590 mV 1180 mV
1583 mV 1180 mV
1590 mV 1180 mV
1593 mV 1180 mV
1593 mV 1183 mV
Слегка округленный результат: верхняя точка переключения составляет 1,59 В, а нижняя 1,18 В. Таким образом, существует гистерезис 0,41 В.
9 Измерение температуры
Всего RP2040 имеет пять аналоговых входов, три из которых доступны снаружи на плате PICO PI. Четвертый вход используется для измерения напряжения на плате. А пятый подключен к внутреннему датчику температуры в контроллере. Расширение платы pico поддерживает измерение температуры с помощью функции
AnalogReadTemp().
Цель здесь — выяснить, насколько сильно нагревается контроллер, когда он подвергается более тяжелым нагрузкам на порты. Три выхода переключаются на высокий уровень и управляют тремя желтыми светодиодами без последовательного резистора. Поскольку заданный ток составляет 4 мА, через каждый светодиод протекает около 20 мА. Переключатель на линии GND может включать и выключать всю нагрузку.

//Pico_ADtemp
#include "pico/stdlib.h"
#include "hardware/adc.h"
void setup() {
Serial.begin(115200)
pinMode(0, 1);
pinMode(1, 1);
pinMode(2, 1);
digitalWrite(0, 1);
digitalWrite(1, 1);
digitalWrite(2, 1);
}
void loop() {
Serial. println(analogReadTemp());
delay(1000);
}

Измерение показывает разогрев прибл. 10 градусов. Однако можно увидеть скачки на 6 градусов при включении и выключении нагрузки, а затем типичный экспоненциальный диапазон нагрева или охлаждения. Таким образом, предполагается, что большие токи в портах приводят к фальсификации измерений температуры. Однако в любом случае общая нагрузка 60 мА не может привести к тепловой перегрузке контроллера.
Как уже было показано на примере диодного тестера, кремниевый диод также является хорошим датчиком температуры. Схема остается прежней. К аналоговому входу A0 подключается диод 1N4148, и включается внутренний подтягивающий резистор. При комнатной температуре измеряется прямое напряжение в диапазоне 500 мВ. Ток диода ок. 50 мкА достаточно мал, чтобы избежать электрического нагрева. Теперь температуру диодного датчика можно рассчитать по точному напряжению.
Программа отображает измеренное напряжение диода, расчетную температуру диода и внутреннюю измеренную температуру микроконтроллера. Если требования к точности не слишком высоки, температуру контроллера можно использовать в качестве сравнения для оптимизации преобразования. При 23 градусах получилось напряжение 476 мВ. Наклон составляет 0,5 мВ/градус. Таким образом, очень высокая точность не достигается. Но преимущество диода в том, что с его помощью можно измерять температуру до 150 градусов. Пример измерения показывает повышение до 89 градусов.

//Pico_ADtemp2 Si diode
#include "pico/stdlib.h"
#include "hardware/adc.h"
void setup() {
int iir=0;
int ad, temp;
Serial.begin(115200);
adc_init();
adc_gpio_init (26);
gpio_pull_up(26);
adc_gpio_init (26);
gpio_pull_up(26);
adc select input(0);
while(true){
adc_select_input (0);
for (int n=0; n<10; n++){
ad = adc_read 0*3300/4095;
iir = (iir*9+ad)/10;
}
temp = 23+(476-iir)/2;
Serial.print (iir);
Serial.print (" mV");
Serial.print (temp);
Serial.print (" °C ");
Serial.print (analogReadTemp());
Serial.printin("° С");
sleep_ms(5000);
}
}
void loop() {}
(ПРОДОЛЖЕНИЕ СЛЕДУЕТ)
Источник : «Домашняя лаборатория» №1 (январь) 2024
Комментарии (0)
Добавить
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.

