Управление соляриями из 1С через Arduino

01.10.20

Интеграция - Периферийные устройства

Мой опыт автоматизации сети соляриев с интеграцией 1С и оборудования соляриев с помощью платформы Arduino.

Хочу поделиться опытом интеграции 1С с мощным электронным оборудованием. 

Был у меня проект - внедрение конфигурации "Салон красоты" в сеть соляриев - 11 салонов. Клиент захотел чтобы администратор салона включал/выключал сами солярии (кабинки для загорания) из 1С. Ну и учёт и тарификацию времени работы солярия для клиента естественно.

Погуглив я остановился на платформе Arduino. По ней ОЧЕНЬ много материала в сети, на ютьюбе в частности. Язык программирования контроллера там не очень сложный подобный C++.

Это был мой первый опыт, но всё оказалось не так страшно. 

Как это работает.

1. Покупается самый простейший контроллер Арудино (можно даже китайскую подделку, не обязательно оригинальный итальянский).

2. Подключается по USB. Питание контроллера может осуществляться от USB, а может от внешнего источника. Разницы я не заметил, но рекомендуют от внешнего стабилизированного источника потому что при включении соляриев (а это 2-3 кВТ мощности) бывали скачки напряжения.

3. При подключении оригинального контроллера драйвер на Win 10 ставится автоматически. Для китайского клона нужно скачать драйвер и установить - ничего сложного. При этом эмулируется com-порт.

4. Далее через системную библиотеку работы с ком-портами MsCommLib.MsComm идёт работа с контроллером через COM-объект.

5. Для 64-битной Вин 10 для сом-объекта нужно сделать 64-битную обёртку (далее распишу как это делается) чтобы работать с 32-разрядной DLL

 

В 1С код выглядит так:

 

Функция ОткрытьКомПорт() Экспорт
	Попытка
		ComPort = Новый COMОбъект("MsCommLib.MsComm");    
	Исключение
		Если ЗадаватьВопросы Тогда
			Предупреждение("Ошибка создания COMОбъект MsCommLib.MsComm");
		КонецЕсли;
		КонтроллерПодключен = Ложь;
		Возврат Ложь;
	КонецПопытки;
	

	ComPort.CommPort        = НомерКомПорта;
	ComPort.Settings        = "9600,N,8,1";
	ComPort.RTSEnable 		= 1; 
	ComPort.Handshaking     = 0;
	ComPort.InBufferCount   = 0;
	ComPort.InBufferSize    = 0;
	ComPort.InputLen        = 0;
	ComPort.InputMode       = 1;  ////1 (массив байтов) ,по умолчанию 0 (текст)
	ComPort.NullDiscard     = 0;
	
	Попытка
		ComPort.PortOpen 			= 1;
		Возврат Истина
	Исключение
		Если ЗадаватьВопросы Тогда		
			Предупреждение("Ошибка открытия com-порта.");
		КонецЕсли;
		Возврат Ложь;
	КонецПопытки;
КонецФункции

Значения параметров подобраны экспериментально - путём проб и ошибок.

Дальше самое интересное - непосредственно чтение/запись в контроллер.

По обработке ожидания формы 1 раз в секунду происходит чтение и запись через com-объект:

 

Функция ОпроситьКнопки()
	Перем н;
		
	Если ComPort = Неопределено Тогда	 
		Возврат "";
	КонецЕсли; 
	
	Если НЕ КонтроллерПодключен Тогда	 
		Возврат "";
	КонецЕсли; 
	
	// 
	//добавлено для исключения ошибки контроллера
	Если ТипЗнч(ComPort) = Тип("COMОбъект") Тогда
		Data = ComPort.Input;
		Если ComPort.InputMode = 0 Тогда   // если режим "получение текста", а не массива байт	
	    	Возврат  Data;
		КонецЕсли;
	Иначе
		Возврат Неопределено;
	КонецЕсли;
	
	Всего = Data.GetLength(0);
	Если Всего = 0 Тогда
		Возврат "";
	КонецЕсли; 
	Мас = Новый Массив(Всего);
	Для н = 0 По Всего -1 Цикл
		Мас.Добавить(Data.GetValue(н));
	КонецЦикла; 
	
	Возврат ОбработатьРезультат(Мас);
