Многие из вас на предприятиях и иных объектах бывшего СССР встречали зелёные сегментные часы. Были самостоятельные устройства, типа “Электроника-7”, но так же существовали и вторичные, как в предыдущем посте, только более сложного строения — часы семейства “Воронеж”. Они также включались в единую часовую сеть предприятия и показывали то время, которое передавалось от главных первичных часов по проводам.
Решил разобраться, как же это работало, и самостоятельно собрать первичные часы. Из-за отсутствия документации, информации по данной теме, а также живых первичных часов — это превратилось в настоящий квест, реверс-инжиниринг, навязчивую идею, боль страдание и бессонные ночи с кодом и осциллографом в обнимку.
Тем не менее, я смог их победить, и могу теперь рассказать, как же они работают и поделиться кодом своего проекта.
Как всё начиналось
Если вы помните, в моём посте “Охота на блошках 2.0 — Уделка” приводил фотографию разбитых вторичных часов. Меня поправили и сказали, что это обычные часы “Электроника-7”, и ценности они не представляют. Но хотелось приключений, и будучи в Санкт-Петербурге, я купил первичные часы и вторичные часы “Воронеж”, в надежде, что их можно будет поженить (как же сильно я ошибался).
Достаточно быстро я выяснил, что протоколы у них несовместимы и работать вместе они не будут. В результате, для начала разобрался как же работают первичные часы “старого типа”, что вылилось в пост “Разбираемся с работой часовых сетей в лабораторных условиях”, а потом приступил к часам “Воронеж”. И, как оказалось — это было верное решение. На ловца и зверь бежит!
Поиск информации и разъёмов
Шильдик
Если начать искать информацию по запросу “вторичные часы Воронеж” или по маркировке “ВЧЦ1-С2ПГ12К-80”, то, за исключением ЖЖ sfrolov, информации практически нет. Более того, встречаешь форумы, где Сергей спрашивает о протоколе часов, но без ответа.
В результате одним из кладезей информации стал его пост: “Вторичные часы «Воронеж”. Сергей, также позднее сделал собственный контроллер этих часов. Чисто из спортивного интереса, по максимуму я старался двигаться самостоятельно, не спрашивая Сергея. Также Сергей мне косвенно очень помог, своим постом, и тем, что в личной беседе сказал, что его посылки сигналов в посте отличаются от тех, что посылают оригинальные первичные часы.
Как я уже сказал, на ловца и зверь бежит. Для моего прошлого поста, уже в Москве я докупал вторичные часы. С продавцом разговорились, и оказалось, что у него есть первичные часы для “Воронежа”. К сожалению, мне не удалось уговорить продавца, чтобы я смог снять живые сигналы с его часов, предлагая деньги. Однако, продавец всё же, отфотографировал паспорт часов, где были бесценные эпюры и описание их работы
В общем, я разобрал все эти фотографии, немного обработал и сделал отдельную pdf, чтобы другие люди, которые пойдут по моим стопам, смогли её использовать в своих целях. Фактически, то что я делал дальше, основывалось только на этих данных.
Последнее, чего мне не хватало для полного счастья, чтобы начать работать с часами — это разъёма питания. Он оказался достаточно хитрым, хотя мне казалось что где-то я видел такие разъёмы, но на других приборах.
Не хотелось делать времянку из автомобильных клемм (да и опасно это с 220 вольтами). Поэтому долго искал варианты. Тут я просто кинул клич среди друзей, в том числе написал BootSector и он даже нашёл у себя в закромах таковой разъём, но что-то мы так и не состыковались. В одном из чатов, на помощь пришёл sfrolov, поняв, для чего я ищу. И дал ссылку на “Мешок”, где я и заказал жмень таких разъёмов.
Жмень разъёмов.
Внутри разъём оказался очень интересно устроен — сама прижимная клемма выполнена из нескольких наборных пластин, так что их нужно спаивать между собой. Если кому нужен такой разъём, у меня ещё есть в запасе.
В результате я получил вот такой аккуратный провод.
Пардон за жёлтую термоусадку, но чёрной не было, а дело было в ночи. В результате, всё готово, чтобы приступить к экспериментам.
Формат посылки
Располагая документацией, всё стало немного веселее. Если кому интересно, настоятельно рекомендую читать её всю (и по несколько раз, до просветления), но я приведу главные тезисы.
Перевожу с инженерно-советского на русский: каждые 20 мс у нас идут синхроимпульсы (СИ), между ними идут шесть пачек тактовых импульсов (ТИ), с интервалом 33,(3) мс и после них идёт двоичный код посылки десятков часов, единиц часов, десятков минут, единиц минут, десяток секунд, единиц минут. Единственное, что я не понял — это информационный импульс (ИИ). После 15 прочтений документации, яснее не стало. Проще взглянуть на картинку эпюр сигнала.
Если вы ещё ничего не поняли, не печальтесь, я тоже ничего не понимал долгое время.
Что из этого графика у нас есть: это формы сигналов, общая длительность посылки (20 мс), и то что сигнал у нас двухполярный (минус, ноль и плюс).
Что у нас нету: амплитуды сигнала, длительность одиночного импульса, и что же такое, ИИ? Будем честны, на последний вопрос у меня до сих пор нет толкового ответа.
Из графика выше, совершенно непонятно какое время выводится и документация, в сущности не даёт ответа на вопрос. Принципиальной электрической схемы устройства нет.
Поэтому придётся обратиться к посту sfrolov и взять оттуда картинку. Ниже процитирую информацию, которая оказалась мне полезной.
Сначала идёт длинный импульс сброса номера позиции отрицательной полярности (1). Такие же импульсы, но короткие (2) сбрасывают счетчик номера цифры.
Импульсы (3) как-то связаны с импульсами сброса (2) и должны идти друг за другом. Наверно чтобы отделить длинные импульсы от коротких. Номер цифры задается количеством счетных импульсов (4). Сколько импульсов придёт, такая цифра и отобразится. На осциллограмме можно увидеть, что закодировано время 22:09.
Если импульсов (2) не ставить, то на следующей позиции номер цифры будет прибавляться к предыдущей. То есть если предыдущая цифра была „3“, а на следующую позицию пришло еще два импульса (4), то зажжется цифра 5.
После пачки импульсов необходимо выдержать паузу, по окончании которой предыдущая цифра сменится той, которая пришла. То есть пока обрабатывается текущая цифра, на экране отображается предыдущая.
Внимательный тот, кто заметит, что на картинке в посте одни тайминги, а на видео там же другие. Однако, буду лукавить, если скажу, что не пробовал повторить этот сигнал, и да, я его повторил, но результат мне не понравился. Поэтому мы пойдём другим путём.
Из картинки выше, самое ценное, что сигнал ИИ (по паспорту), он же (2) (по картинке) идёт перед посылкой импульсов. Дальше уже дело техники сформировать данную посылку.
Электрическая часть
Одна из самых сложных задач было сформировать сигнал трёх напряжений: отрицательной полярности, нуля и положительной. Плюс, мне было неизвестно рабочее напряжение посылки. Эмпирическим путём было установлено, что мои часы работают, начиная от шести вольт. Поэтому я выбрал рабочее напряжение 12 вольт.
Когда только принёс часы домой, очень хотелось проверить, работают ли они вообще, поэтому провёл весьма варварский эксперимент: поочерёдно подключал то плюс, то минус, и получил такую картину.
Из чего стало понятно, что мне не требуется хитрого многополярного питания, а достаточно, как и в прошлой статье использовать Н-мост, например, драйвер двигателя L9110S. И в начале отладки, я даже использовал ту же плату, которой тактировал часы “Стрела”. Единственное, что на плате драйвера надо снять конденсатор.
Если этого не сделать, то на выходе будет получаться очень забавная арабская вязь.
Арабская вязь.
Однако, после шести сгоревших драйверов (на каждой платке их два), я понял что нужно что-то делать. Они горели как свечки. Оторвался провод питания — сгораем. Подключаем по USB, вместе с внешним блоком питания — горим с пламенем (я ни разу до этого не видел таких фейерверков). Поэтому, я решил отказаться от китайских плат, и купил себе нормальные микросхемы IR4427 с адекватным током работы и потолком напряжения выше 12 вольт. И всё стало сильно стабильнее.
Жаль, что микросхема pin to pin несовместима с L9110S, так бы поставил прямо на ту же плату, но увы.
Макетка с IR4427.
В качестве часов я выбрал модуль часов реального времени DS3231, и для отображения готовый модуль дисплея для Arduino. За основу потом взял Arduino Uno, её же питал от 12 В, и с неё же брал эти 12 В для драйвера.
На самом деле, работать с часами и дисплеем просто, примеров в интернете вагон, эта часть кода совершенно неинтересна. А вот сделать правильный сигнал — это важно, и совершенно не принципиально на какой плате вы это реализуете.
Его величество код!
Код, радикально (полностью) я переделывал три раза. Это выстраданная глава. В первую очередь, расскажу то, что может быть полезно и в других задачах. Скажу сразу, что имел глупость использовать среду Arduino, где очень многое скрыто под капотом. В какой-то момент я даже думал плюнуть и переписать на тёплом ламповом си, где всё прозрачно, но пока сдержался, потому что сама отладка тоже отняла слишком много времени.
▍ Отладочный код
Итак, наша задача — это формировать сигнал, с заданными длительностями. В качестве отладки сделал такую структуру.
struct pulse_package {
uint8_t direction;
uint16_t delay_t;
};
Первая переменная — направление передачи, которое может принимать три значения:
#define POS_SIG 3
#define NEG_SIG 2
#define ZER_SIG 0
Где, 3 и 2 — соответствующие пины, нуль — отсутствие пина. delay_t — это переменная длительностей в микросекундах, соответственно она будет передана в функцию delayMicroseconds(), которая на вход принимает переменную типа uint16_t и со значением до 16383 (это важно, чтобы не выйти за рамки допустимых значений).Меня в этой структуре смущает, что она не выровнена в памяти (элемент занимает 3 байта), и занимает драгоценную оперативную память, но я прикинул, что её должно хватить. По хорошему, стоит подобные структуры делать константой и размещать в памяти программ.
Сама отправка сигнала осуществлялась функцией, которая на вход принимала указатель на массив структур.
void send_to_voronezh(struct pulse_package *to_send) {
for (int i = 0; to_send[i].delay_t != 0 ; i++) {
switch(to_send[i].direction) {
case POS_SIG:
set_posi_sig();
break;
case NEG_SIG:
set_nego_sig();
break;
case ZER_SIG:
set_zero_sig();
break;
default:
break;
}
delayMicroseconds(to_send[i].delay_t);
}
}
О функциях
set_posi_sig(), set_nego_sig(), set_zero_sig()
я расскажу чуть позднее, но и так понятно что тут происходит.Формирование самого массива структур делаю прямо в функции
loop()
:void loop() {
static struct pulse_package pulse_package_send [] = {
{NEG_SIG, LONG_NEG}, //Синхроимпульс №1
// {ZER_SIG, LONG_AFTER_LONG_NEG}, //нулевой импульс
{POS_SIG, SHORT_P}, //импульс №3
{NEG_SIG, SHORT_P}, //импульс №2
//1
{POS_SIG, SHORT_P}, //импульс №4
{ZER_SIG, LAST_LONG-SHORT_P}, //нулевой импульс между посылками
....
};
send_to_voronezh(pulse_package_send);
}
Как видно, можно легко, в текстовом виде сделать сигнал с заданными таймингами, практически любой длительности (сколько позволит память вашего контроллера). Это не прям Real Time Output, но лучше, чем ничего.
В результате на выходных пинах контроллера 2 и 3 (простите меня за ардуиновские обозначения), мы получим, например, вот такой сигнал:
Могу сразу сказать, что это неработающая осциллограмма, но принцип уже хорошо виден. Жёлтый график — это сигналы отрицательной полярности, синей — положительной. Тут попытка вывести 22:09.
Вывод в порт осуществлялся следующими инлайновыми функциями (для экономии тактов процессора, они нам ещё пригодятся).
inline void set_zero_sig() __attribute__((always_inline));
inline void set_posi_sig() __attribute__((always_inline));
inline void set_nego_sig() __attribute__((always_inline));
void set_zero_sig() {
digitalWrite(POS_SIG, HIGH);
digitalWrite(NEG_SIG, HIGH);
}
void set_posi_sig() {
digitalWrite(POS_SIG, LOW);
}
void set_nego_sig() {
digitalWrite(NEG_SIG, LOW);
}
Чем удобно вынести всё это в отдельные функции? А тем, что всё это можно заменить printf с печатью сигнала на экране, и получить готовый консольный осциллограф (берите на заметку те, у кого нет осциллографа). Для примера одна функция, остальные аналогичные:
void set_zero_sig() {
if ( -1 == signal_stage) {
printf("- \n");
}
if ( 1 == signal_stage) {
printf(" -\n");
}
signal_stage = 0;
}
В результате можно получить такой симпатичный график, который удобно пролистать.
Смех, смехом, но именно таким образом я потом отлаживал реализацию с помощью таймеров. Оказалось очень удобно, и легко отлаживать. Всё проще, чем каждый раз компилировать, отключать контроллер, подключать его обратно и смотреть осциллографом.
Отлаживать удобнее всего оказалось на 00:00:00, что логично, так как нет лишних импульсов. Самая беда начинается на цифре восемь и девять. Ниже покажу видео.
Сформированный программой сигнал.
И да, этот сигнал оказался рабочим, хотя период между синхроимпульсами составляет всего 12 мс (вместо положенных 20).
Часы стабильно показывают время.
На фото видно, что ещё используется L9110S (он сгорел, буквально через пару часов), а также пока что не подключен дисплей и часы.
Очень важный момент, выше — это отладочный код, который не попал в основную программу, но дал понимание, куда надо идти.
▍ Подключаем дисплей, клавиатуру и часы
Подключение дисплея 1602, клавиатуры на АЦП и часов достаточно простое и примитивное занятие — это примеры из интернета, и я даже не буду заострять на них внимание. Но важно другое, что суммарно опрос клавиатуры, запись значения в дисплей, получение времени с DS3231 занимали 16 мс! Что, ну никак не укладывается в последовательное выполнение программы. Поэтому необходимо было создать отдельный “поток” программы, который бы выполнял код. Поток, здесь скорее в кавычках, так как это не полноценные потоки в понимании, с переключением контекста, хотя на AVR я такое реализовывал, и это вполне реально. В этом случае, одну из функций нужно вынести в отдельный таймер.
Долго думал, что же вынести, всё же решил вынести самое критичное по таймингам — это функцию вывода сигнала. И в результате код был полностью переписан. Это была уже третья итерация. Промежуточную можете посмотреть по коммитам на гите.
Как вы помните, во многопоточном программировании, если вы работаете с разделяемой переменной, вам необходимо её ограждать мьютексами, либо семафорами, либо другим иным способом синхронизации потоков. Тут полностью такая же ситуация. В данном случае, разделяемая переменная у нас — это структура содержащая дату и время. Разделение доступа к переменный осуществляется очень просто, в качестве мьютекса у нас выступает запрещение прерываний на время записи в переменную. Таким образом, пока идёт запись структуры, эта операция будет полностью атомарной. После разрешения прерываний, если прерывание поступило в этот момент, оно будет обработано.
int settime () {
tmElements_t l_time = {0};
...
RTC.read(l_time); //read time from DS3231
noInterrupts();
m_time = l_time; //send time to output function
interrupts();
Так делается в двух местах программы.
Функцию вывода сигнала отлаживал очень долго, и очень пригодился вариант с помощью printf. Вообще, в больших программах, можно сделать это всё дефайнами и делать универсальный код для отладки на компе и работе в контроллере.
Как выше было сказано, для вывода, я сделал отдельную функцию таймера. Она вышла просто монструозной, и кто сможет разобраться, что в ней происходит, тому дам конфетку. Приводить её сюда целиком не буду, однако обращу внимание на некоторые моменты. Таймер дёргается с интервалом 50 мкс (то есть, я могу делать импульсы не короче этого периода). Для того, чтобы минимизировать время выполнения функции, и не мешать основному коду программы, везде, где только было можно, использовал “запрещённый” оператор goto. Но если вы откроете код ядра линукс, особенно драйвера, то увидите, что он используется там постоянно. В общем, это можно делать, но с умом.
ISR(TIMER1_COMPA_vect) {
...
if (_delay >= TIMER_PERIOD) {
_delay-=TIMER_PERIOD;
goto exit_isr;
} else {
_delay = 0;
}
if (0 == pkg_stage) {
SET_BIT(pkg_stage, H_SYNC_PULSE); //h-sync pulse stage
numbers[0] = m_time.Hour / 10;
...
numbers[5] = m_time.Second % 10;
//first pulse
set_nego_sig();
_delay = PULSE_DURATION;
goto exit_isr;
} else {
set_zero_sig();
if (CHK_BIT (pkg_stage, H_SYNC_PULSE)) {
CLR_BIT(pkg_stage, H_SYNC_PULSE);
SET_BIT(pkg_stage, L_SYNC_PULSE); //l-sync pulse stage
set_posi_sig();
_delay = PULSE_DURATION;
goto exit_isr;
...
exit_isr:
return;
}
Таким образом, функция таймера — это машина состояний, которая даёт нужный сигнал, в зависимости от того, каком состоянии сейчас находится. Могу честно сказать, что я треснул умом, пока сделал её.
Отладка.
Какая же форма сигнала правильная?
Скажу сразу, что я до сих пор не знаю ответа на этот вопрос. Ниже покажу, те формы, которые оказались рабочими.
Изначально, я использовал большие паузы между посылками, и в целом это было хорошим решением, но мне хотелось большего, и проверить в каких режимах будет работать, и может подобрать более подходящий.
Форма сигнала с большими паузами. Тут СИ, ТИ и ИИ.
В результате я решил добиваться формы эпюр, которые были изображены в паспорте. Как видно, что там сигналы переходят друг в друга, без нулевой паузы между ними. Изначально, все мои сигналы следовали друг за другом с определённой задержкой, но я отказался от такого решения, потому что работает и без неё. Плюс, изначально сигнал синхроимпульса был длиннее, чем остальные сигналы, как оказалось, что и это не важно. На данный момент начало сигнала выглядит таким образом (пока не смотрите на время развёртки — это не принципиально).
Начало посылки.
1 это синхроимпульс (СИ), один на каждую пачку посылок, далее он без паузы переходит в 3 тактовый импульс (ТИ), который, также без пауз, переходит в 2 — информационный импульс (ИИ). После чего, также без пауз идёт посылка часов, уже разделённая паузами (тут 2 десятка часов и 1 единица). В посылке единиц часов всё тоже самое, но без СИ.
Вот график, как выглядит такая посылка целиком.
Полная форма сигнала. Время: 16:49:38.
Теперь главный вопрос: какие длительности импульсов и нужна ли пауза после посылки каждой цифры? Если без паузы, то длительность импульса я взял 150 мкс, и следующий импульс начинал после истечения времени всех пульсов, но это привело к забавным артефактам. Проиллюстрирую в видео.
Как видно, такое решение нельзя назвать рабочим. В результате, на данный момент я остановился на предельном значении импульса, равное 50 мкс, и после посылки делаю паузу, равную 2700 мкс, за вычетом отправленных импульсов и пауз между ними. В результате сейчас всё выглядит следующим образом.
Да, работает не идеально, и есть ещё куда расти.
Резюмируя
Да, я смог докопаться и понять алгоритм работы часов. Практически каждый день, на протяжении месяца я ковырялся с этими часами, всё свободное время я думал, как улучшить код, как сделать его оптимальнее и элегантнее. В качестве награды — часы наконец-то показывают время.
На фото видно, что секунды светятся ярко, а остальные цифры имеют отдельные яркие точки, но остальные точки тусклые. Это не ошибка фотосъёмки, это так и выглядит.
Но, вы сами видите на видео, что в режим работы часов я так и не попал. Вам на фотографиях кажется, что яркость часов недостаточная — это не кажется, они в действительности светят странно, каждый отдельный сегмент имеет разную яркость. Я пробовал разные тайминги, разные режимы работы (даже те, о которых тут не рассказал), игрался с ними по-всякому — всё равно свечение сегментов неяркое и есть блики. Допускаю также, что конденсаторы внутри требуют замены, но, вероятнее всего, я делаю что-то не так. Пока рано делать выводы.
P.S.
Громадное спасибо sfrolov — осциллограммы есть!
Ссылки:
- Паспорт первичных часов.
- Проект на гитхаб.
- Вторичные часы „Воронеж“
- Другой самодельный Контроллер вторичных часов „Воронеж“
Комментарии (65)
Xobotun
30.08.2021 12:53Рискну предположить, что если СИ — синхроимпульс, ТИ — тактовый импульс, то ИИ — информационный импульс или инфоимпульс.
UPD: отвечал на вопрос "что же такое ИИ?", не заметив, что и в документации, и параграфом выше это было написано. >_<
dlinyj Автор
30.08.2021 12:57Ну да, я об этом говорил в тексте. Но для чего он нужен?
Xobotun
30.08.2021 13:05+3У меня сложилось впечатление, что он как раз и задаёт, какую цифру показывать на индикаторе.
У всех этих пакетов есть отрицательный сигнал СИ в самом начале, потом череда тактовых импульсов. И один из этих тактовых импульсов доходит не до нуля, а "проваливается" вглубь на -3 вольта. И он устанавливает отображаемую цифру, насколько я понял.
Если что, я электроникой только в институте лет пять назад занимался, моим словам веры нет. Просто это интересно. :)
goodic
30.08.2021 13:09+3Как интересно. Они по сути просто экран на проводе. Думал, что они имеют собственные часы с дешевым тактовым генератором и по проводу только "подводятся".
ps на них можно вывести 99:99?
dlinyj Автор
30.08.2021 13:10+5Нет, это просто показометр. Можно даже дату показывать (нет ограничения, можно вывести 99:99:99).
Gengenid
30.08.2021 13:28+3А вообще грустно немного. Наверняка полная эксплуатационная документация со схемами, описаниями на эти часы хранится в еще бесчисленных бумажных архивах, но скорее всего никогда не будет оцифрована и скорее всего будет просто выброшена.
dlinyj Автор
30.08.2021 13:36+3На самом деле, если прям очень сильно захотеть, можно пройтись по библиотекам и найти много интересной информации, я так в Ленинке нашёл по моделям паровых двигателей просто сокровищницу. Но это надо очень-очень много свободного времени, либо потратить отпуск.
sim2q
30.08.2021 19:00+2Мы в Ленинке ещё будучи пионерами выискивали инфу по АОНу до того как они появились на МК. До18 одних ещё и не пускали тогда.
maxwolf
07.09.2021 23:28Зато пускали в филиалы ГП-НТБ, которых AFAIR в Москве было несколько, и где я нашёл книжку с описанием систем сигнализации телефонной связи (в т.ч. междугородней) :)
BootSector
30.08.2021 13:40+1Впечатляющая работа проделана! Ты бы сказал, что провод нужен для такого проекта, я бы как-нибудь побыстрее до тебя доехал) Впрочем, хорошо, что удалось выйти из положения.
dlinyj Автор
30.08.2021 13:48Спасибо!
Да ладно, не переживай. Тут просто хотелось новые найти, так чтобы сделать свой провод.
man_of_letters
30.08.2021 14:53+2Господи. ты чертов монстр, чертов монстр. Я же почти шутил, когда предлагал изнасиловать эти часы. Пост пока только пролистал, поэтому на правах деревяшки спрошу, а буквы писать можно?
dlinyj Автор
30.08.2021 15:23+1Господи. ты чертов монстр, чертов монстр.
Потупив взгляд в пол, скромно шаркаю ножкой.а буквы писать можно?
В рамках протокола, к сожалению только цифры, но если влезть в железо…
WinLin2
30.08.2021 16:19Подскажите, как начинающему. В электронном будильнике-приемнике "Scarlet" с горящим индикатором в разное время некоторые полоски цифровых индикаторов горят в половину накала или не загораются. Сами индикаторы точно полностью рабочие, так как полоски загораются все (в разное время). Пара таких часов и обоих со временем появился одинаковый дефект.
Dominikanez
30.08.2021 18:02+1Чтобы ответить на этот вопрос, надо знать ответ на другой: какой тип цифровых индикаторов применен в этом будильнике-приёмнике? Светодиодный, газоразрядный, вакуумно-люминесцентный, жидкокристаллический, на электронных чернилах?
usa_habro_user
30.08.2021 18:55-3Хороший пост, интересная работа. Но вы, видимо, не "гуглили" перед началом проекта? Буквально первый же результат поиска находит вот такие работы Сергея Фролова: вот тут и тут. В первом посте, кстати, есть и "разгадка" ИИ.
P.S. Кстати, на его видео часы показывают ярче и чётче, чем на вашем.
dlinyj Автор
30.08.2021 19:04+2Буквально первый же результат поиска находит вот такие работы Сергея Фролова: вот тут и тут.
А вы видимо не читали пост, раз мне советуете публикации на которые я ссылался трижды в посте, даже приводил цитаты из них.P.S. Кстати, на его видео часы показывают ярче и чётче, чем на вашем.
Об этом я тоже написал.usa_habro_user
30.08.2021 19:52-2Пост я прочел, но почему-то вылетело из головы, сорри. Еще смутила описанная вами "проблема с ИИ" - ведь Фролов, вроде-бы, достаточно подробно описал, как именно работает протокол.
NotebookKiller
31.08.2021 21:17+1Просто у Вас часы видимо прилично поработавшие, и индикаторы у них выгорели
sashakx
30.08.2021 20:17+1Вот что я понял из инструкции: на вторичных часах индикация динамическая, значит ни о каких паузах между пакетами не может быть и речи:
СИ - 50 Гц (0,020 сек) - отображение 6 индикаторов НН:ММ:ss, без видимого мерцания.
ТИ - 300 Гц (6 пачек - на каждый индикатор, поочередно загорается и гаснет)
частота импульсов в пачке - 3000 Гц (300*10 импульсов в пачке).
Схема информационного сигнала очень принципиальная (не точная).
third112
30.08.2021 22:08+1Школьные часы — особая песня. В начальной школе у нас были электромеханические часы в учительской: обычные напольные часы с гирями и маятником, но в маятнике магнит и по бокам в корпусе (натуральное дерево) две катушки. На все школьные часы с этих импульсы шли, но звонки наш технический работник тетя Женя руками из учительской подавала.
Позже появились бытовые часы-будильник с батарейкой, а механизм, кроме пружины (вместо моторчик) был обычный.
dlinyj Автор
31.08.2021 18:22Посмотрите этот тред: habr.com/ru/company/ruvds/blog/572312/#comment_23360032
vlad49
31.08.2021 01:43"Сергей не был готов делиться информацией", "не удалось уговорить продавца, чтобы я смог снять живые сигналы с его часов" - странные какие-то люди в роли собаки на старом сене. Охраняют тайну коммерческую что-ли :)
sfrolov
31.08.2021 08:32+1Вообще это печально. Стараешься, помогаешь, а про тебя такое пишут.
dlinyj Автор
31.08.2021 10:23Вы меня не совсем правильно поняли, вас спрашивали где-то в сообщениях вполне явно, вы ответили уклончиво. Из чего я сделал вывод, что информация закрытая. Возможно я ошибаюсь.
В любом случае, я невероятно вам благодарен за всю информацию, и подчёркиваю это.
devlev
31.08.2021 08:59+1Я конечно не такой гуру по части электронных компонентов для ардуино, даже асцилографа нет, но вот по части кода я нашел для себя несколько удобных иснтументов которые возможно в будущем могут пригодиться и вам.
Как то раз у меня возникла задача управлять обычным двигателем с энкодером так чтобы он прокручивался на определенное кол-во оборотов. На входе микроконтроллеру прилетали шаги энкодера, а на выходе микроконтроллер должен был щелкать релюшками двигателя. И я не знаю сколько бы вечностей ушло на отладку кода если бы я все отлаживал на реальном стенде.
И тут я понял что без класического подхода программирования, когда пишется тест, а потом под него пишется код тут просто не обойтесь. Так я открыл для себя VisualMicro - расширегие для Visual Studio. Из коробки можно создать проект который будет запускаться прямо на ардуино. Далее я создал отдельный проект библиотеку на СИ и отдельный проект для написания тестов.
После этого скорость разработки пошла с колосальной скоростью. Т.е. надо мне получить нужный порядок сигналов на выходе микроконтроллера, я пишу сначала тест, в котором описываю то что должно получиться а потом просто пишу нужный код. В самом коде библиотеки я не использую каких то ардуиновских штук, вроде дерганья пинов или прерываний. Это по сути абстракция над интерфейсом ардуино.
Все что должно работать с определенным интервалом - засовываю в таймер. Все что может выполняться должно - в главный цикл программы. Библиотека обертка по сути все это эмулирует.
Noatime
31.08.2021 10:24+1Имел дело с подобным протоколом, отрицательные импульсы формируют сигналы сброса/установки счётчиков, интересно было бы схему внутренностей посмотреть, но предполагаю напряжения 12 В многовато. Вот предположительная последовательность для формирования 01:23:45.
gaelellon
31.08.2021 12:16+1сразу вспомнилось как лет семь назад мне ну очень захотелось вывести время на дисплей видеомагнитофона сони, провозился неделю, когда разобрался, оказалось что протокол очень простой с контролем четности. вывел, до сих пор работают, радуют своим VFD.
а индикаторы похожи на просто неравномерно выгоревшие и программно это не лечится.
ilyawg
01.09.2021 19:36+1индикаторы похожи на просто неравномерно выгоревшие и программно это не лечится
Так оно и есть. Разбирал когда-то подобные часы. Индикаторы пришлось выбросить - они вот так вот светились даже просто при подаче напряжения.
Wan-Derer
05.09.2021 07:22Интересно. Правда немного странно видеть в одном тексте мысль об экономии ресурсов и digitalWrite(). Ардуиньи методы написаны универсально, подходят для всех возможных Ардуин, окружены многочисленными проверками и, как следствие, небыстры. Но фреймворк позволяет писать прямо в порт и это работает гораздо быстрее.
Ну и на правах оффтопа мой небольшой опыт формирования импульсов с помощью МК.
dlinyj Автор
05.09.2021 12:09У меня есть мысль всё переписать на си, но тогда потеряется прогресс на гите. Кстати, как обойти эти проверки и сразу писать в порт, ну кроме ассемблерных вставок?
Gengenid
05.09.2021 15:04+1А разве ардуино не позволяет напрямую в регистры портов писать? Типа PORTB=B00010000;
maxwolf
07.09.2021 23:34А жёлтая термоусадка хорошо косплеит повидавший виды бело-серый ПВХшный кембрик…
Gengenid
Я наверное что-то совсем неправильно понял, потому что мне эпюры сигналов настолько понятны, что я даже понять не могу, в чем тут может быть проблема.
dlinyj Автор
По эпюрам, расскажите мне где и зачем должен стоять ИИ? Почему перед ним идут импульсы и после него? Что означают эти импульсы, какой в них практический смысл?
Я спрашиваю без какого либо подкола, и допускаю что я не понимаю очевидные вещи.
Gengenid
ИИ идут в бите, после соответствующего такта ТИ. Грубо говоря идет СИ, нужное количество ТИ, потом на нужном значении, ИИ. Вроде как очень просто. Ну или я совсем неправильно понял.
Я единственное чего понять не могу, почему для разных разрядов разное количество ТИ.
dlinyj Автор
Вот, своими словами, объясните по этому графику, как передать время 00:00:00, если всё очевидно и понятно (самое простое время).
Gengenid
Ну как-то так наверное, хотя, это может и "1" на все разряды передать (или "9") надо пробовать.
dlinyj Автор
Не знаю, что за график сверху, но вы сейчас передаёте 99 часов.
Касательно импульсов, а почему так в эпюрах ИИ стоит где-то по середине, а у вас вначале?
Gengenid
Так положение ИИ и определяет, какая цифра передается.
На часы вообще сколько проводов идет, два или три? У Вас как-то не показано это.
dlinyj Автор
Хм… Возможно вы правы.
Xobotun
Согласен с @Gengenid, что положение ИИ между ТИ определяет цифру. :)
Я только не могу понять, как кодируется ноль (крайним импульсом или его отсутсвием) и с какой стороны этот крайний импульс должен быть (оно big-endian или little-endian, так сказать).
dlinyj Автор
Да это можно эмпирическим путём установить, но идея мне очень понравилась.
Gengenid
Если внимательно почитать паспорт, как я это сделал только сегодня, то там все написано
ИИ сбрасывает счетчик в ноль, то есть в разряд будет записано число, равное числу ТИ после ИИ.
dlinyj Автор
Да, вы абсолютно правы. Сегодня в ночи sfrolov прислал осциллограммы первичных часов, и полностью всё совпало с вашим предположением. Утром попробовал повторить, таки да! Оно работает!
dlinyj Автор
Вот, утром перед работой набросал, попробовал. Таки да, работает!
Тайминги пока неверные, есть ещё что править, но в целом да — это оно.
Gengenid
Круто, рад что получилось!
Gengenid
А как все-таки выходной каскад реализован? Просто подключены два провода к выходам моста? Ноль ведь плавающий получается тогда? Может там хотя бы резистор шунтирующий должен быть?
dlinyj Автор
Вот тут ничего не было, но были подтяжки к сигнальным линям и конденсаторы по питанию, справедливости ради, сигнал с L9110S был чище (осциллограммы в середине статьи). А вот с IR4427 более зашумлён. Но я не ставил никаких фильтрующих конденсаторов по питанию.
Xobotun
Мне кажется, что эти эпюры рисовал кто-то незнакомый с работой этих часов. :/
У десятков часов — девять ТИ, то есть восемь промежутков для ИИ. У единиц часов — десять ТИ. У десятков минут — восемь ТИ, у единиц — опять девять ТИ. У десятков секунд — восемь дырок для ИИ, но ТИ у них то ли восемь, то ли девять, ибо последний импульс состоит только из вертикальной палочки. У единиц секунд — опять девять ТИ.
Кажется разумным, чтобы их было девять или десять. Или чтобы у десятков минут их было пять-шесть, а у десятков часов — один-два ТИ вместо десяти. Действительно что-то непонятное.
Gengenid
Я не удивлюсь, если какому-то практиканту дали перерисовать каракули инженера и он без особого понимания, но аккуратно перерисовал в документацию.
dlinyj Автор
Либо инженер рисовал в день выдачи зарплаты ;).
degor
В тексте указано, что пачка ТИ состоит из 10 импульсов. Так что это художник так видит.