Здесь принимаются все самые невообразимые вопросы... Главное - не стесняйтесь. Поверьте, у нас поначалу вопросы были еще глупее :)
Ответить

Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 07:14:20

Допустим у меня есть DIP-выключатель на восемь позиций и я хочу, пользуясь единственным аналоговым входом микроконтроллера, распознавать, в каком положении находятся эти выключатели. То есть я хочу получить некую резисторную сеть-DAC, которая будет мне давать на выходе одно из 256 возможных напряжений в зависимости от одной из 256 возможных комбинаций положений выключателей.

Если бы это были переключатели, которые подключают вход DAC либо к Vcc, либо к GND, то готовое решение известно: R2R-лесенка резисторов как раз и будет таким DAC-ом.

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

А что можно придумать взамен? Добавить к R2R-лесенке pull-down резисторы, которые будут тянуть к GND висящие входы? Если так можно, тот какой номинал таких резисторов будет в таком случае правильным?

Или есть какое-то другое решение?

Добавлено after 1 hour 22 minutes 9 seconds:
Хотя чего тут огород городить: понатыкать последовательно с выключателями удваивающихся резисторов и этого должно быть достаточно. Вопрос разве что в конкретных номиналах, чтобы получить более-менее равномерное деление...

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 08:06:24

удваивающихся резисторов и этого должно быть достаточно. Вопрос разве что в конкретных номиналах, чтобы получить более-менее равномерное деление...
Нужен ещё источник стабильного тока Iref. Такой, чтобы Iref·Rsum было равно апертуре АЦП, где Rsum — сумма всех восьми сопротивлений.

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 11:11:14

у меня есть DIP-выключатель на восемь позиций и я хочу, пользуясь единственным аналоговым входом микроконтроллера, распознавать, в каком положении находятся эти выключатели.
Нужно один раз для каждого значения регистра вывода(хранения) из i=[0, 255] построить функцию U(i), например i=[0, .., 255] => U(i)=[1.55, .., 4.55] записать в память МК и по ней распознавать: U => i => bin(i). Но для точной работы АЦП потребуется ИОН, можно и без него если используется батарея, но тогда функция U(i) должна учитывать разрядку батареи: U(i, Uбат), где Uбат - напряжение батареи. Некоторые МК имеют встроенный ИОН, можно задействовать его, тогда усложнять функцию не придётся, выбрать напряжения внутреннего ИОН меньше напряжения питания, чтобы не зависеть от его снижения.
Вам остаётся найти откуда брать эти аналоговые значения U(i).
Например суммировать в ЦАП, при этом значения U должны быть равномерно распределены по [Umin, Umax] - вывода ОУ, наверное так.
Изображение

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 16:07:31

можно с выключателей собрать рядом 2^n резисторов (1;2;4;8;16...условных единиц сопротивления) в одну точку, точку притянуть к минусу резистором и на выключатели подать питание на х вольт больше чем в узловой точке например через лм317.
так на подключенных резисторах будет всегда одно и то-же напряжение, значит ток через них будет тоже постоянен, в узловой точке ток со всех подключенных резисторов суммируется и утекает в минус через общий резистор, напряжение на нём будет пропорционально току...
вот и всё...

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 16:45:59

Изображение

8 источника тока на общую нагрузку. Внимание на питание - 5,7V для достижение вых. напр. ближе к 5V. Каждый блок по схеме.

Если есть возможность выкопать PSSI2021 - будет легче. Там тоже питание выше.

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 17:10:43

пипец сложность... достаточно всего 1 микросхемы, выключателя и 9 резисторов... (если делать как я предложил) хотя принцип тот-же - сумма токов.
питание нужно только одно - на величину напряжения стабилизации лмки выше максимально нужного выходного напряжения (можно нестабильное)

Добавлено after 1 minute 31 second:
схему смогу только послезавтра нарисовать.

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 17:18:19

Да, 8 транзисторов, и замер напряжение после общего.

Изображение

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 18:34:22

Изображение

Можно и так

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 21:24:56

ну, да можно ещё и так
Изображение
Вложения
2021-03-07_23-23-12.png
(10.51 KiB) Скачиваний: 349

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 22:20:41

А что говорят классики? А классики говорят следующее (Титце-Шенк. Полупроводниковая схемотехника. М. Мир. 1982. с. 444.).

Изображение

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

p0444.png
(87.52 KiB) Скачиваний: 352

Re: Резисторный DAC, но с плавающими входами: как?

Вс мар 07, 2021 23:24:35

El-Eng, здесь требуется двуполярное напр. Иначе все ОК.

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 01:03:14

diplodok писал(а):... здесь требуется двуполярное напр.
Необязательно. Вот пример. При указанных номиналах и питании 5В напряжение на выходе изменяется от 0.5В до 4.5В. ОУ должен быть Rail-To-Rail по выходу и работать от 0.5В синфазного сигнала по входу. Можно взять и обычный, если учесть минимальное и максимальное выходные напряжения и входной диапазон синфазного сигнала.

Изображение

DAC.png
(3.26 KiB) Скачиваний: 307

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 02:47:13

Собственно мне все это нужно для решения второстепенной утилитарной задачи: установки часового пояса на часах. Предыдущая итерация этих часов была реализована на Arduino Nano, где я реализовал выбор пояса программной кнопкой с последующей записью в EEPROM. А сейчас просто из общего интереса решил выдернуть Nano и воткнуть взамен Seeeduino XIAO, перейдя при этом на 3.3В питание. Там нет EEPROM, хотя в качестве заменителя можно использовать FLASH.