КонецФункции // ОпроситьКнопки()

Дальше дело техники - обрабатываются значения массива Мас.

Что характерно - пока не добавил проверку переменно сом-объекта на равно Неопределено и проверки типа значения, часть точек - где-то процентов 30 жаловались на периодическое возникновение ошибки "сравнение недопустимых типов" при полном бездействии в 1С.

Сейчас всё работает стабильно и чётко.

Работает так:
1. Приходит клиент в солярий и заказывает х минут загара.

2. Оператор выбирает солярий из списка (на точке может быть до 4 разных - вертикальные, горизонтальные, разной мощности - каждый на своём канале от 1 до 4), задаёт количество минут и нажимает кнопку.

3. В этот момент солярий переходит из состояния "Остановлен" в состояние "Ожидание" и клиент идет в солярий раздеваться.

4. Когда клиент разделся, зашел или лег в кабинку - он нажимает кнопку "Старт" в солярии. Замыкание кнопки даёт команду контроллеру, который переводит солярий на данном канале в режим "Работа" и включаются лампы, вентиляторы и начинается отсчёт времени в 1С. Именно в 1С, а не в солярии. Отчет идёт через функцию Количество миллисекунд с полуночи(). Только так и никак иначе, потому что в противном случае кратковременные зависания и подтормаживания 1С искажают реальное время работы солярия.

Кроме того, в расчет времени добавлена задержка в 2-3 секунды на переходные процессы запуска. Подбирается экспериментально.

После того, как 1С отсчитала положенное время, она даёт команду контроллеру о том, что солярий на таком-то канале должен быть остановлен.

 

В общих чертах это всё. Если нужно подробности - пишите в комментарии, я дополню информацию.

 

Дальше привожу приблизительный код контроллера:

// статусы соляриев 0 - выкл., 1 - ожидание, 2 - работает
char Sol[4] = {'0','0','0','0'};    

// команда на изменение статуса соляриев считанная с Serial
char SolNew[4] = {'0','0','0','0'}; 

boolean pressed_buttons[4] = {HIGH, HIGH, HIGH, HIGH}; // сост. нажатия кнопок
boolean last_pressed_buttons[4] = {HIGH, HIGH, HIGH, HIGH}; // пред сост. нажатия кнопок
boolean change[4] = {LOW,LOW,LOW,LOW,}; // признак изменения состоян. нажатия кнопки

int printed = 0; // флаг для одноразового вывода ответной строки

// момент (millis) последнего изменения сост. соляриев
long time[4] = {0,0,0,0};                      

void setup() {
  Serial.begin(115200);
  pinMode(2, OUTPUT); // реле для солярия 1
  pinMode(3, OUTPUT); // реле для солярия 2
  pinMode(4, OUTPUT); // реле для солярия 3
  pinMode(5, OUTPUT); // реле для солярия 4
  
  pinMode(13, OUTPUT); // светодиод для отладки
  
  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  
  pinMode(6, INPUT_PULLUP); // опрос кнопки 1                   
  pinMode(7, INPUT_PULLUP); // опрос кнопки 1                   
  pinMode(8, INPUT_PULLUP); // опрос кнопки 1                   
  pinMode(9, INPUT_PULLUP); // опрос кнопки 1
}

