Меню Рубрики

Установка r2r что это

Arduino.ru

Обаяние замечательной схемы R2R

Заметка посвящена тому, как повесить до семи кнопок (переключателей) на один аналоговый пин используя простую и элегантную схему R2R. Рассматривается в основном теория и как оно должно работать. Есть продолжение этой заметки — о граблях, которые разбросаны на пути практической реализации этой идеи. Те читатели, которые и без меня знают что такое R2R и как она работает, могут сразу переходить ко второй заметке.

Подключить несколько (от двух до семи) кнопок (переключателей) на один единственный аналоговый пин.

R2R схема – это необычайно красивое и элегантное решение для построения ЦАП, описанное в огромном количестве литературы, включая и собственно «библию» (стр. 642). Идея состоит том, чтобы комбинацию кнопок преобразовать в аналоговый сигнал, а затем оцифровать этот сигнал, прочитав с аналогового входа контроллера. Получаем комбинацию кнопок в цифровом виде.

Отметим сразу, R2R — это не конкретная схема, а скорее идея. Чтобы понять её, рассмотрим сначала простейшую схему с одной кнопкой:

Если переключатель SA1 замкнут на землю, то на пине имеем, очевидно, потенциал земли. Если же переключатель SA1 замкнут на питание, то на пин попадает напряжения с делителя, у которого верхнее плечо – 20К (резистор R1), и нижнее – тоже 20К (последовательно резисторы R2 и R3). Т.е. не пине имеем половину напряжения питания.

Добавим в схему ещё один блок полностью идентичный тому, заключён в синий прямоугольник.

Посмотрим, что у на здесь с напряжениями:

Напряжение на пине

Земля Земля Очевидно – потенциал земли, т.к. Питание от схемы отключено полностью Земля Питание Перерисуем схему, убрав переключатели и немного переставив детали, чтобы было легче считать (справа). Напряжение в точке А определяется делителем в верхнем плече которого 20К (R4), а в нижнем – 12К (параллельно стоят R5+R3 и R1+R2), т.е. напряжение – 3/8 от питания. Это напряжение в свою очередь делится делителем R2 (верхнее плечо) и R1 (нижнее), т.е. на пин попадает 2/3 от 3/8 или 1/4 напряжения питания. Питание Земля На пине результат делителя с верхним плечом 20К (R1) и нижним плечом тоже 20К (R2 последовательно с параллельными R4||(R5+R3)), т.е. половина напряжения питания Питание Питание Перерисуем схему, убрав переключатели и немного переставив детали, чтобы было легче считать (справа). Напряжение в точке А определяется делителем с верхним плечом 12К (параллельно стоят R4 и R2+R1) и нижним плечом – 20К (R5+R3) и равно 5/8 напряжения питания. Это напряжение подаётся на нижнее плечо делителя R1-R2 к верхнему плечу которого подано Vcc. Таким образом напряжение на пине будет равно 5/8 напряжения питания плюс 1/3 от (Vcc – 5*Vcc/8) = 6/8 или 3/4 напряжения питания.

Итак, что мы получили? Самая левая кнопка даёт нам 0, если замкнута на землю и половину питания, если замкнута на питание.

Вторая слева кнопка (независимо от первой. ) даёт 0, если замкнута на землю и четверть питания, если замкнута на питание. Причём эта четверть просто прибавляется напряжению, которое получается от первой кнопки! Т.е. по напряжению на пине мы всегда можем однозначно определить, какая кнопка нажата, нажаты обе, или не нажата ни одна!

Более того, если добавить третью (четвёртую и т.д.) кнопки, то получим всё ту же картину:

Первая (самая левая) кнопка по-прежнему даёт 1/2 напряжения питания, вторая – 1/4, третья 1/8, четвёртая 1/16 и т.д.

Вообще, для этой цепочки, сколько бы кнопок мы не нарисовали, всё равно будет верно следующее:

1. Если замкнуть на землю все кнопки, кроме n-ой слева, а n-ую слева замкнуть на питание, то напряжение на пине будет равно напряжению питания, поделённому на 2 n .

2. Если включено одновременно несколько кнопок, напряжения указанные в п.1 для каждой в отдельности, будут просто суммироваться.

Например, если на питание замкнуты первая (слева), третья и четвёртая кнопки то, то напряжение на пине будет равно 1/2 + 1/8 + 1/16 = 11/16 от напряжения питания.