Однако мне хотелось реализовать выбор часового пояса именно "низкотехнологическим" методом (если это можно так назвать, учитывая что читать аналоговый вход будет МК), заняв при этом только один вход МК. То есть желательно пассивная и малопотребляющая реализация собственно селектора. Понятно, что для часового пояса достаточно 5-ти битов информации, а про 8 я уж загнул для ровного счета.

Отсюда и идея с микриками и резисторами.

Решил навскидку попробовать вот просто так

Изображение

Моделирование "на коленке" в Экселе показывает более-менее приемлемую кривую на выходе с верхней точкой на 2.19В (при 3.3В питания)

Изображение

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

Попробовал.

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

Погонял туда-сюда, подгоняя прошитые в коде фактические значения сопротивлений и получил работоспособный вариант.

Спойлер
Код:
static int8_t read_time_zone_delta(void)
{
  const uint16_t v_range = 1u << ADC_BITS;
  static const uint16_t r_sw_10[] PROGMEM = { 13710, 6510, 3200, 1480, 815 };
  const uint16_t r_bot_10 = 810;

  uint16_t v = analogRead(TIME_ZONE_PIN);

  uint8_t best_combination = 0;
  uint16_t min_delta = UINT16_MAX;
 
  for (uint8_t combination = 0; combination < (1u << ARRAY_N(r_sw_10)); ++combination)
  {
    uint16_t v_expected = 0;
    if (combination > 0)
    {
      uint32_t conductivity_total_sw = 0;
      for (unsigned sw = 0; sw < ARRAY_N(r_sw_10); ++sw)
        if ((combination & (1u << sw)) != 0)
          conductivity_total_sw += UINT32_MAX / pgm_read_word(&r_sw_10[sw]);
         
      uint16_t r_total_sw_10 = (uint16_t) (UINT32_MAX / conductivity_total_sw);
      v_expected = (uint32_t) v_range * r_bot_10 / (r_total_sw_10 + r_bot_10);
    }

    unsigned delta = v_expected > v ? v_expected - v : v - v_expected;
    if (delta < min_delta)
    {
      best_combination = combination;
      min_delta = delta;
    }
  }

  int8_t abs_delta = best_combination & 0x0F;
  if ((best_combination & 0x10) == 0)
    abs_delta = -abs_delta;

  abs_delta = MAX(abs_delta, TIME_ZONE_DELTA_MIN);
  abs_delta = MIN(abs_delta, TIME_ZONE_DELTA_MAX);
 
  return abs_delta;
}


Полученное 5-битное значение затем интерпретируется как sign-and-magnitude значение (с той тонкостью, что у меня 0 в знаковом бите обозначает отрицательные значения)


Хотя, надо заметить, в правой части графика дребезг уже на грани фола, с немалой вероятностью ошибки на +-1. Однако после подгонки значений сопротивлений в коде все стало работать весьма надежно. Для пущей надежности смену часового пояса делаю тогда, когда 3 раза прочитано одно и то же значение.

Но если понадобилось бы добавить шестой бит, то точности такой реализации уже бы не хватало.
Вложения
Screenshot (42) - Copy.jpg
(168.06 KiB) Скачиваний: 265
Screenshot (41).jpg
(54.04 KiB) Скачиваний: 269

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 04:37:03

Однако мне хотелось реализовать выбор часового пояса именно "низкотехнологическим" методом (если это можно так назвать, учитывая что читать аналоговый вход будет МК), заняв при этом только один вход МК.

Гуглить однокнопочный интерфейс :)

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 05:09:21

Гуглить однокнопочный интерфейс :)


Однокнопочный интерфейс здесь совершенно ни при чем. Как я сказал выше, у меня уже был реализован однокнопочный интерфейс для Arduino Nano.

Задача совсем не в кнопочности интерфейса. Задача в том, чтобы получить энергонезависимо хранимое значение, то есть значение, которое не теряется при выключении/включении питания. В случае Arduino Nano я просто использовал для этой цели тот самый "однокнопочный интерфейс" и сохранение в EEPROM.

Здесь же, на XIAO, я хочу поступить по-другому: я хочу получить внешний "механический байт памяти" - набор из восьми (или хотя бы пяти) микропереключателей. И вопрос лишь в том, как прочитать содержимое такого "механического байта памяти", пользуясь при этом лишь одним входом МК.
Последний раз редактировалось KorbenDallas Пн мар 08, 2021 05:15:02, всего редактировалось 1 раз.

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 05:13:26

Если задача получить всего 1 из 24-х значений, наверное можно извратиться и без АЦП, используя обычный IO пин и внешнюю (переключаемую) RC-цепочку.

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 06:52:02

Если задача получить всего 1 из 24-х значений, наверное можно извратиться и без АЦП, используя обычный IO пин и внешнюю (переключаемую) RC-цепочку.


А кто будет переключать цепочку?

Альтернативных решений, однако, хватает. Я могу прицепить к переключателям сдвиговый регистр c параллельным входом и последовательным выходом. Какой-нибудь 74HC165. Для него, разумеется, понадобятся дополнительные управляющие пины, но я могу извернуться и подцепиться на уже существующие в схеме сигналы аналогичного толка. То есть дополнительный пин понадобится лишь один.

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 06:53:26

А кто будет переключать цепочку?

Ваши дип-переключатели.

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 06:56:45

А кто будет переключать цепочку?

Ваши дип-переключатели.


И? Кап же RC-цепочка решает такую задачу?

Re: Резисторный DAC, но с плавающими входами: как?

Пн мар 08, 2021 07:07:20

Был аппнот от Atmel, не могу его сейчас найти. Но принцип описан здесь.
Изображение
Ответить