void loop() {
  // ====================================
  // ~~~~~~~~~~~ Опрос кнопок ~~~~~~~~~~~
  while(Serial.available() == 0) {  // пока в порту ничего нет - опрашиваем кнопки
     for (int i = 0; i<4; i++) {         
      pressed_buttons[i] = digitalRead(6+i);      // запоминаем состояние кнопки
      change[i] = last_pressed_buttons[i] != pressed_buttons[i];      
      if (change[i] && pressed_buttons[i] == LOW) { // как только нажали
          if (millis() - time[i] > 5000) {
            switch (SolNew[i]) {
               case '1':
                  Sol[i] = '2';
                  SolNew[i] = '2';
                  digitalWrite(i+2,LOW);              
                  pressed_buttons[i] = HIGH;
                  time[i] = millis();
                  last_pressed_buttons[i] = pressed_buttons[i];
                  change[i] = LOW;                  
                  printed = 0;
                  break;
               case '2':
//                  Sol[i] = '1';
//                  SolNew[i] = '1';
//                  digitalWrite(i+2, HIGH);              
//                  pressed_buttons[i] = HIGH;
//                  time[i] = millis();
//                  last_pressed_buttons[i] = pressed_buttons[i];
//                  change[i] = LOW;
//                  printed = 0;
                break;          
            }
          }     // if (millis() - time[i] > 3000) {
        }     // if (change[i] && pressed_buttons[i] == LOW)
    }   // for (int i = 0; i <4; i++)
    printSerial();
  }   // while(Serial.available() == 0) 
  // ====================================
  
  
  // ====================================
  // ~~~~~~~~~~~ Опрос КОМ_порта ~~~~~~~~~~~
  delay(10);
  int i=0;
  while(Serial.available() > 0) 
  {
       SolNew[i] = Serial.read(); i++;
       printed = 0;
  }
  // ====================================

  // кнопки опросили, новые состояния соляриев из ком-порта считали
  proceedRelay();
  
}   // void loop()

void printSerial() {
  if (printed == 0) {
    String out = "";
    for (int i = 0; i <4; i++) {
      out = out + String(Sol[i]);  
    }
    //Serial.println(Sol);  
    Serial.println(out);   
    printed = 1;
  }
}

void proceedRelay() {           // Включить / выключить реле по массиву состояния соляриев
  for (int i=0; i < 4; i++)    // выходные порты с 2 по 5 включительно
  {
    switch (SolNew[i]) {
      case '0':              // выключение
        Sol[i] = '0';
        digitalWrite(i+2,HIGH);
        last_pressed_buttons[i] = pressed_buttons[i];
        change[i] = LOW;              
        break;
      case '1':              // установка режима ожидания
         if (pressed_buttons[i] == HIGH && last_pressed_buttons[i] == pressed_buttons[i]) {
            Sol[i] = '1';
            digitalWrite(i+2,HIGH);              
            last_pressed_buttons[i] = pressed_buttons[i];
            change[i] = LOW;              
            break;
          }
          else { // режим ожидания и кнопка ВКЛ.
            Sol[i] = '2';
            digitalWrite(i+2,LOW);              
            pressed_buttons[i] = HIGH;
            last_pressed_buttons[i] = pressed_buttons[i];
            change[i] = LOW;              
            break;
          }
       case '2':              // режим РАБОТЫ 
         if (pressed_buttons[i] == HIGH && last_pressed_buttons[i] == pressed_buttons[i]) { // И кнопка OFF
            Sol[i] = '2';
            //Serial.println('8');   
            digitalWrite(i+2,LOW);
            break;              
          }
          else { // режим РАБОТА и кнопка ВКЛ.            
//            Sol[i] = '1';
//            digitalWrite(i+2,HIGH);              
//            pressed_buttons[i] = HIGH;
//            last_pressed_buttons[i] = pressed_buttons[i];
//            change[i] = LOW;              
//            break;            
        }          
      } // switch (SolNew[i]) {
    } // for (int i=0; i < 4; i++)
  printSerial();
} 



Всё это работает сейчас на платформе 1С Предприятие 8.3.9.2170

Вызов 32-битных COM-объектов на стороне 64-битного сервера 1С

См. также

Распознавание номеров автомашин с ip - камер, видео, фото

Распознавание документов и образов Периферийные устройства Автомобили, автосервисы Россия Платные (руб)

Программа считывает кадры с ip-камер (http - запрос к камере), видео, фото (источники кадров (нет ограничения на их количество) настраивается в конфигурационном файле), находит и распознает номера автомашин и сохраняет в базу db, с сохранением фото номера и автомашины, а также времени детекции.

20400 руб.

31.05.2023    3809    2    1    

3

Получение изображения с веб-камеры с возможностью его кадрирования по произвольной области

Инструментарий разработчика Периферийные устройства Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

