Содержание
- Назначение и принцип работы
- Разновидности и сравнение
- Подключение к Ардуино
- Примеры использования
- Выводы
- FAQ
Назначение и принцип работы
Всем известны и любимы пины Ардуино с приставкой “А”, А0, А1 и так далее. Это своего рода вольтметры, которые информируют нас об уровне напряжения на соответствующем пине в цифровом виде. Другими словами, преобразуют аналоговый сигнал в цифровой, они так и называются - “аналого-цифровые преобразователи”, сокращенно АЦП, по английски ADC, вещь очень полезная в хозяйстве и востребованная в проектах весьма часто.
Возникает вопрос, а можно ли сделать наоборот? Чтобы цифровой сигнал преобразовывался в аналоговый? К сожалению, Ардуино так не умеет. На неискушенный взгляд может показаться, что и не надо, есть же хорошая имитация, называется ШИМ, широтно-импульсная модуляция. Задавая ее скважность, мы можем заставить светодиод гореть в половину накала или вообще с любой яркостью. Можем, но гореть он будет все равно на полную яркость, только иногда не гореть совсем, так сказать, быстро мерцать. Не всегда и не для всех задач такая иллюзия способна полностью заменить реально заданное напряжение, например, не годится для плавного управления некоторыми типами коллекторных двигателей. Не всякому глазу приятна и полезна ШИМ подсветка, особенно при малой яркости и частоте. Отдельная задача, недостижимая для модуляции - вывод динамически изменяемой формы сигнала, отличной от прямоугольника. Никак не получится увидеть на цифровых пинах пилу, треугольник и синусоиду, а значит отпадает часть возможностей.
Но такие устройства существуют отдельно, даже называется очень похоже, только наоборот: “цифро-аналоговые преобразователи”, сокращенно ЦАП, по-английски DAC, и их великое множество. Поговорим об относительно простых однокомпонентных решениях в виде специализированных микросхем.
Разновидности и сравнение
Все ЦАПы делятся на два типа по интерфейсу: с параллельным или с последовательным, и группируются по разрядности, чаще всего 8, 10 и 12 разрядов. От интерфейса зависит способ подключения, а разрядность влияет на размер “шага”, которым можно задавать напряжение. Чем больше шагов, тем они мельче, а значит, выше точность.
“Параллельный” ЦАП это, по сути, регулируемый резистивный делитель. Подключая или отключая отдельные ветки, меняем суммарное сопротивление на плечах, тем самым получая заданное напряжение на выходе. Простейшая схема четырехразрядного ЦАПа выглядит так:
К каждому разряду подключается свой пин контроллера и операционный усилитель на выход, чтобы сопротивление нагрузки не влияло на результат. Комбинируя сочетания включения-выключения пинов, добиваемся изменения выходного напряжения. Условным преимуществом можно назвать быстродействие, никаких вычислений в такого рода ЦАПах не производится, все процессы происходят на физическом уровне. Но недостатков больше. Во-первых, требуется достаточно много свободных ножек контроллера, например, недорогой и распространенный параллельный ЦАП КР572ПА - десятиразрядный, то есть ему нужно 10 пинов.
Во-вторых, каждый пин влияет на выходное напряжение по-своему, один больше, другой меньше, и эта зависимость нелинейна.
В-третьих, проистекающая из второй причины необходимость программного вычисления комбинаций пинов для вывода точного напряжения. Обычные двоичные числа в качестве комбинаций тут не работают. Например, так выглядит осциллограмма при простом переборе десяти разрядов от 0 до 1023 (максимальное значение) в стандартном двоичном исчислении:
Вместо ровной растущей линии наблюдаем хаотичное ступенчатое изменение напряжения. Чтобы увидеть линию, необходим особый алгоритм, его написание ложится на программиста, а вычисления ложатся на контроллер, что заметно замедлит и работу, и разработку.
В-четвертых, если разрядность более восьми, пины переключаются группами не одновременно, небольшая задержка будет даже при прямом обращении к портам, что приведет к непредсказуемым скачкам между шагами. Такие скачки тоже видно на осциллограмме выше. Если потребуется получить гладкий, быстро меняющийся сигнал, эти всплески будут проблемой.
В-пятых, сложность подключения. Кроме разрядов и выхода, необходимо подключить несколько настроечных резисторов и конденсаторов, калибрующих точность, и, самое главное, несколько различных напряжений, логическое, опорное и зачастую отрицательное опорное, то есть от двух до трех различных. Вот вырезка из даташита на ЦАП 1108ПА1А:
Обратите особое внимание на ножки 1 и 2.
ЦАПы с параллельным интерфейсом устройства важные и нужные, но они пришли к нам в наследство от аналоговой техники, когда микроконтроллеры были большой редкостью. При некотором трудолюбии, упорстве и большом количестве свободного времени их можно приспособить к своему проекту, если нет жестких требований к точности, скорости и помехам, но для облегчения жизни лучше использовать более современные ЦАПы - с последовательным интерфейсом.
“Последовательные” ЦАПы представляют собой составное устройство с собственным микроконтроллером и делителем напряжения. По какой схеме и алгоритму происходит работа внутри этого комбайна, пользователю вникать не обязательно, важно лишь знать способ передачи в него информации. Чаще всего используется протокол SPI, он простой, быстрый и достаточно помехоустойчивый. В качестве данных в ЦАП необходимо только передать необходимое количество бит, в соответствии с количеством разряда.
Последовательных ЦАПов в природе тоже очень много, но мы рассмотрим на их примере одного чипа - MCP4921.
Маленький, простой в подключении и программировании, точный, быстрый и надежный, рекомендуется для большинства DIY-проектов. Он 12-разрядный, то есть расстояние от минимального до максимального значения напряжения у него разделено на 4096 шагов. Максимальное напряжение (без усиления) на выходе составляет 5 В, а значит один шаг, в теории, соответствует всего лишь 0,0012 В, и, в отличие от параллельных ЦАПов, все шаги одинаковы. Вычислить нужное значение для установки точного напряжения не составит абсолютно никакого труда, умножаем требуемое на 4096/5, то есть 819, и готово. Хотите 3.8 В, отправьте на чип число 2703. Далее узнаем, как это сделать на практике.
Подключение к Arduino
Для долгой и счастливой работы даташит настойчиво рекомендует нам не лениться и подключаться правильно, тем более, что это не так уж и сложно.
Но нам лень собирать даже такое, и для тестирования мы используем схему в стиле “минимал”. Даже операционный усилитель пока добавлять не будем:
Для максимально быстрой и надежной отправки данных используем аппаратный SPI, поэтому подключаем к чипу ножку исходящих сигналов MOSI (11), ножку синхроимпульсов SCK (13) и практически любую в качестве ключа. Мы возьмем 9. К выходу OUT подключим осциллограф, если его нет, то вольтметр или светодиод, чтобы наблюдать за работой ЦАПа.
Примеры использования
Попробуем вывести “треугольник” с максимальной амплитудой и точностью, то есть двигаясь по одному шагу за цикл. Для этого зальем в Ардуино такую программу:
#include <SPI.h> unsigned int maxV = 4090; // максимальное отклонение в одну сторону unsigned int minV = 1; // минимальное значение отклонения (не менее делителя) byte defV = 1; // делитель unsigned int delV = 0; // задержка в волне мкс void setup() { pinMode(9,OUTPUT); SPI.begin(); noDel(); } void loop() {} void noDel() { cli(); while (1) { for (unsigned int analogValue = minV; analogValue < maxV; analogValue += defV) { mcpWrite1(analogValue); } for (unsigned int analogValue = maxV; analogValue > minV; analogValue -= defV) { mcpWrite1(analogValue); } } } inline void mcpWrite1(unsigned int value) { byte data; PORTB = ~(PINB & (1 << 1)); data = highByte(value); data = B00001111 & data; data = B00110000 | data; SPI.transfer (data); data = lowByte(value); SPI.transfer (data); PORTB = PINB | (1 << 1); }
Включаем осциллограф и наблюдаем такую картину.
Практически идеальный результат. Максимальная частота почти 20 Гц, то есть за секунду напряжение способно принять более 80 тысяч разных значений. Этого вполне достаточно для формирования звука, воспроизведения музыки и прочих достаточно быстрых процессов. Впрочем, этот результат можно ускорить кратно, если перескакивать сразу через несколько шагов, например, через четыре.
Как видим, треугольник все такой же ровный, но частота увеличилась тоже в 4 раза. Причем, учитывая неидеальность нашего мира и данного ЦАП в частности, в точности мы практически ничего не потеряли, потому что выходное напряжение слегка шумит, порядка 10 мВ. Иными словами, без потери точности можно формировать сигнал с делителем 10, реальная точность данного чипа порядка 10 бит. Немного сгладит ситуацию подключение по полной схеме, но это будет лишь аппаратное усреднение. Вот так выглядит шум в “чистом” виде без подавления, на ЦАП выводим значение 1200.
Вооружившись новыми практическими знаниями, выводим максимально быструю пилу на максимальной амплитуде с минимальными потерями точности. Для этого в шапке программы меняем следующие данные:
unsigned int maxV = 4086; // максимальное отклонение в одну сторону unsigned int minV = 10; // минимальное значение отклонения (не менее делителя) byte defV = 10; // делитель unsigned int delV = 0; // задержка в волне мкс
Смотрим:
Почти 200 Гц, более 300 тысяч разных уровней напряжения в секунду, неплохо.
Завершая эксперименты, давайте посмотрим, как будет по-настоящему, не мерцая, менять яркость светодиод от минимума к максимуму и наоборот. Чтобы глаз успел заметить данный процесс, замедлим наш “треугольник”, для чего добавим задержки между сменами уровней.
#include <SPI.h> unsigned int maxV = 4086; // максимальное отклонение в одну сторону unsigned int minV = 10; // минимальное значение отклонения (не менее делителя) byte defV = 10; // делитель unsigned int delV = 2000; // задержка в волне мкс void setup() { pinMode(9,OUTPUT); SPI.begin(); Del(); } void Del() { while (1) { for (unsigned int analogValue = maxV; analogValue > minV; analogValue -= defV) { mcpWrite1(analogValue); delayMicroseconds(delV); } for (unsigned int analogValue = minV; analogValue < maxV; analogValue += defV) { mcpWrite1(analogValue); delayMicroseconds(delV); } } } inline void mcpWrite1(unsigned int value) { byte data; PORTB = ~(PINB & (1 << 1)); data = highByte(value); data = B00001111 & data; data = B00110000 | data; SPI.transfer (data); data = lowByte(value); SPI.transfer (data); PORTB = PINB | (1 << 1); }
Подключаем к выходу ЦАП светодиод, не забывая резистор, любуемся на честный маячок без ШИМа.
Разумеется, вывод “треугольника” не единственное, на что способен ЦАП, форма сигнала может быть абсолютно любой, вычисленной по формуле или заданной по таблице. Она может меняться в зависимости от ситуации и ограничена лишь задачами и возможностями программиста. В качестве примера и финальной иллюстрации посмотрим на такую осциллограмму:
Выводы
Современные цифро-аналоговые преобразователи - удобные и несложные в применении устройства. Они могут и должны применяться в DIY проектах везде, где это необходимо. Рекомендуются в виде более качественной альтернативы ШИМу в управлении яркостью освещения и скорости работы двигателей.
FAQ
1. Как вывести синусоиду?Мощность контроллера не позволяет производить вычисления достаточно быстро на ходу, поэтому синусоиду, как и любые другие графики сложных функций, лучше выводить, используя заранее рассчитанные таблицы. Зная амплитуду, положения середины, шаги по вертикали и горизонтали, сделать это довольно просто, например, при помощи электронной таблицы.
2. Стоит ли выбирать ЦАП с максимально большой разрядностью?Как показывает практика, смысла использовать ЦАПы с разраядностью выше 10, во всяком случае, для бытового уровня, смысла не имеет. Шумы поглотят эту точность, а времени на вывод информации и формирование сигнала потребуется больше.
3. Для чего и как можно использовать “параллельные” ЦАП, несмотря на их недостатки?Для выставления нескольких редко меняющихся напряжений без особых требований к точности. Например, в режимах светильника: максимум, полумрак, ночник.
4. Как управлять напряжением в других диапазонах, например от 0 до 24 В?Используя операционные усилители, можно добиваться любого масштабирования и сдвига сигнала. Например, сканирующие зеркала используют сигналы с симметричными относительно нуля напряжениями, от -ХХ, до +ХХ. При помощи несложной схемы “треугольник” 0-5 В примет правильную форму, размер и полярность.
5. Как при помощи ЦАП воспроизводить звук?Проще всего это делать из WAV файлов, так как звук в них закодирован в несжатом виде. Размеры таких данных не позволяют много поместить в память Ардуино, поэтому, как правило, ЦАП используют в паре с SD-ридером. В интернете есть примеры реализации данного проекта разной степени успешности.