ЦАП для Arduino: виды и работа с микросхемой MCP4921

ЦАП для Arduino: виды и работа с микросхемой MCP4921

Чем настоящий аналоговый выход отличается от ШИМ, почему параллельные ЦАП неудобны и как подключить к Arduino 12-разрядный MCP4921 по SPI.

Зачем нужен ЦАП, если есть ШИМ

Аналоговые входы Arduino (A0, A1 и далее) — это аналого-цифровые преобразователи, АЦП: они измеряют напряжение и выдают его в виде числа. Обратной операции — превратить число в напряжение — плата не выполняет. Обычно её имитируют широтно-импульсной модуляцией, но ШИМ остаётся прямоугольным сигналом: светодиод не горит вполнакала, а быстро мерцает на полной яркости. Для ряда задач такая имитация не годится: она не подходит для плавного управления некоторыми типами коллекторных двигателей, ШИМ-подсветка на малой яркости и частоте неприятна для глаз, а получить на цифровом выводе пилу, треугольник или синусоиду невозможно вовсе.

Эти задачи решает цифро-аналоговый преобразователь — ЦАП, или DAC. Проще всего использовать готовую специализированную микросхему.

Параллельные ЦАП и их недостатки

По интерфейсу ЦАП делятся на параллельные и последовательные, по разрядности чаще всего встречаются 8, 10 и 12 бит. Разрядность определяет размер шага, с которым задаётся напряжение: чем больше шагов, тем они мельче и тем выше точность.

Параллельный ЦАП по сути представляет собой управляемый резистивный делитель: подключая и отключая отдельные ветви, меняют суммарное сопротивление плеч и получают нужное напряжение. К каждому разряду подводится свой вывод контроллера, а на выходе ставится операционный усилитель, чтобы нагрузка не искажала результат.

Схема простейшего четырёхразрядного параллельного ЦАП

Достоинство такой схемы — быстродействие: вычислений внутри нет, всё происходит на физическом уровне. Недостатков больше:

  • требуется много выводов контроллера — распространённому десятиразрядному КР572ПА нужно 10 линий;
  • вклад каждого разряда в выходное напряжение различен, и зависимость нелинейна;
  • обычные двоичные числа в качестве комбинаций не работают: при переборе от 0 до 1023 вместо ровной линии получается хаотичная ступенчатая кривая, поэтому комбинации приходится вычислять особым алгоритмом, что замедляет и разработку, и работу контроллера;
  • при разрядности более восьми выводы переключаются группами не одновременно даже при прямой записи в порты, отчего между шагами появляются выбросы;
  • сложная обвязка: настроечные резисторы и конденсаторы, а также два-три разных напряжения — логическое, опорное и зачастую отрицательное опорное.
Параллельный десятиразрядный ЦАП КР572ПА
Осциллограмма при переборе значений от 0 до 1023 на параллельном ЦАП
Фрагмент документации на ЦАП 1108ПА1А с выводами питания

Параллельные преобразователи достались в наследство от аналоговой техники. Их разумно применять там, где нужно выставить несколько редко меняющихся уровней без строгих требований к точности, — например, режимы светильника «максимум», «полумрак», «ночник».

Последовательные ЦАП на примере MCP4921

Последовательный ЦАП — составное устройство с собственной логикой и делителем напряжения. Внутреннее устройство пользователю знать не обязательно, достаточно передать число нужной разрядности. Чаще всего используется протокол SPI — простой, быстрый и достаточно помехоустойчивый.

Микросхема MCP4921 — компактный 12-разрядный преобразователь, который подходит для большинства любительских проектов. Диапазон выходного напряжения разбит на 4096 шагов; при максимуме 5 В (без усиления) один шаг теоретически равен 0,0012 В, причём все шаги одинаковы. Чтобы получить требуемое напряжение, его значение умножают на 4096/5, то есть на 819, и отправляют результат в микросхему.

МикросхемаMCP4921
ИнтерфейсSPI
Разрядность12 бит (4096 шагов)
Максимальное выходное напряжение без усиления5 В
Теоретический шаг0,0012 В
Шум на выходепорядка 10 мВ
Реальная точностьоколо 10 бит

Подключение к Arduino

Документация рекомендует полную схему включения, но для проверки достаточно минимальной, даже без операционного усилителя. Используется аппаратный SPI: к микросхеме подводят линию данных MOSI (вывод 11), линию синхроимпульсов SCK (вывод 13) и линию выбора, для которой подойдёт практически любой вывод — в примере это 9. К выходу OUT подключают осциллограф, а при его отсутствии вольтметр или светодиод.

Что показывает осциллограф

Тестовый скетч подключает библиотеку SPI.h, вызывает SPI.begin() и в бесконечном цикле с отключёнными прерываниями перебирает значения от минимума до максимума и обратно, формируя треугольный сигнал. Каждое значение передаётся двумя байтами через SPI.transfer(): в старшем байте к четырём старшим битам числа добавляются служебные биты (маска B00110000), затем идёт младший байт. Линия выбора на время передачи опускается прямой записью в порт PORTB.

При шаге в единицу и размахе от 1 до 4090 получается практически идеальный треугольник частотой почти 20 Гц. Если перескакивать через четыре шага, форма остаётся такой же ровной, а частота вырастает вчетверо. Точность при этом практически не теряется: выход шумит примерно на 10 мВ, так что реальная точность микросхемы — порядка 10 бит, и шаг 10 можно использовать без потерь. С шагом 10 и диапазоном от 10 до 4086 пила на полной амплитуде достигает почти 200 Гц.

Если добавить между сменами уровней задержку delayMicroseconds() в 2000 мкс и подключить к выходу светодиод с резистором, яркость будет плавно нарастать и убывать без мерцания. Форма сигнала может быть любой — вычисленной по формуле или заданной таблицей.

Практические замечания

  • Синусоиду и другие сложные функции лучше выводить по заранее рассчитанной таблице: считать их на ходу контроллер не успевает.
  • ЦАП с разрядностью выше 10 для бытовых задач смысла не имеет: дополнительную точность поглощают шумы, а на вывод уходит больше времени.
  • Другие диапазоны напряжения, например 0–24 В или симметричные относительно нуля, получают с помощью операционных усилителей, которые масштабируют и сдвигают сигнал.

← Все статьи