Чего только не придумывают люди сидящие в заточении самоизоляции! Одно радует, подопечные с работы меньше достают, и есть время позаниматься любимым хобби. Я радиолюбитель с пеленок, и даже позывной есть R6DCZ. Иногда грею ионосферу передатчиком в 1,0кВт, за что имею разные разговоры с инспекцией по электросвязи. Ну да ладно... мелкие шалости. Так вот... нарисовалась задача исследовать амплитудно-частотную характеристику некоторых узлов, которые я сконструировал для очередного приемника. Раньше (при СССР) был доступ к любой измерительной аппаратуре и проблем не было. В настоящее же время приходится выкручиваться всякими подручными средствами купленные по случаю у китайцев на Али или на радиорынках. Исследовать АЧХ нам поможет эквивалент измерительного прибора Х1-47 собранный на коленках из Ардуины, модуля синтезатора частот на AD9850, небольшой обвески из дискретных компонентов и, конечно же, обработка на 1С!
Приступим
Осуществим сборку "прибора" согласно принципиальной схемы.
У меня получилось на монтажной доске вот такое изделие
Черная коробочка рядом с доской - это логический анализатор DSLogic. Классная вещь для хака различных протоколов обмена. При помощи него удалось подобрать специфические параметры для стабильного обмена 1С с ардуинкой. Но это позже.
Ищем Arduino IDE, и загружаем скетч в Ардуино.
#define W_CLK 13 //Тактирование AD9850
#define FQ_UD 10 //Запуск AD9850
#define DATA 11 //Данные установки частоты
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); } //Строб импульс
#define INP_VAL A0 //Выход исследуемой цепи (детектор)
#define INP_OUT A1 //Вход исследуемой цепи (выход генератора)
long freq = 3500000; //Частота по умолчанию 3,5 МГц
String serial_readline = "";
const int bSize = 64; //Длина буфера
char Buffer[bSize]; //Буфер приема данных RS232
float vin = 0;
float vout = 0;
float ratio = 0; //Коэфф. передачи исследуемой цепи
void setup()
{
pinMode(FQ_UD, OUTPUT);
pinMode(W_CLK, OUTPUT);
pinMode(DATA, OUTPUT);
sendFrequency(freq);
Serial.begin(115200); //Настройка COM порта
Serial.setTimeout(100);
}
//Главный цикл
void loop()
{
while (Serial.available() > 0)
{
memset(Buffer, 0, bSize);
Serial.readBytesUntil('\n',Buffer, bSize);
serial_readline = String(Buffer);
if (serial_readline.startsWith("GET "))
{
long fr_Start = (long)serial_readline.substring(4, 14).toFloat();
long fr_End = (long)serial_readline.substring(15, 24).toFloat();
long fr_Step = (long)serial_readline.substring(25).toFloat();
for (freq = fr_Start; freq <= fr_End; freq += fr_Step)
{
sendFrequency(freq);
delay(2);
readInVoltage();
String freq_str = "000000000" + String(freq) + " ";
String out_str = freq_str.substring(freq_str.length() - 10) + String(ratio, 6);
Serial.println(out_str);
}
}
Serial.flush();
}
}
//Измерения
void readInVoltage()
{
vin = 0;
vout = 0;
ratio = 0;
for (int i = 0; i < 16; i++)
{
vin = vin + ((float)analogRead(INP_VAL) / 1023 * 5);
vout = vout + ((float)analogRead(INP_OUT) / 1023 * 5);
}
vin = vin / 16;
vout = vout / 16;
ratio = vin / vout;
}
// Обслуживание AD9850
void tfr_byte(byte data)
{
for (int i = 0; i < 8; i++, data >>= 1) {
digitalWrite(DATA, data & 0x01);
pulseHigh(W_CLK);
}
}
void sendFrequency(double frequency) {
int32_t freq = frequency * 4294967295 / 125000000;
for (int b = 0; b < 4; b++, freq >>= 8) {
tfr_byte(freq & 0xFF);
}
tfr_byte(0x000);
pulseHigh(FQ_UD);
}
С железом закончили. Займёмся 1С
Готовую к использованию обработку я выкладывать в виде отдельного файла не буду. Опубликую только код. Там все понятно. В конфигураторе нарисуем форму вот такого вида
В модуле формы запишем следующий код
Перем КомПорт,Серия,Ответ;
Процедура ОсновныеДействияФормыОсновныеДействияФормыВыполнить(Кнопка)
Команда = "GET ";
Команда = Команда + Прав("000000000" + Старт, 9)+" ";
Команда = Команда + Прав("000000000" + Стоп, 9)+" ";
Команда = Команда + Прав("000000000" + Шаг, 9)+Символы.ПС;
Если (КомПорт.PortOpen=1) Тогда
ЭлементыФормы.Диаграмма1.Очистить();
Итераций = Цел((Число(Стоп)-Число(Старт))/Число(Шаг));
//0.01 - магическое число, без него не работает
Интервал = Цел(Итераций*0.01)+1;
Ответ = Новый Массив;
КомПорт.Output=Команда;
ПодключитьОбработчикОжидания("Отрисовать", Интервал, Истина);
Иначе
Сообщить("Порт не открыт!");
КонецЕсли;
КонецПроцедуры
Процедура ПолучитьДанные()
Ответ.Добавить(Компорт.Input);
КонецПроцедуры
Процедура Отрисовать()
Если (Ответ.Количество()>0) Тогда
ТекстФ = Новый ТекстовыйДокумент;
Для Каждого Стр_Ответ Из Ответ Цикл
ТекстФ.ДобавитьСтроку(Стр_Ответ);
КонецЦикла;
Для Индекс = 1 По ТекстФ.КоличествоСтрок() Цикл
Текст = ТекстФ.ПолучитьСтроку(Индекс);
Если СокрЛП(Текст)="" Тогда
Продолжить;
КонецЕсли;
Точка = ЭлементыФормы.Диаграмма1.УстановитьТочку(Число(Лев(ТекстФ.ПолучитьСтроку(Индекс),9)));
Серия = ЭлементыФормы.Диаграмма1.УстановитьСерию("Kp");
Попытка
Если Линейная Тогда
ЭлементыФормы.Диаграмма1.УстановитьЗначение(Точка,Серия,Число(Прав(ТекстФ.ПолучитьСтроку(Индекс),8)));
Иначе
ЭлементыФормы.Диаграмма1.УстановитьЗначение(Точка,Серия,20*log10(Число(Прав(ТекстФ.ПолучитьСтроку(Индекс),8))));
КонецЕсли;
Исключение
Сообщить(Текст);
КонецПопытки;
КонецЦикла;
ЭлементыФормы.Диаграмма1.Обновление = Истина;
Иначе
Сообщить("Нет данных!");
КонецЕсли;
КонецПроцедуры
Процедура Кнопка1Нажатие(Элемент)
ТекущееВремя = ТекущаяУниверсальнаяДатаВМиллисекундах();
Если (КомПорт.PortOpen=1) Тогда
КомПорт.PortOpen=0;
ЭлементыФормы.Кнопка1.Заголовок = "Connect";
Иначе
КомПорт.CommPort = НомерПорта;
КомПорт.Settings = СтрокаИни;
КомПорт.RThreshold = 20;//Количество символов в ответе
КомПорт.Handshaking = 1;
КомПорт.PortOpen = 1;
ЭлементыФормы.Кнопка1.Заголовок = "Disconnect";
КонецЕсли;
Пока (ТекущаяУниверсальнаяДатаВМиллисекундах()-ТекущееВремя < 2000) Цикл
//Ожидаем около 2 сек для открытия/закрытия канала передачи данных
КонецЦикла;
КонецПроцедуры
Процедура ПриЗакрытии()
Если (КомПорт.PortOpen=1) Тогда
КомПорт.PortOpen=0;
Компорт="";
КонецЕсли;
КонецПроцедуры
//Значения по умолчанию
НомерПорта = 12;
СтрокаИни = "115200,N,8,1";
Старт = "400000";
Стоп = "500000";
Шаг = "250";
//Инициализация
КомПорт=Новый COMОбъект("MsCommLib.MsComm.1");
ДобавитьОбработчик КомПорт.OnComm,ПолучитьДанные;
Здесь необходимы некоторые пояснения. Как известно MSCommControl - крайне капризная штука, особенно когда работает с виртуальным COMM портом, созданным USB соединением. Да и проинсталировать эту компоненту на современные 64bit ОС - это отдельная песня. На Инфостарте эту проблему уже обсуждали. У меня резонный вопрос к разработчикам платформы 1С - Что, за 20 лет развития, не хватило сил для реализации встроенных объектов для управления сокетами и портами на уровне платформы? Т.е. для мобильной "Телефонию" запилили , а для десктопа?
По поводу свойства компоненты RThreshold. Туда пишется число полученных байт, при достижении которых сработает событие onComm. Благодаря анализатору стало понятно сколько вешать в граммах.
Магическое число в 10 ms вычислил там же. Оно необходимо для запуска обработчика ожидания. Интервал ожидания взял с запасом плюс 1 секунда.
Ну и полученный результат измерения АЧХ, точнее коэффициента передачи в полосе частот, колебательного контура на 465 кГц в линейном и логарифмическом масштабе. На картинках виден резонанс. Именно этого я и добивался.
Глядя на картинки напрашивается какой нибудь цифровой фильтр чтобы сгладить шум в измерениях. Но это другая история.
Пожалуй все.Благодарю за внимание.
Будут вопросы,отвечу.
Upd1: На управляемой форме, качаем бесплатно :)
Upd2: от 06.05.2020 - про сеть
Я обещал читателю event-driven networking с 1С и Ардуинкой. Получите... распишитесь... Не забываем плюсики на статью вешать. Не жалко же :) , я надеюсь...
Исходные данные таковы. Имеем плату MEGA2560, ethernet шилд на базе W5100 и комнатный датчик DHT11. Выглядит вот так:
Вместо Меги можно Леонардо или УНО R3 задействовать. Без разницы. Можно и Нано, только тогда монтажными перемычками нужно все правильно соединить. Маленький лайфхак по поводу эзернет шилда. Иногда китайцы не те номиналы паяют на платы. Внимательно смотрите сюда:
Если у Вас резисторная сборка такого номинала, придется поработать с паяльником. Если номинал 510 - ничего не делаем.
Найдите пару резисторов с номиналом 100 ом и напаяйте таким образом. Сделайте это аккуратно, без соплей и коротышей.
В результате этой процедуры получите устойчивую работу шилда с любым сетевым оборудованием.
Это квинтэссенция штатных примеров из Arduino IDE. Для нашего эксперимента сойдет. Ну и займемся обработкой на 1С. Обычная форма, толстый клиент. На УФ тоже работать должно, я не проверял.
Рисуем такую форму:
Код модуля формы, тут все понятно :
Перем НетСокет,Start;
Процедура ДанныеПришли(bytes)
buff="";
НетСокет.GetData(buff);
Incoming = Incoming+buff;
КонецПроцедуры
Процедура Кнопка1Нажатие(Элемент)
Если НетСокет.State=0 Тогда
НетСокет.RemoteHost = СокрЛП(host);
НетСокет.RemotePort = СокрЛП(port);
НетСокет.Protocol = 0; //TCP
НетСокет.Connect();
Incoming="";
ЭлементыФормы.Кнопка1.Заголовок="Disconnect";
Иначе
НетСокет.Close();
Start=Ложь;
ЭлементыФормы.Кнопка1.Заголовок="Connect";
КонецЕсли;
КонецПроцедуры
Процедура ПоказатьСтатус()
Если НетСокет.State=0 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Connection closed...";
ИначеЕсли НетСокет.State=1 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Connection open...";
ИначеЕсли НетСокет.State=2 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Listening for incoming connections...";
ИначеЕсли НетСокет.State=3 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Connection pending...";
ИначеЕсли НетСокет.State=4 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Resolving remote host name...";
ИначеЕсли НетСокет.State=5 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Remote host name successfully resolved...";
ИначеЕсли НетСокет.State=6 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Connecting to remote host...";
ИначеЕсли НетСокет.State=7 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Connected to remote host...";
ИначеЕсли НетСокет.State=8 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Connection is closing...";
ИначеЕсли НетСокет.State=9 Тогда
ЭлементыФормы.Надпись3.Заголовок="State:Error occured...";
КонецЕсли;
Если (НЕ Start) И (НетСокет.State = 7) Тогда
Start = Истина;
НетСокет.SendData("Start"+Символы.ВК+Символы.ПС);
КонецЕсли;
КонецПроцедуры
НетСокет=Новый COMОбъект("MSWinsock.Winsock.1");
ДобавитьОбработчик НетСокет.DataArrival,ДанныеПришли;
ПодключитьОбработчикОжидания("ПоказатьСтатус", 1, Ложь);
host="192.168.100.24";
port="23";
Start=Ложь;
Ну и результат работы без всяких HTTP,WEB и прочих заморочек
По поводу регистрации древних компонентов в 64bit ОС нашел кино на ресурсе ютуб. Смотрим, кто не видел.
На сайте производителя принтера DYMO LabelManager 280 вместе с драйвером поставляется пакет DYMO Connect, который предлагает функционал вёрстки этикеток в фирменном формате и отправки их напрямую на принтер. Так же в этом пакете есть веб-сервис для взаимодействия с принтером через HTTP-запросы, о котором и пойдет речь в этой статье.
Кто сказал, что умный дом на 1С сделать невозможно? На конференции Infostart Event 2021 Moscow Premiere Юрий Лазаренко из компании «Цифровой Кот» показал, какие уникальные прикольные вещи можно делать на базе IoT (интернета вещей), где в этом всем 1С, и как это все между собой интегрируется.
Программа считывает кадры с ip-камер (http - запрос к камере), видео, фото (источники кадров (нет ограничения на их количество) настраивается в конфигурационном файле), находит и распознает номера автомашин и сохраняет в базу db, с сохранением фото номера и автомашины, а также времени детекции.
Хотите попробовать свои силы в разработке собственного мобильного приложения на 1С для управления светом и электроприборами в своём доме?
Добро пожаловать! Хочу поделиться собственными наработками в этой области.
Это будет приложение, разработанное для мобильных устройств на базе Android. Основное предназначение: управление включением/выключением устройств, работающих от сети 220 V (свет, телевизор, чайник, вентилятор, микроволновка и т.д.). Управлять будем: из приложения, голосом, на заданный промежуток времени, интенсивностью света, расписанием работы.
Организация потокового обмена системы 1С с большим количеством разнородных устройств – нетривиальная задача. О том, как организовать архитектуру такого решения с учетом возможного масштабирования хранимых данных и поддерживаемых интерфейсов, на конференции Infostart Event 2021 Post-Apocalypse рассказал TeamLead и специалист по внедрению компании ИнфоСофт Григорий Шатров.
Настало время, что можно ставить + если человек не пожрдничал и не выложил статью в духе "я тут накидал, короче, во вложении".
А вам плюс, что статья не только про 1с и админство
Там, где стоило бы использовать бесплатный питончик, люди используют старые и добрые обычные формы. С другой стороны, не было бы статьи на Инфостарте, а была бы на Хабре )))
(2) На УФ не взлетело. Нет возможности передать в обработчик ПолучитьДанные(), onComm то бишь, ссылку на КомПорт. Ограничение управляемых форм. Про питончик ничего не скажу... не пробовал :)
(6) Запятая не проставилась. 1,0 кВт - разрешенная мощность для 1 и 2 категории. 10 кВт не сложно сделать по двухтактной схеме с заземленными сетками. 6-8 ламп в параллель, и будет счастье. Правда у соседей утюги петь начинают :). Ко мне претензии предъявляли из за жалоб соседей.
Тоже недавно небольшой проект делал на arduino для мониторинга серверной. Никак не найду времени написать статью про это, может будет интересно кому-нибудь.
Железки лучше в Zabbix/Icinga мониторить. Arduino в формате json может отдавать ответ, а zabbix у себя собирать, визуализировать и оповещать.
(10) Мы пойдем другим путем! Ближе к полуночи будет расширение этой публикации, или новая заметка про event-driven networking 1С+Ардуино. Может кому пригодится.
Я лет 5 назад выиграл в споре бутылку текилы, температуру через Ардуино в регистр сведений писал. Вообще для автоматизации производства интересная возможность.
(12)Возможность конечно интересная... Но есть нюансы. Применить Ардуинку вместо промышленного ПЛК можно, но не всегда и не везде. Есть процессы повышенной опасности. Туда оборудование без сертификации не установишь. Есть жесткие условия эксплуатации. Там, без дополнительной схемотехнической обвязки Ардуинки не прославишься. Нужно решать вопросы помехозащищенности, гальвано-опто-развязки и так далее. Самый примитивный пример это Промдуино.