Рассказ о процессе заимствования при разработке электроники на наглядном примере.
Однажды мне понадобилось скопировать довольно простое устройство. Компания-производитель перестала существовать, но по всей стране ещё был спрос на замену сломанных или отработавших свой ресурс девайсов.
Само устройство — кнопка вызова лифта на фото слева. Для опытов мне дали два экземпляра, один из которых можно было полностью разобрать.
Общий план работы выглядел примерно так:
- Изучение схемы подключения платы;
- Изучение элементной базы самой платы;
- Срисовывание её электрической схемы;
- Попытка считывания файла прошивки из микроконтроллера;
- Дизассемблирование прошивки;
- Извлечение алгоритма работы;
- Разработка новой платы;
- Написание новой прошивки.
При неудаче пункта 4, дальнейший план выглядел бы сложнее, но мне повезло.
Изучаем подопытного
Плата собрана на микроконтроллере 1997 года выпуска AT89C2051, в основе которого лежит архитектура Intel MCS-51. В 2020 году она празднует свой 40-летний юбилей на рынке встраиваемых систем.
Небольшое пояснение: микроконтроллер — это такая микросхема, содержащая вычислительное ядро и набор периферии для управления внешними устройствами. Например, в современной стиральной машине микроконтроллер опрашивает кнопки управления, датчики, выводит информацию на экран и управляет насосами, нагревателем, клапанами и приводом барабана. Для большинства перечисленных функций ему не требуются промежуточные устройства, только набор пассивных электронных компонентов.
Срисовывание оригинальной электросхемы платы в будущем поможет узнать назначение пинов микроконтроллера, которое необходимо для разбора кода прошивки.
Оригинальное устройство разработано китайской компанией, а потому его схема крайне запутана и со множеством лишних компонентов. Например, включение реле производилось через тройной каскад из биполярного транзистора, оптопары и полевика (именно в таком порядке).
Знакомый, работающий с китайскими производствами, рассказал мне, что китайцы занимаются подобным усложнением схем для увеличения стоимости разработки и производства, если то и другое делают одни люди. После такого я склонен ему верить:
Схема срисована, загадочные места смоделированы в мультисиме, берёмся за прошивку.
Пытаемся считать прошивку
Мне очень повезло, что на обоих платах в контроллерах не включена защита от чтения, поэтому я успешно слил два варианта прошивки подобной порнографией:
Дизассемблирование прошивки
Следующим этапом нам нужно преобразовать этот машинный код во что-то более читаемое:
Берём известный инструмент IDA Pro, в котором уже есть наш контроллер со всеми регистрами периферии, и открываем HEX файл прошивки:
После этого идёт довольно нудный процесс изучения набора команд нашего вычислительного ядра, комментирование и расшифровка ассемблерного кода.
По адресам таблицы векторов прерываний нашлись сами обработчики прерываний, записи в регистры периферии дали информацию о конфигурации интерфейса связи. Шаг за шагом безымянный ассемблерный код превратился в то, что можно читать.
Извлечение алгоритма работы
Так как мне нужно было разработать новое устройство на другой элементной базе, из кода необходимо было извлечь алгоритм. Некоторое время спустя родился такой псевдокод:
Кому интересен протокол передачи:
Станция управления лифтом общалась с платами кнопок вызовов по полнодуплексному 24-вольтовому интерфейсу. В обычном режиме платы кнопок слушали линию, ожидая 9-битный пакет данных. Если в этом пакете приходил адрес нашей платы (задавался DIP-переключателем на плате), то плата переключалась на 8-битный режим приёма, и все последующие пакеты аппаратно игнорировались остальными платами.
Первым после адреса шёл пакет с кодом команды управления. Конкретно эта плата принимала всего 3 команды:
1. Запись в регистры данных. Например частота и длительность мигания кнопки при вызове;
2. Включение подсветки кнопок;
3. Запрос состояния кнопок (нажаты или нет).
Последним байтом шла контрольная сумма, которая представляет собой простой XOR всех байт после адреса.
После контрольной суммы плата опять переходила в режим ожидания своего адреса.
Разработка новой платы
Для этапа разработки новой электросхемы и печатной платы у меня нет картинок, но всё было примерно так:
Составление электросхемы и разводка платы делались в Altium Designer. Изготовление печатной платы заказывалось в зеленоградском «Резоните».
Написание новой прошивки
Пока наша новая плата на изготовлении, едем на объект, где установлены такие кнопки вызова, и проверяем правильность разобранного протокола передачи с помощью собранного на ардуине сниффера:
Дальше нужно было действовать крайне аккуратно, чтобы не спалить ничего в лифте и не допустить его остановки.
Проверяем, что всё работает как надо, исправляем косяки и пишем новую прошивку под наше устройство:
Простоту устройства и прошивки можно оценить по объёму кода, он содержит всего лишь около 600 строк на языке Си.
Процесс сборки выглядел так:
Фотографию готового устройства приложить не могу, просто поверьте, что оно до сих пор производится и продаётся.
Лирическое заключение
По поводу кнопок лифта «вверх» и «вниз» на этаже. Я заметил, что многие люди совершенно не понимают их назначение и жмут обе сразу.
У лифта есть два набора кнопок: в кабине — панель приказов, и на этаже — панель вызова. Уже по названию можно догадаться, что панель приказов имеет более высокий приоритет управления.
Все лифты, имеющие панели вызовов с кнопками «вверх» и «вниз», работают с каким-то из вариантов алгоритма оптимизации поездок, целью которых является перевозка максимального числа пассажиров за минимальное время и отдельное условие максимального времени ожидания на этаже (регулируется госстандартом).
Такой алгоритм обычно предполагает подбор пассажиров на этажах, если они едут в том же направлении, которое указывают нажатием кнопки вызова «вверх» или «вниз».
Представим ситуацию, что лифт с пассажирами едет вниз и по пути получает с этажа ниже вызов «вниз». Лифт остановится для подбора пассажира (да, есть ещё учёт загрузки кабины по весовому датчику, но его мы опустим).
Лифт едет дальше и получает с этажа ниже вызов «вверх». Логично, что лифт не остановится для подбора пассажира, так как не будет менять направление движения (это тоже регулируется стандартом), а подбирать пассажира, чтобы поехать вниз, а затем вверх — бесполезный расход энергии и места в лифте.
Лифт едет дальше и получает с этажа ниже сразу два вызова «вверх и «вниз», которые нажал какой-то нетерпеливый пассажир, которому нужно ехать вверх. Логично, что лифт остановится на этом этаже, но пассажир в него не войдёт, зато потратит время людей в кабине на замедление и остановку лифта, открытие дверей, ожидание, закрытие дверей и разгон до номинальной скорости.
Если у лифта только одна кнопка на этаже, то в 99% случаев он работает по алгоритму «собирательный вниз», и при наличии приказов в кабине останавливается только при движении вниз.
Если у вас есть навыки программирования на JS, то можете попробовать реализовать подобный алгоритм управления в онлайновой игре Elevator Saga. В ней есть все аспекты оптимизации поездок без углубления в хардкор вроде работы цепей безопасности лифта.
Я завёл себе телеграм-канал, где буду выкладывать подобные материалы. Прямо сейчас там можно следить за разработкой очередного устройства.
Отдельное спасибо Роману Персианинову, который помог это всё прилично оформить.