В этой статье пошагово соберем схему измерителя расстояния из нескольких микросхем стандартной логики.
Зачем
Все just-for-fun. Конечная схема является тривиальной и не несет новых технических решений. Автор не является профессиональным конструктором электроники и некоторые решения могут не отвечать принятым стандартам.
Больше оправданий
Разработка даже простейшего цифрового устройства без использования микроконтроллера все чаще становится практически нецелесообразным занятием в силу низкой цены микроконтроллеров, их гибкости и богатого набора периферии, упакованного в компактный корпус.
Несмотря на это, автор находит разработку схем на дискретных элементах интересным занятием-пазлом, что-то на уровне лампового звука. В мире где все описывается программным кодом, исполняемым черными ящиками с миллиардами транзисторов, испытываешь неподдельное удивление, когда видишь, как небольшой набор логических вентилей, счетчиков и триггеров образуют устройство имеющее непростое поведение.
Конечно, такое мнение смогут разделить в основном те, для кого работа с дискретной логикой не была обыденностью.
Задача
Хотим получать устройство, представляющее расстояние в сантиметрах в десятичной системе счисления. Минимальное значение – 1 см, максимальное – 254 см. Для отображения используем 7-сегментный индикатор с 3 знакоместами, для измерения расстояния – модуль ультразвукового датчика HC-SR04 или аналог.
Да, я понимаю, что в модуле датчика скорее всего используется микроконтроллер. Это не считается.
Собираем
HC-SR04 – очень популярный, дешевый и неточный ультразвуковой датчик. Кратко о интерфейсе. Датчик имеет две сигнальные линии TRIG
(вход) и ECHO
(выход).
На вход TRIG
подаем импульс запуска измерения и через некоторое время получаем положительный импульс на выходе ECHO
. Длительность импульса ECHO
умноженная на некоторую константу K равна измеренному расстоянию.
Вся задача сводится к измерению длительности импульса в единицах времени K, для чего нам понадобится 8-битный счетчик, который будем тактировать частотой 1/K Гц. Выход счетчика будет отражать расстояние в сантиметрах (в двоичном представлении).
При этом, мы не хотим, чтобы в процессе счета на индикаторе отображалось постепенно увеличивающееся значение – это будет мешать чтению результата. Поэтому возьмем счетчик 74HC590 со встроенным выходным буферным регистром.
Выводами СЕ
(разрешение счета) и OE
(включение выходов) мы управлять не будем. На вход тактирования счетчика CPC
подан сигнал CLK0
задающего генератора (~= 58мкс или 17240 Гц).
Нам нужно сбросить счетчик по фронту ECHO
и сохранить состояние счетчика в выходной регистр по спаду. Сбросом занимается вывод MRC
, а записью в выходной регистр – вывод CPR
. Сброс происходит по низкому уровню, как нам и нужно, а вот запись – по фронту (не по спаду, как хотелось бы). Придется добавить инвертор. Для уменьшения количества корпусов в качестве инвертора возьмем 74HC00 (4 элемента И-НЕ), далее нам еще понадобятся элементы И-НЕ.
Тут сталкиваемся с первой небольшой проблемой. После спада ECHO
сигнал на вывод MRC
придет чуть быстрее, чем на CPR
, так как инвертор вносит некоторую задержку. Состояние счетчика будет сохраняться сразу после сброса, то есть сохранится ноль. Обычно для дополнительной задержки сигала ставят буферы, но мы не будем разбрасываться элементами и внесем задержку с помощью RC цепочки.
Выбранный счетчик может считать только до 255, но от датчика может прийти сигнал большей длительности: когда измеренное расстояние более 255 см или если измерение не удалось (в этом случаи датчик намеренно выдает очень длинный импульс). В таких ситуациях наш счетчик просто переполнится (возможно, не один раз) и затем будет остановлен на каком-то случайном значении. Поэтому нужно останавливать счет по достижению максимального значения, что можно сделать используя выход переноса RCO
.
По достижению счетчиком значения 255 RCO
переходит в низкое состояние отключая тактирование счетчика, что "замораживает" его значение до сброса (следующего измерения). Еще мы тут "случайно" инвертировали сигнал тактирования (с целью не добавлять новый корпус и использовать оставшиеся элементы И-НЕ), в данном случаи это не приведет к проблемам.
Теперь нужно сформировать сигнал TRIG
, запускающий измерения. Его период должен быть на несколько порядков больше CLK0
(>60мс). Для этого можно использовать отдельный низкочастотный генератор или поставить делитель на сигнал тактирования. Снова стремясь уменьшить количество элементов, пойдем вторым путем.
Возьмём CD4060 – делитель с коэффициентом деления до 214 с двумя встроенными инверторами (на которых мы соберем задающий RC генератор).
Генератор по схеме из даташита CD4060 запускаться у автора отказался, поэтому схема была изменена.
Для запуска измерения подадим сигнал с Q13
(~4 Гц) на TRIG
. Частота у него подходящая, а коэффициент заполнения (50%) – нет. Нам не нужен сигнал высокого уровня длительностью в 125мс, нам нужно всего около 0.02-1 мкс. Решим эту проблему еще одной RC цепочкой в режиме high-pass фильтра.
Вы, наверное, заметили появление кнопки на схеме. Она реализует функцию "HOLD": при ее удержании подавляются сигналы запуска измерения, тем самым на выходе счетчика будет удерживаться значение последнего измерения.
Запустив схему в таком виде с подключенными к выходу счетчика светодиодами мы уже сможем порадоваться значениям измеренного расстояния… в бинарном виде. Не сильно user-friendly, согласитесь, нужно срочно переводить в десятичную систему счисления. Сделать это можно несколькими способами, все они ужасны (требуют много корпусов), поэтому начинаем читерить (=.
Да, да, будет ПЗУ (параллельная EEPROM, в данном случаи). Тут многие могут возразить: "Как же так, без микроконтроллера, а программировать все равно нужно?! Заголовок – клик-бейт!" Что еще будет, когда придется показать, как прошивалась ПЗУ без покупки программатора.
"Программатор"
В качестве программатора берем ардуину и кучку проводов. Прищурив глаза будем смотреть на ПЗУ как на гигантский декодер адреса и 8192 диода в одном корпусе.
Описание процесса программирования ПЗУ выходит за рамки статьи. Скажу лишь, что с ардуино сделать это довольно просто. Самое неудобное – необходимость формирования двух источников напряжения 14В (для стирания) и 12В (для записи). Скетч "программатора" приведен с файлами проекта в конце статьи.
При формировании содержимого ПЗУ, преобразование числа 255 было заменено на вывод трех прочерков "---", что означает неудачное измерение.
Входов у ПЗУ много, а вот выходов хватит только на одну цифру 7-сегментного индикатора, потому будем использовать динамическую индикацию. Входы A8
и A9
в бинарном коде выбирают одну из трех отображаемых цифр, четвертое состояние не используется и соответствует погашенным сегментам. Для активации цифры индикатора (в зависимости от кода на A8
и A9
) понадобится 2-битный дешифратор с инвертированными выходами (т.к. нам нужно управлять общими катодами индикатора). Сделать дешифратор можно так (четвертый код мы не используем).
Теперь осталось подключить наш дешифратор и ПЗУ к делителю частоты, который будет заниматься формированием сигналов для A8
, A9
и IN0
, IN1
, тем самым последовательно перебирая десятичные цифры.
gif по кадрам
Цифры будут переключаться с частотой ~1кГц, поэтому не страшно, что они переключаются не по порядку, глазу это будет не заметно.
Однако, выходы делителя рассчитаны на нагрузку около 1мА, чего недостаточно для управления индикатором (на схеме выше сигнал CLK5
с делителя напрямую подключен к индикатору). Нас тут спас бы еще один инвертор (или буфер) перед CLK5
, но мы уже использовали все 4 элемента И-НЕ из 74HC00. Не добавлять же ради одного элемента еще один корпус. Используем вместо этого свободный выход D7
ПЗУ, запрограммировав его так, чтобы на D7
всегда была инверсия A9
. (Можно было бы и без инверсии, просто так сложилось.) Нагрузочная способность выхода ПЗУ достаточна для управления индикатором.
Собираем все вместе, добавляем регулятор питания и посыпаем схему щепоткой блокировочных конденсаторов.
Правильно собранное устройство настройки не требу -
Калибровка
Для правильного измерения расстояния нам нужно подстроить частоту задающего генератора подстрочным резистором. Сделать это можно так: размещаем датчик напротив ровной стены на известном расстоянии (чем больше, тем лучше точность калибровки). Расстояние выбираем как N+0.5 см, где N – целое. Далее ищем положение резистора, при котором значение на индикаторе самопроизвольно переключается между N и N+1. (Например, между 127 и 128, если выбранное расстояние – 127.5 см.)
Итог
-
Теоретическая точность измерений +/- 1см, не считая погрешность датчика. На самом деле все еще хуже, т.к. частота генератора плавает.
-
Потребление ~14мА, предполагается питание от "кроны". Даже плохой батарейки должно хватить на 6-8 часов.
-
Схема может измерять не только расстояние, но и другие физические величины. Нужен только преобразователь, который линейно переводит измеряемую величину в длительность сигнала.
Фото
Схема была отлажена на бредборде.
Потом решил заказать плату, для эстетического удовольствия.
Знаете, как называется, когда берешь первую непроверенную плату и впаиваешь в нее ПЗУ без каретки?
Это смелость.
Смелость и слабоумие, конечно.
В процессе переноса схемы с бредборда была допущена ошибка: перепутаны общие катоды двух крайних индикаторов (число 123 отображается как 321). Благо, это было исправлено через перепрошивку ПЗУ. Так что даже не пришлось резать и подпаивать проводки.
Ссылки
Схема/плата в Ki-CAD 5.1 и скетч для Arduino mega 2560, которым прошивалась ПЗУ
— На этом все, спасибо за внимание!
Автор: Alex-111