Внешняя обработка получения изображения с веб-камеры с возможностью его кадрирования по произвольно выделенной области. Использует собственную внешнюю компоненту на основе библиотеки AForge. Содержит примеры интерактивного взаимодействия с полем HTML.

20.03.2024    327    1    AndSem    1    

3

Прямая печать на принтерах TSC из 1С

Периферийные устройства Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

Прямая печать на принтерах TSC из 1С при вызове с сервера позволяет печатать из тонкого клиента, мобильного клиента и веб-клиента. Потребуется установка драйвера и библиотеки для отправки команд на этот драйвер.

1 стартмани

19.02.2024    536    3    realslavyan    0    

5

HotKeys на Python для 1С

Периферийные устройства Конфигурации 1cv8 Бесплатно (free)

Недавно прочитал статью на Инфостарте о KeyPad и вначале захотел себе такой, но через какое-то время я понял, что дополнительная даже маленькая клавиатура занимает место, и нужно все время держать ее под рукой. Это все создает дополнительные неудобства.

20.12.2023    4946    John_d    25    

70

Очистка очереди печати конкретного принтера

Периферийные устройства Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

Очистка очереди печати выбранного принтера, перезапуск службы печати, вывод списка системных принтеров, открытие свойств принтера из 1С.

1 стартмани

07.11.2023    1257    1    vsnazarov    1    

26

Печать этикеток на DYMO LabelManager 280 через DYMO Connect Web Service

Периферийные устройства WEB-интеграция Этикетки, ценники Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

На сайте производителя принтера DYMO LabelManager 280 вместе с драйвером поставляется пакет DYMO Connect, который предлагает функционал вёрстки этикеток в фирменном формате и отправки их напрямую на принтер. Так же в этом пакете есть веб-сервис для взаимодействия с принтером через HTTP-запросы, о котором и пойдет речь в этой статье.

29.08.2023    1460    GeraltSnow    0    

3

Второй монитор в качестве дисплея покупателя

Розничная торговля Периферийные устройства Платформа 1С v8.3 1С:Управление торговлей 11 Абонемент ($m)

Использование второго монитора в качестве дисплея покупателя. Выполнено в качестве расширения.

1 стартмани

02.02.2023    3194    25    windsurf    4    

5
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. muskul 02.10.20 04:05 Сейчас в теме
Сколько вы взяли за такую работу если не сикрет?
3. impextr 88 02.10.20 18:56 Сейчас в теме
(1) ну скажем так, заказчик был готов почасово оплатить мои НИОКР, а я в свою очередь отказывался от авторских прав на разработки. Компромисс такой.
Получилось достаточно дорого конечно, но система работает уже несколько лет на всей сети. Думаю всё отбилось уже.
С другой стороны у заказчика не было альтернативы - ничего подобного он не нашел. До 1С работали в какой-то жуткой самописке где управление соляриями происходило через LPT-порт и какие-то релюшки. Всё это глючило, очень плохо и медленно дорабатывалось, а с отмираем Windows XP перестали поддерживаться LPT на уровне операционки. Это и добило заказчика)
29. papami 55 08.01.21 10:21 Сейчас в теме
(3)
Подскажите, а авторские права на что именно? Что является разработкой здесь?
Или просто имеется в виду, что это не будет ставиться конкурентам, если будет аналогичная задача?
30. impextr 88 11.01.21 20:30 Сейчас в теме
(29) в плане прав владения интеллектуальной собственностью - если вдруг я захочу продавать эту систему как тиражируемую
31. papami 55 11.01.21 20:57 Сейчас в теме
(30) По договоренностям ясно. Просто получается, что Вы тут все рассказали в подробностях). В любом случае, это пока единственное Практическое применение связки с Ардуино из того, что коллеги публиковали на ИС.
32. FB_3986935191342576 19.05.21 12:59 Сейчас в теме
(3)здравствуйте) как можно с вами связаться ? Как раз ищем специалиста по данному внедрению
33. пользователь 21.05.21 09:56
Сообщение было скрыто модератором.
...
2. ipoloskov 162 02.10.20 05:55 Сейчас в теме
Как опыт интеграции, интересно, но можно вопрос - зачем контролировать время из 1С? Это просто опасно - компьютер может зависнуть, и клиент получит ожоги.
4. impextr 88 02.10.20 18:59 Сейчас в теме
(2) там было много аргументов, все уже не вспомню. Ну, как минимум:
1) чтобы администратор салона мог из 1С остановить солярий
2) в случае досрочного прекращения процедуры корректно тарифицировалось время работы солярия.