Эти два утверждения несложно доказать, если, вооружившись законом Ома и правилами Кирхгофа, выписать формулу для одной кнопки, а затем, воспользовавшись математической индукцией показать, что если эта формула верна для n кнопок, то верна и для n+1 кнопки. Но это я предпочитаю оставить склонному к математике читателю для самостоятельного упражнения. Уж если авторы «библии» поступили так, то мне – грешному …

Используются резисторы двух номиналов. Сами по себе номиналы не особо важны, важно лишь, чтобы они были как можно более точными (не хуже, чем 1%) и одни были ровно вдвое больше других. А так, можно использовать от 1К / 2К, до 100К / 200К – ничего не изменится.

Следует особо отметить очень важное свойство этой схемы. Как Вы могли заметить, вклад каждой следующей кнопки в общее напряжение ровно в два раза меньше, чем вклад предыдущей! Это очень важно, т.к. позволяет построить предельно простую схему идентификации кнопок. Действительно, если всю группу кнопок представить как двоичное число, то (для десятиразрядного АЦП) получим следующие коды:

(здесь и далее биты расположены по правилу MSBF, т.е. самый младший бит — самый правый)

Т.е. каждой кнопке соответствует свой бит! Таким образом, получив результат функции analogRead, нам достаточно просто проверить бит, соответствующий кнопке, что узнать нажата она или отпущена! Во как здорово!

Вот собственно и всё про замечательную схему R2R. Согласитесь, ведь красиво! Когда я впервые её увидел – просто влюбился и очень жалею, что придумал её не я.

Максимальное количество кнопок

Если мы откроем даташит, то в описании АЦП увидим, что его абсолютная погрешность ±2 LSB. На практике это означает, что полученное от analogRead число имеет право на ±2 отличаться от точного. Значит двум младшим битам доверять нельзя! Поэтому, первая идея – ставить восемь кнопок, а по двум младшим битам определять наличие и знак ошибки. В случае, если ошибка была «в плюс», то ничего не делать, а если «в минус», то прибавить 4. Но это не работает. Смотрим пример. Допустим, у нас восемь кнопок и нажаты все нечётные (а все чётные замкнуты на землю). В идеале analogRead должен вернуть нам число 680 (дв. 1010101000). Посмотрим, как будет выглядеть результат в случае ошибки на +2 LSB и на -2 LSB:

Правильный результат — 680 1010101000
Ошибка: +2 LSB — 682 1010101010
Ошибка: -2 LSB — 678 101010 01 10

Действительно, при положительной ошибке можно ничего не делать, а при отрицательной, прибавление к результату числа 4 спасло бы ситуацию и восстановило бы правильное значение (красные битики восстановились бы). Но. Внезапно. А как мы узнаем какая была ошибка? Положительная или отрицательная? Ээээ … А никак! Младшие то биты в которых сидит ошибка абсолютно идентичны! Т.е. в этой ситуации мы просто не можем узнать в какую сторону была ошибка и, стало быть, не можем узнать нужно ли нам прибавлять 4 к результату или не нужно!

Так что, восемь кнопок – многовато!

А вот семь или меньше кнопок – вполне возможно! Ведь при таком количестве кнопок, у нас справа от значащих битов образуются неиспользуемые биты, которым мы можем доверять! Для семи кнопок такой бит будет один (третий справа), для шести – два (3-й и 4-й справа), для пяти – три и т.д. Более того, эти самые неиспользуемые. Но доверительные биты дадут на индикатор в какую сторону была ошибка!

Если ошибка была в «плюс» (или не было вовсе), то они все будут нулями. Если же ошибка была «в минус», они все будут единицами! В последнем случае, нам просто нужно взять число, образованное используемыми битами (т.е. взять слева количество битов, равное количеству кнопок), прибавить к этому числу единицу и получи правильный результат.

Давайте проверим, допустим, у нас шесть кнопок и, как и раньше, на питание замкнуты все нечётные, а на землю все чётные. В идеале мы должны получить число 672 (дв. 1010100000). Неиспользуемых, но надёжных битов будет два – они обозначены зелёным цветом:

Правильный результат — 672 101010 00 00
Ошибка: +2 LSB — 674 101010 00 10
Ошибка: -2 LSB — 670 1010 01 11 10

