Обратная разработка реле времени ВЛ-76-С
Когда-то давно мне попалось под руку электронное цифровое реле времени ВЛ-76-С, новое, в упаковке, но в неисправном состоянии. Внутри никаких дефектов на печатных платах не было обнаружено. Стало быть, заводской брак, битая прошивка.
Общий вид реле.
Что удивило, применён популярный и простой микроконтроллер ATTiny2313. Внешне данная конструкция состоит из задатчика в виде трёх декадных переключателей и клеммы, на которую выведены питание 220В и контакты исполняющего ЭМ реле. Диапазон задания — 0.1…99.9 мин. с шагом 0.1 мин. (6 секунд). В Интернете отсутствуют схемы и прошивки на данную конструкцию, что вполне неудивительно. Долго не думая, решил срисовать схему с печатных плат и в дальнейшем написать программу на МК самостоятельно.
Конструкция состоит из трёх печатных плат, соединённых между собой. На первой плате выполнен блок питания и исполняющее реле TRA3. Блок питания сделан по безтрансформаторной схеме: для понижения напряжения применены гасящие конденсаторы. На второй плате находится МК ATTiny2313 и другие вспомогательные элементы. На третей плате — переключатели (задатчики) и контрольный светодиод.
Фото третьей платы с обратной стороны.
Начну описание с третей платы. Задатчики представляют собой переключатели на 10 положений. На них нет никакой маркировки, каждый из них имеет 5 контактов. Стало быть, в зависимости от положения те или иные контакты замыкаются в различных комбинациях. Вызванивая контакты, я тут же уловил закономерность: один фиксированный вывод (общий) замыкается с остальными четырьмя выводами (информационными) согласно двоичному представлению числа, соответствующего номеру выбранной позиции. Например, если выбрана позиция »3», то общий вывод (пятый по счету) замыкается с выводом третьим и четвёртым, так как число »3» в двоичном представлении — »0011». Вот такой хитрый переключатель. И там таких три. Они подключаются через разъёмы XP1 и XP2 ко второй плате с МК. Через разъём XP3 подключается светодиод и ещё какая-то ненужная незапаянная хрень, для которой предусмотрено место на плате. Вероятнее всего это распространённый шестивыводной переключатель DPDT (квадратненький такой, PB22E06 например). Может быть, плата универсальная, но в данной конкретной модели он не применяется.
Фото второй (основной) платы.
Вызванивая контакты переключателей, я не сразу понял принцип их подключения к портам МК. На основной плате сразу бросаются в глаза 8 SMD транзисторов. Позже выяснил, что эти транзисторы применены в роли диодных пар с общим анодом. Их базы идут к портам МК, а коллекторы и эмиттеры — на контакты переключателей. Потом мне объяснили, что в таких корпусах существуют диодные пары, они звонятся как транзисторы, но транзисторами они не являются. Итого, имеем 16 проводников, уходящие с диодных пар на третью плату. Три четверти из них (12 штук) приходят на информационные контакты переключателей (три по четыре), а 4 остаются свободными. Нетрудно догадаться, что теоретически они предусмотрены для четвёртого переключателя, которые не так или иначе отсутствует, ибо место на плате для него вовсе не предусмотрено. Тем не менее, чтобы не нарушать логику рассуждений, я буду упоминать о данном мнимом четвёртом переключателе. Общие концы второго и третьего, а также, первого и четвёртого переключателя (но четвёртый не предусматривает плата) попарно соединены вместе дорожками в основной плате на ответных разъёмах XS1 и XS2. Данные две пары подключаются к выходам транзисторных групп. Эти две одинаковые группы выполнены на транзисторах BC857 и BC847 (разных структур). Их входы подключены к МК. При подаче логического »0» на вход данной группы, на выходе будет также логический »0». Также, на плате расположен разъём XP2 для прошивки МК, подключенный к выводам SPI интерфейса МК, ответный разъём XS3 для светодиода и разъём XP1, соединённый шлейфом с первой платой. Следует помнить, что часть портов МК могут использоваться как для SPI (для прошивки), так и для обычного ввода-вывода (работа в схеме).
Всё вышесказанное отражено на схемах, которые я рисовал сначала на черновике, затем в SPlan. Номиналы радиоэлементов, которые были без маркировки (например, SMD конденсаторы), на схемах отсутствуют, они не столь важны. Сначала я приведу схему основной платы и платы с задатчиками (подписи картинок снизу).
Схема основной платы.
Схема третьей платы с задатчиками
Рассмотрим, каким образом происходит опрос каждого задатчика. Сигналы с портов PB4 и PB5 МК логическим »0» открывает транзисторы VT2 и VT1, следом, VT4 и VT3, подключая к нулевой шине общие контакты переключателей №1 и №2-№3 соответственно. Это происходит по очереди. Сначала с PB4 приходит логический »0» (PB5 пока что установлен в логической »1»), подключая второй и третий переключатель. В этом состоянии по очереди фиксируются значения сигналов контроллером с входных портов PB3, PB2, PB1, PB0 через диодные группы 2VD1…2VD4 со второго и отсутствующего четвёртого переключателей. Сразу же, фиксируются значения сигналов с выводов PD6, PD5, PD4, PD3 МК, на которые приходят через диодные группы 2VD5…2VD8 сигналы с первого и третьего переключателей. Но, так как у нас подключены общим контактом только второй и третий переключатель, на первые оговоренные порты МК придут сигналы фактически со второго переключателя, а четвёртый будет игнорироваться. Аналогично, на вторую половину МК придут сигналы только с третьего переключателя, а первый будет игнорироваться. На этом этапе контроллеру известны, в каких позициях установлен второй и третий переключатели. После этого PB4 устанавливается в «единицу», отключая второй и третий переключатели, а PB5 устанавливается в «ноль». При этом подключаются общим концом к «корпусу» первый и отсутствующий четвёртый переключатели. Их опрос происходит точно так же, как и в предыдущем случае, но теперь фиксироваться будут сигналы с тех переключателей, которые игнорировались в прошлый раз. Таким образом, контроллеру известна информация о положениях всех переключателей. Этот процесс похож на опрос матричной клавиатуры, но в данном случае матрица »4-слойная» размерами 2 на 2 с отсутствующим одним элементом.
Резисторы R8…R15 — подтягивающие. Хотя, можно было «подтягивать» и в самом МК. Точную частоту тактирования МК обеспечивает кварц на 10 МГц. R1 и C4 — схема сброса МК. Больше ничего на этой плате интересного нет.
Фото первой (силовой) платы со стороны элементов.
Фото первой (силовой) платы с обратной стороны.
Перейдём к рассмотрению схемы первой платы (рис. выше). Схема показалась очень интересной и местами непонятной.
Схема первой (силовой) платы.
C1C2 — для снижения напряжения. R1 — для разрядки вышеупомянутых. После диодного моста DB1 стоят два электролита. Для усложнения схемы (или же для надёжности) — каскадная схема стабилизации VT3R6VD3 — VT7R12VD5. VD5 похож на SMD транзистор с незадействованным эмиттером. Здесь обеспечивается стабилизированное постоянное напряжение 12В. Далее стоит линейный регулятор VR1 на 5В. Параллельно, с диодного моста DB1 через диод VD2 снимается напряжение на другой стабилизатор VT1R3VD1 на 24В. Данное напряжение поступает на обмотку ЭМ реле Rel1 и на R17. Последний — не понятно для чего. На другой конец R17 приходит сигнал с транзисторной группы VT9VT10. Схема данной группы аналогична схеме на основной плате. На вход данной транзисторной группы через разъём приходит сигнал с отдельного порта МК PB6. Для чего же он нужен? Зачем подключать резистор R17 к 24В? Скорее всего, была идея, что вместо резистора можно поставить что-либо ещё, например, внутренний контрольный светодиод, запрограммировав порт PB6 МК определённым образом. Или дополнительный коммутационный узел. Но, всё равно, это дурь, как выразились мои знакомые радиоинженеры, посмотрев плату конструкции. Второй конец ЭМ реле Rel1 подключён к аналогичной транзисторной группе VT2VT5, а она — на порт МК PD0. Сигналом »0» с этого порта включается исполняющее ЭМ реле. Самое интересное, что внешний светодиод подключен не параллельно ЭМ реле, а в разрыв эмиттера транзистора VT2, причём, через два разъёма (проходя основную плату). На клемме номера контактов 1 и 2, судя по наклейке на реле, остаются пустыми. Но в схеме контакт №2 соединён с общим проводом, а контакт №1 поступает на вход транзисторной группы VT6VT8. Выход с данной группы поступает на порт PD2 МК. Позже я в спецификации на данную модель реле прочитал, что данные контакты используются для управления в других моделях реле, собранные в том же корпусе. Рассматриваемая мной модель не предполагает управления, но его можно реализовать при написании программы на МК, так как схема данную возможность обеспечивает. Под управлением может подразумеваться старт, сброс (как в «тригерном», так и в обычном режиме), и всё, что в голову придёт. В спецификации на другие реле приведены временные диаграммы, где отражено поведение реле в зависимости от данного управляющего сигнала. Там же ниже сказано: по просьбе заказчика можем реализовать любую возможную диаграмму. И последний момент в схеме. Данный управляющий сигнал с клеммы №1 поступает ещё и на бесполезный транзистор VT4, подпитанный напряжением 12В. Это, опять же, усложнение схемы. А может быть здесь ещё какая-либо идея заложена? Я глубоко не вникал. Буду рад любым комментариям.
Маркировки выводов разъёмов подписаны через точку после названия самого разъёма. Римскими цифрами после символа »~» обозначены бесполезные и отсутствующие выводы. Последних в схеме не мало, но на них я не буду останавливаться. Ниже приведу рисунки эскизов каждой платы с обозначениями разъёмов, выводов и основных элементов.
Эскизы плат.
Рассмотрим описание исходного кода программы МК. Сама программа простая и была написана мной в CVAVR в течение 20 минут. Оговорю алгоритм, по которому будет выполняться программа. Данная информация может некоторым показаться весьма банальной, но она будет не лишней для начинающих. В моём варианте алгоритма задатчики на реле времени будут опрашиваться не один раз, а постоянно. Более того, опрос будет продолжаться даже после того, как реле сработает. Это позволить производить корректировку на ходу. Возможно, этот алгоритм не совпадает с оригинальным алгоритмом работы данного реле, но я с оригинальным алгоритмом не знаком. Именно на примере вышеозначенного алгоритма будет рассмотрено описание программы.
#include
#include
Далее, делаем необходимые макроподстановки, согласно схемным назначениям портов МК. Данные подстановки удобны тем, что в тексте программы вместо, например, PORTB.5, можно будет писать getAD, что более удобно. Сочетание getAD при компиляции будет интерпретировано как PORTB.5. Итак, первая подстановка — выходы для подключения первого (A) и четвёртого (D) переключателей задатчика. Вторая — для второго (B) и третьего (C). Далее — подстановка для включения реле. И, наконец, неиспользуемая в программе и в рассматриваемой модели подстановка «Ctrl». Её можно и не писать.
#define getAD PORTB.5
#define getBC PORTB.4
#define RL PORTD.0
#define Ctrl PIND.2
Переменные A, B, C служат для хранения номера положения соответствующих трёх переключателей и принимают значения от 0 до 9.
unsigned char A,B,C;
Переменная i — текущее значение номера десятой доли минуты (6-секунды), то есть, номер минимального «тика» реле. Переменная t — число десятых долей минут (тиков), получаемое с задатчика.
unsigned int i=0,t;
Основная функция программы представлена ниже. В первых 6 строчках я не разбирался. Они сформированы с помощью вспомогательной утилиты CodeWizadAVR и связаны с наличием внешнего кварца на 10 МГц.
void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
Следующие две строки конфигурируют порт B нашего МК. Согласно схеме, ставим младшие 4 бита на вход, а старшие — на выход (PB7 не используется, а PB6 — бесполезный, но, по идее схемы, выходной). Следовательно, согласно принципам конфигурации МК, которые я не буду излагать, записываем в регистр DDRB число 240 (F0 в 16-ричной нотации). Начальный выходной уровень — »1», кроме ненужного PB7. А на входы на всякий случай подключим «подтягивающие резисторы» МК, хоть они в схеме уже установлены. Для этого регистру PORTB дадим значение 7F в 16-ричной нотации.
PORTB=0x7F;
DDRB=0xF0;
Аналогично конфигурируется порт D. Все пины на вход, кроме двух младших. «Подтягивающие резисторы» на входных и начальный выходной уровень »1» на выходных — аналогично.
PORTD=0x7D;
DDRD=0x03;
Следующие пять строчек относятся к конфигурированию одного из таймеров МК. Данный таймер шестнадцатиразрядный, то есть обеспечивает счёт до 2^16=65536. Частота счёта определяется тактовой частотой МК и коэффициентом деления (один из пяти предустановленных). В описываемой программе было принято решение вести счёт в течение 6 секунд (минимального шага задания), после чего увеличивать переменную i на 1 и сбрасывать таймер на начало счёта. Для того чтобы обеспечить вышесказанное, нужно взять максимальный коэффициент деления 1024 и считать до 58594. Последнее посчитать несложно. Частота МК — 10000000 Гц. Используя коэффициент деления 1024, частота таймера будет равна 10000000/1024=9765.625 Гц, а период — 1024/10000000=0.0001024 сек. В течение 6 секунд уложатся 6/0.0001024=58593.75 таких периода. Данное число лежит в пределах 16-разрядного таймера, но оно не целое, поэтому придётся округлить до 58594. При этом погрешность нашего реле времени будет незначительна: 58594–58593.75=0.25; 0.25×0.0001024=0.0000256; 0.0000256×999=0.0255744. То есть, за максимально возможный промежуток времени (99.9 мин.) неточность данного реле времени составит приблизительно 25.6 миллисекунды, что вполне допустимо на практике. Кстати, производитель тоже оговаривает погрешность устройства, и наша погрешность будет не хуже. В регистр конфигурации таймера TCCR1B записываем значение 5. Не вдаваясь в подробности, это означает, что таймер запускается и коэффициент деления равен 1024. В регистр TCNT1 записываем значение 0. Данный регистр 16-разрядный и разделён на две 8-разрядные половины: младшую (L) и старшую (H). В него записывается значение, откуда таймер будет вести счёт. Нам надо считать с нуля. В регистр OCR1A записывается значение, до которого будет считать таймер, после чего он вызовет функцию прерывания. В этот момент прервётся выполнение основной функции программы, и выполнятся действия, прописанные в функции данного прерывания. После отработки прерывания продолжится выполнение основной функции. Данное значение, как было выше сказано, равно 58594 (E4E2 в 16-ричной нотации). Так как регистр OCR1A также разделён на две половины, записываем вышесказанное значение по частям.
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0xE4;
OCR1AL=0xE2;
Следующие две строчки конфигурируют разрешение прерываний должным образом (не стоит вдаваться в подробности).
TIMSK=0x40;
#asm("sei")
В основном цикле происходит постоянный опрос переключателей задатчика (по алгоритму в описании схемы) с применением задержек в 30 мс для корректности и устойчивости работы. Установкой на PORTB.5 значения »0» (getAD=0) подготавливаем первый переключатель. Его выводы подключены к порту D МК к пинам 6, 5, 4, 3. Направление — от младшего к старшему. То есть, младший бит переключателя подключен к относительно младшему биту (бит 3) порта D МК. Поэтому, чтобы получить информацию с порта D МК о положении первого переключателя, необходимо произвести побитовый сдвиг вправо на три позиции (PIND>>3), инвертировать полученные биты операцией »~» (так как информация будет приходить по »0», согласно схеме) и обнулить ненужные старшие четыре бита полученного 8-разрядного значения. Последняя операция делается путём логического побитового умножения результата на число 15 (00001111 в бинарном представлении). После этой операции переменной A будет присвоено значение позиции первого переключателя. Далее — отключается первый переключатель, и подготавливаются второй и третий. Значение со второго переключателя в переменную B снимается с порта B МК аналогично, но без операции сдвига, так как выводы данного переключателя подключены к самым младшим пинам порта B МК и также сонаправленно. Информация с третьего переключателя в переменную C снимается точно так же, как и с первого. После этого «закрываются» второй и третий переключатель (getBC=1) и в переменную t подсчитывается задаваемое значение (число десятых долей минут) с трёх переключателей.
while(1){
delay_ms(30);
getAD=0;
delay_ms(30);
A=(~(PIND>>3)&15);
delay_ms(30);
getAD=1;
getBC=0;
delay_ms(30);
B=(~PINB)&15;
C=(~(PIND>>3)&15);
delay_ms(30);
getBC=1;
t=100*A+10*B+C;
}
}
Сравнение данной переменной и аналогичной переменной реального времени i происходит в функции прерывания.
interrupt [TIM1_COMPA] void timer1_compa_isr(void){
i+=1;
if(i>=t){
RL=0;
}else{
RL=1;
}
TCNT1H=0x00;
TCNT1L=0x00;
}
Если последняя переменная превысит задаваемое значение, по »0» включится исполняющее реле (RL=0). Более того, оно отключится, если при этом установить переключателями значение большее, чем набежало в переменной i. В этой же функции прерывания выполняется увеличение переменной i на 1 и сброс таймера в 0.
Биты FUSE были списаны с МК и оставлены без изменений. Я их проанализировал, там всё нормально.
Таким образом, была не только срисована схема устройства, но и разработана программа на МК, которая по функциональности не отличается от фирменной. Более того, появилась возможность на программном уровне довольно гибко (и, самое главное, бесплатно) изменять временные параметры устройства и в различных функционалах использовать вывод управления (№1 на клемме). Программа настолько проста, что её можно (даже лучше) написать на ассемблере, но я этим пока не занимаюсь.