На счёт опасно - верное замечание, поэтому код контроллера был доработан таким образом что если вдруг из 1С переставали поступать управляющие сигналы, то солярий дорабатывал заданное время и отключался.
ipoloskov; +1 Ответить
5. BobNN 02.10.20 20:49 Сейчас в теме
Не соображу, Ардуина одна возле компа? Она воткнута в USB, и управляет припаянным к ней ком-портом, в который заведены всё кабинки??
Или возле каждой кабинки своя Ардуина?
Картинка-схемка бы всё прояснила.
Очень интересное, а главное, практичное применение контроллера.
6. impextr 88 02.10.20 21:34 Сейчас в теме
(5) Да там всё предельно просто. Контроллер подключен к компу через USB. Контролер управляет четырьмя реле на 10 А. А те уже в свою очередь включают/выключают весь солярий. Кнопка "Старт/Стоп" заведена из солярия к контроллеру просто как замыкающийся/размыкающийся контакт, который опрашивает контроллер.
Вот и вся схема.

Вывод такой что в принципе любой железкой можно управлять из 1С и опрашивать что угодно тоже из 1С. Встречал решение - конфигурация для управления школой, где через Ардуино включается / выключается школьный звонок.
7. BobNN 02.10.20 22:49 Сейчас в теме
(6)
А, теперь понятно, спасибо!
(остался ещё вопрос о длине проводов или о применении беспроводных реле, но это уже тонкости)
19. TitanLuchs 395 08.10.20 19:38 Сейчас в теме
(7) Беспроводное реле - это аналог Ардуино с WiFi на борту. Например, Wemos Lolin d1 r2, К ним продаются реле в виде шилда. Минимум проводов, и, соответственно, возможных глюков, а главное - устранение привязки с сом-порту со всеми его глюками.
8. impextr 88 03.10.20 13:03 Сейчас в теме
Использовался самый простой и дешевый контроллер
Arduino UNO R3 (CH340)

Контроллер

Реле вот такие 4-канальные на 10 А 12 В:


Реле
11. Dmitri93 12 08.10.20 10:35 Сейчас в теме
(8) а контакты реле не подгорают от такой мощности? Возможно, лучше бы использовать твердотельные в таком случае.
14. impextr 88 08.10.20 15:24 Сейчас в теме
(11) там на самом деле система много контурная, дальше уже штатный электронщик "шаманил". На сколько я знаю реле Ардуино включает следующее реле, а то уже в свою очередь всю систему.
9. anton.fly7 173 07.10.20 19:25 Сейчас в теме
не было ситуации что COM порт был "занят", помню со сканерами была такая проблема (давно), что пока комп не перегрузишь COM не освобождался