Как видите, всё получилось. В случае положительной ошибки, когда зелёные биты равны 0 – не делаем ничего. А в случае отрицательной ошибки, когда зелёные биты равны 1 – просто берём значащую часть результат (левые 6 бит) и прибавляем к ней 1. В результате, красные ошибочные биты исправятся и всё станет на свои места – результату можно доверять.

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

Но, к делу. Мне нужен был четырёхканальный выключатель для дистанционного включения праздничной иллюминации во дворе моего дома. Схема R2R на четыре кнопки выглядит, очевидно, вот так:

Из неё получилась вот такая плата (кнопки расположены зеркально, т.е. самая старшая — справа, а не слева, как на схеме — мне так было удобнее):

А из платы — вот такой модуль:

Архитектура приложения была выбрана такая:

1. Имеем переменную, в которой хранится текущее состояние всех кнопок в виде числа от 0 до 15 (для четырёх это покрывает все возможные сочетания);

2. Имеем переменную candidate – в ней хранится новое состояние кнопок, которое мы уже прочитали, но оно ещё не стало «текущим состоянием» (или равно ему);

3. С периодичностью 10-15 миллисекунд

3.1. читаем напряжение на пине функцией analogRead;

3.2. округляем ошибки АЦП, сдвигаем на 6 бит вправо и получаем число от 0 до 15 (переменная newState);

3.3. Если newState равна переменной candidate, но при этом не равна текущему состоянию кнопок – значит мы получили новое состояние! Трубим во все колокола (флаг изменения, call-back), и запоминаем новое текущее состояние.

Читайте также:  Установка карбюратора от вольво

3.4. Независимо от верности условия в п.3.3, присваиваем cand >

Собственно всё. При таком подходе вновь прочитанное состояние кнопок становится текущим только в том случае, если оно дважды одинаково прочиталось с интервалов в наши 10-15 мс. Это даёт защиту от считывания переходных состояний (когда напряжение начало повышаться/понижаться, но еще не успело дойти до нужного уровня), а также, в известной мере, от дребезга кнопок.

Осталось только пояснить, как была устроена фильтрация ошибок из п. 3.2.

Поскольку мы всегда имеем 6 младших бит, которые по идее должны быть нулями, и именно в них и сидит погрешность измерения, было решено поступать просто. Всего в шести битах может поместиться число от 0 до 63, значит, если там число меньше 32, просто отбрасываем эти биты (округляем вниз), а если больше 31, то к результату, полученному после сдвига вправо, прибавляем единицу (округляем вверх). Это примерно то, что мы описывали выше, только чуть проще. Идея настолько проста, что программа оказалась в разы короче этого описания.

И на самом деле всё это отлично заработало!

Но, потоптавшись немного вокруг работающего модуля, я вдруг ощутимо получил по лбу, от валявшихся вокруг и доселе незамеченных граблей. Работать-то схема работала, хорошо работала, как и задумывалось, но . впрочем. это уже совсем другая история.

источник

Установка r2r что это


Довольно часто встречаю подобные схемки в различных радиолюбительских конструкциях, но далеко не всегда они используются достаточно осмысленно. Попробую объяснить.

Такие ЦАП используются для преобразования цифрового кода разрядности «n» в напряжение от 0 до, практически, напряжения питания, а точнее до (2^n-1)/(2^n)*VCC с шагом VCC/2^n.
Если, например, на такой ЦАП подать линейно возрастающий код, то на выходе (OUT), мы должны увидеть такой сигнал:

Но это все в идеале, в реальной жизни все может выглядеть несколько иначе.
Нюанс первый — используемые в реальной схеме резисторы имеют какую-то конечную точность.

В качестве примера рассмотрим конкретный случай — восьмиразрядный (n=8)
ЦАП на резисторах 1ком/2ком. Для количественной оценки влияния точности
резисторов примем следующее допущение: все резисторы, кроме самого старшего (2R), подключенного к выходу Qn-1(MSB) идеальные, т.е. имеют абсолютно точные
значения своих номиналов. В таком случае, если задаться максимальным отклонением выходного сигнала,скажем, не более половины одного бита (VCC/2^n/2), то отклонение номинала старшего резистора должно быть не более чем 2R/2^n.
В нашем случае — 2ком/256=7.8 ом. Далее, если предположить, что все остальные резисторы не идеальные, а имеют такую-же точность как и самый старщий, то это значение нужно еще разделить на 2. В итоге, для того, чтобы получить максимальное отклонение не более половины одного бита, точность резисторов должна быть не хуже 3.9/2000=0.2% (!)

На практике достичь такой точности довольно сложно. Обычно для решения этой
проблемы используют резисторы одного номинала ,например 1ком (для R) и два
резистора 1ком последовательно (для 2R) или наоборот, 2ком(для 2R) и два
резистора на 2ком паралельно(для R). В данном случае ставка делается не на
абсолютную точность, а на одинаковость номиналов в конкретной партии резисторов. Хорошо-бы эту одинаковость еще и проверить каким-нибудь подходящим приборчиком.

Нюанс второй — выходное сопротивление ключей (Rc), которое в данном случае
получается подключенным последовательно к резисторам 2R — не равно нулю. Кроме того, у разных микросхем, микроконтроллеров, ПЛИС , ТТЛ ИЛИ КМОП-логики его величина разная и может быть довольно большой.
В частности у EPM240 сопротивление канала 20ом. Есть два метода решения этой проблемы.

Первый — минимизировать его влияние, например включить несколько ключей паралельно, тем самым уменьшив его величину, или увеличить значение R, например поставить вместо 1ком/2ком — 10ком/20ком (при этом увеличится выходное сопротивление, оно = R).

Второй — попытаться измерить его величину и учесть ее в схеме,
включив дополнительные резисторы последовательно с R:

Нюанс третий — значение напряжения на выходе ЦАПа напрямую зависит от напряжения VCC. Поэтому, для достижения все той-же точности в половину одного бита, величина всякого рода шумов и помех на VCC не должна превышать VCC/2^n.
Вобщем не стоит экономить на качественном стабилизаторчике и блокировочных конденсаторах.

Если подвести краткий итог вышесказанного, то на резиках с 5% точностью можно
с успехом делать 4х-битные цапики, на 1%ных смело рассчитывать на 6 бит (и в глубине души надеяться на 7), а чтобы сделать хороший 8-битный, придется потрудится.

источник

Электроника для всех

Блог о электронике

Параллельный Цифро Аналоговый Преобразователь по схеме R-2R

Порой надо выдать точный аналоговый сигнал, да еще с быстро менющийся. Например, функцию. Раньше я рассматривал как это можно сделать с помощью ШИМ, но у этого метода есть проблема — он очень медленный. В самом деле, чтобы получить один уровнь на ШИМ, нужно, по меньшей мере, 256 тиков таймера. А если надо развернуть функцию в которой 256 отсчетов? Да еще на каждый отсчет по 256 тиков? Это какая же должна быть частота процессора? Да еще надо учесть, что ШИМ требует интегрирующей цепочки с конденсатором. А значит для четкого установления уровня должно пройти еще несколько импульсов, что снижает скорость еще раза в три. Короче, получить что либо быстрей чем 50 ГЦ на ШИМ очень сложно. Я не говорю даже о том, что у ШИМ изза свойств емкостного заряда сильно плывет линейность, так что это приходится учитывать.

Читайте также:  Установка пожарных извещателей при дымоудалении

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

Опорное напряжение тут последовательно делится на резистивной матрице. Номиналы резисторов должны быть любыми. Главное, чтобы горизонтальные ветви были по номиналу ровно в два раза больше чем вертикальные. А вся резистивная цепь в своей нижней точке садится на землю через резистор равный номиналам в горизонтальных ветвях . Ну и кондерчик для фильтрации дополнительной. Самый старший разряд вверху, самый младший внизу, ближе к земле.

Теоретически, разрядность можно повышать практически до бесконечности. На практике же, уже на десятом разряде возникают проблемы из-за сопротивления ключей, что сказывается на точности и , главное, линейности выходных данных. Но в подавляющем большинстве случаев восьми разрядов хватает за глаза. Тем более их где то еще надо найти, это же целых 8 линий I/O которые надо урвать.

Также не помешает добавить операционный усилитель, включенный повторителем. Чтобы сопротивление нагрузки не вносило искажений. Я поначалу впаял OP07, но получил облом — у меня отрезало все, что ниже 2.5 вольт. Слишком маленькое напряжение питания. Тут нужен усилитель который может работать в режиме Rail-2-Rail то есть выдавать на выходе сигнал с амплитудой от плюса до минуса питания, с минимальным отклонением. При добавлении ОУ, надо учитывать тот факт, что почти у всех операционников максимальное выходное напряжение резко заваливается с ростом частоты — параметр Max Output Swing vs Freq. это показывает. Например, для LM324 выглядит так:

Я усилитель подходящий в запасах не нашел, поэтому пока так. Благо у осциллографа сопротивление высокое и на выходное напряжение он практически не влияет. Чтобы не подбирать номиналы резисторов я поступил проще — в вертикальную линию впаял по два резистора в параллель. При таком включении резистора его сопротивление уполовинивается. Таким образом, все резисторы у меня одного номинала.

Вытравил платку, учел посадочное место под усилитель, а также фильтрующий и блокирующий конденсаторы. Кучу штырей для подключения осциллографов или проводов на другие блоки и завел все это на свою макетку.

Первым делом, выдал синус. Синус у меня чисто табличный. 256 значений, саму таблицу нарыл в инете. Функция получилась гладенькая. Прям заглядение.

Пробовал брать каждое второе значение из таблицы (при этом она ужалась до 128 значений) — тоже все очень красивое. И лишь когда стал брать чуть ли не каждое 16е значение, то тогда стали заметны лесенки на функции:

И то их можно было сгладить фильтром и опять будет красота. Зато на 8ми мегагерцовой Меге удалось добиться 20кГц синусоидального сигнала 🙂

Вот такой код получился, точнее это фрагмент.

Sine: SetTask TS_Sine ; Повторный вызов через API RTOS. Тут не имеет значения LDS Counter,SinCT ; Загрузить из памяти текущее значение указателя Loop: WDR ; Сброс собаки LDPA Sinus ; Макрос, загружающий в Z адрес таблицы с синусом CLR OSRG ; Сбрасываем рабочий регистр ADD ZL,Counter ; Вычисляем смещение по адресу таблицы ADC ZH,OSRG LPM OSRG,Z ; Грузим в рабочий регистр из таблицы байт OUT PORTD,OSRG ; Выдаем его в порт INC Counter ; Увеличиваем счетчик STS SinCT,Counter ; Сохраняем значение счетчика в память RJMP Loop ; Переход RET ; Так как таблица на 256 значений, то проверку счетчика на переполнение делать не надо, он сам, достчитав до 255, ; обнулится. ; А эта та самая таблица Sinus: .DB 64,65,67,68,70,72,73,75 .DB 76,78,79,81,82,84,85,87 .DB 88,90,91,92,94,95,97,98 .DB 99,100,102,103,104,105,107,108 .DB 109,110,111,112,113,114,115,116 .DB 117,118,118,119,120,121,121,122 .DB 123,123,124,124,125,125,126,126 .DB 126,127,127,127,127,127,127,127 .DB 128,127,127,127,127,127,127,127 .DB 126,126,126,125,125,124,124,123 .DB 123,122,121,121,120,119,118,118 .DB 117,116,115,114,113,112,111,110 .DB 109,108,107,105,104,103,102,100 .DB 99,98,97,95,94,92,91,90 .DB 88,87,85,84,82,81,79,78 .DB 76,75,73,72,70,68,67,65 .DB 64,62,61,59,58,56,54,53 .DB 51,50,48,47,45,44,42,41 .DB 39,38,36,35,34,32,31,30 .DB 28,27,26,25,23,22,21,20 .DB 19,18,17,15,14,13,13,12 .DB 11,10,9,8,8,7,6,5 .DB 5,4,4,3,3,2,2,2 .DB 1,1,1,0,0,0,0,0 .DB 0,0,0,0,0,0,1,1 .DB 1,2,2,2,3,3,4,4 .DB 5,5,6,7,8,8,9,10 .DB 11,12,13,13,14,15,17,18 .DB 19,20,21,22,23,25,26,27 .DB 28,30,31,32,34,35,36,38 .DB 39,41,42,44,45,47,48,50 .DB 51,53,54,56,58,59,61,62

З.Ы.
Но синус это не прикольно. В конце концов, его можно и аналоговыми методами получить не сильно напрягаясь. А с ЦАП можно по таблицам задать любую форму. Вот, например,

А это рок концерт. Вид со сцены.

А напоследок, дабы меня не упрекали что тема сисек не раскрыта…

источник

Добавить комментарий

Adblock
detector