на ESP32 можно через WiFi сделать :) провод от контроллера до компа не нужен, и возможно рулить вообще всеми релешками с единого сервера
10. lmnlmn 69 07.10.20 22:16 Сейчас в теме
Круто, но моя практика показала что Ардуина может зависать. Вовсе даже не из-за ошибок в скетче. Случается нечасто, но полагаться на бесперебойную работу нельзя. Воткните вторую Ардуину на мониторинг или как watchdog чтоб куриц гриль не наделать из посетителей, в случае если контроллер зависнет и администатор в телефоне пропадет.
torbeev; Dmitri93; +2 Ответить
20. TitanLuchs 395 08.10.20 19:41 Сейчас в теме
(10) В Arduino UNO есть встроенный watchdog, при зависании он ее перезагружает на аппаратном уровне. Вторая ардуина не нужна, ее работоспособное состояние может мониторить 1С.
25. lmnlmn 69 08.10.20 23:46 Сейчас в теме
(20) Надеюсь что UNO не превращается в кирпич если заиграться с watchdog. Не проверял. А мониторинг надо после реле цеплять. Мало ли контакты залипнут.
27. TitanLuchs 395 09.10.20 15:30 Сейчас в теме
(25) А там заиграться ИМХО вряд ли получится. Это же штатный функционал.
12. viollan 08.10.20 12:38 Сейчас в теме
Можно было гораздо проще и надежнее сделать.
Берем контроллер, например такой https://ab-log.ru/smart-house/ethernet/megad-2561
Управляется простыми GET/POST запросами вида: http://IPАдрес/megad.php?pt=2
Крепится на DIN рейку питается от 12В. Аккуратно, надежно, с обратной связью, управление из любой точки мира при правильной настройке.
torbeev; Legavaz; Sedaiko; +3 Ответить
13. Sedaiko 572 08.10.20 13:41 Сейчас в теме
(12) Поддерживаю. Зачем юзать COM порты, когда уже куча устройств с управлением по HTTP, с которым платформа работает "из коробки"
Мне больше вкатывает эти модули http://kernelchip.ru/
15. impextr 88 08.10.20 15:41 Сейчас в теме
(13) Отлично, но об этих решениях нужно было знать на момент принятия решения о платформе. Я о них не знал.
Проблемы с подключением по USB не было, поэтому не стали ничего дальше искать.
Кроме того, думаю что управление по HTTP тоже не панацея и не идеал, и тоже может глючить.
22. TitanLuchs 395 08.10.20 19:45 Сейчас в теме
(15) Как показывает практика, управление по HTTP в подобных случаях работает на порядки надежнее, так что в следующий раз лучше использовать его.
16. impextr 88 08.10.20 15:44 Сейчас в теме
(12) Спасибо за наводку. Интересная инфа, буду иметь в виду на будущее. А в чём повышенная надежность по сравнению с USB? Как по мне, то роутер может точно так же зависнуть, да и сам контроллер - не думаю что там прям авиационная надежность.
Моё решение клиент использует уже года 3 и не жалуется. Значит оно его устраивает, верно?
17. viollan 08.10.20 18:30 Сейчас в теме
(16) Я не критикую Ваше решение. Как показало время имеет место быть и решает задачи бизнеса.
Какие аргументы для меня:
+ Крепление на DIN-Рейку в щитке (Крепление/Контакты/Меньше вероятность нечаянно зацепить) при условии правильного монтажа
+ Используются симисторы или реле повышенной надежности (зависит от выбранных модулей)
+ Простые HTTP/S запросы из коробки
- Все Ardunio/Rasberi и подобные имеют привычку убивать SD-карту
Есть еще поддержка MQTT и много другое, но это вне контекста описываемой задачи.
23. TitanLuchs 395 08.10.20 19:49 Сейчас в теме
(16) Работа через http не всегда подразумевает коннект через роутер, можно соединиться напрямую витой парой через ethernet-порт. Но теперь взаимодействие идет не через COM-порт, который в 1С довольно капризный, а через http-запросы, которые сильно более отказоустойчивы.
21. TitanLuchs 395 08.10.20 19:44 Сейчас в теме
(12) Не надо брать такую мегу за 12999 рублей. За эти деньги можно взять 65 штук ESP с вайфайем на борту и теми же возможностями.
24. impextr 88 08.10.20 19:50 Сейчас в теме
(21) кстати да, Ардуино простейшие стоили $5 и работают
26. viollan 09.10.20 07:05 Сейчас в теме
(21)
Контролер MegaD-2561 - 3850 руб.
Исполнительный модуль MegaD-8I7O-R - 3520 руб. (если много портов, тогда MegaD-2R - 1420 руб.)
Итого = 7370 руб.

Но разница в цене аппаратной части по сравнению с затраченным временем и стоимостью работ больше в разы
28. TitanLuchs 395 09.10.20 15:32 Сейчас в теме
(26) Да не нужно там настолько времени, готовых библиотек полно.
18. viollan 08.10.20 19:07 Сейчас в теме
Пушка для воробьев автоматизации и пром. надежность:
https://www.beckhoff.ru/ru/default.htm?beckhoff/products.htm
Оставьте свое сообщение