1C + Arduino + сканер отпечатков пальцев + RFID считыватель










Связываем 1C, Arduino, сканер отпечатков пальцев и RFID считыватель для системы учёта рабочего времени или пропускной системы.

Что нужно

 

  1. Модуль отпечатков пальцев FPM10A
  2. RFID-модуль RC522
  3. Arduino mega (теоретически можно использовать и другие платы но я остановился на данной из-за количества выводов)
  4. 1 лицензия на 1С 8.2 (толстый клиент в моём случае, под тонкий пилите сами)
  5. Связь по Com порту с помощью MsCommLib.MsComm (нужна лицензия, ягуглится даже тут)
  6. Среда разработки для ардуино (использована 1.8.5)
  7. Планшет с USB интерфейсом.
  8. Обвязка: Резистор 1 Кило ОМ, кнопка на замыкание, проводочки, "синяя" изолента, терморектальный крипоанализатор по желанию (можно скрутить проводочки если с данным прибором вас связывают тесные непередаваемые ощущения), USB кабель для ардуиино, прямые руки и кривые извилины среднестатистического 1с ника в т.ч. для изготовления корпуса для всего этого чуда.

Примечания: на фото цвета проводов разнятся — в процессе монтажа порвал несколько проводов т.к. они были совсем Huawei и пришлось брать других доступных цветов.

Система сообщений дублируется в критических моментах специально.
Сразу предупреждаю что может у среднестатистического инженера могут потечь слезы из глаз из канифоли но это мой вообще первый Ардуино проект да еще и такой сложности и вроде оно работает и работает стабильно. Сначала была идея сделать всё через сеть (wifi + проводная) но прикинув затраты на отладку и создание своего http сервиса и внедрение всё в 1с я решил использовать com, в любом случае всю логику можно без изменения конфы вынести во внешнюю обработку.

Можно ещё вставить систему фотографирования входящего сотрудника через web камеру планшета, добавить реле и управлять электронными воротами, допилить интеграцию с ЗУП через внешнюю обработку, передаваемую через параметры запуска и аннигиляцию масленницы для особо опасных проходных секретной важности ).

Полезная критика приветствуется.

Пролог

Видя цены на существующие пропусные системы и системы учета времени меня медленно начала душить зеленая сущность. Долго ходив около ардуинки и её модулей наткнулся на модуль отпечатков пальцев FPM10A. Данный модуль в зависимости от версии может запоминать большое количество отпечатков пальцев — от 50 до бесконечности её флеш памяти и используется в большинстве модулей производителей биометрического контроля. Однако в моём проекте из-за библиотеки оно ограниченно 254. Сразу предупреждаю что выкладываю свою измученно-найденную библиотеку для ардуино т.к. долго мучался с поиском и угробил 3 дня на поиски и отладку библиотеки для данного модуля.

 

Описание модулей

 

Библиотека, использованная в проекте позволяет использовать до 256 (byte) отпечатков пальцев. Мне это количество было избыточным, в крайнем случае можно использовать по 1 модулю на каждых 256 сотрудников.
Количество RFID меток ограниченно лишь уникальностью их UID т.к. база может хранится в 1С и привязанна к сотрудникам. Метки можно использовать все совместимые. Теоретически могут подходить всякие ключи от домофонов, карты метро и карты тройка.
Соединение с 1с идёт по com порту через библиотеку MsCommLib.MsComm но можно переписать под любую другую. Драйвера для com порта для Ардуинки должны ставится вместе со средой разработки ардуино но так же ягуглятся.
Всё спаенное прячется в коробку, связывается по сети (я использовал WiFi но можно и внешнюю USB сетевую карту использовать).

Алгоритм работы

Аппаратно:

  1. Модули ардуино спаиваем/скручиваем
  2. Подключаем к ПК-программатору и заливаем прошивку в арду, запускаем тест, убеждаемся в работоспособности команд
  3. Через USB соединяются с планшетом на Windows 10. На планшете заменяем либо через автозагрузку:

А) через батник:

  • пуск — выполнить: shell:startup

  • создаем там через "блокнот" файл с именем hz.bat и содержанием (уверен что сами справитесь с параметрами файловой базы — у меня sql): "C:Program Files1cv8 … in1cv8.exe" ENTERPRISE /SServerName:PortDBName" /NUser /PPassword

Б) более совершенный через замену шелла делаем через VB script (обязательно создайте кроме пользователя по умолчанию другого без запуска шелла):

  • создаем через "блокнот" файл с именем C:hzhz.vbs и содержанием

set oShell=createobject("wscript.shell") 
sCmd="""C:Program Files1cv8 … in1cv8.exe"" ENTERPRISE /SServerName:PortDBName" /NUser /PPassword"
oShell.run sCmd,,true
sCmd="shutdown /r /t 0" 
oShell.run sCmd

  • пуск — выполнить: regedit, идём по ветке: Current UserSoftwareMicrosoftWindows NTCurrentVersionWinlogon

  • добавляем строковый параметр "Shell" (REG_SZ)

  • редактируем его: "wscript C:hzhz.vbs" (без кавычек в параметре)

  • ребут и тест. 1с должна запускаться без explorera

  1. Далее убеждаемся в работоспособности и упаковываем в коробку

 

Программно:

  1. В обычном состоянии ардуино опрашивает сканер отпечатков пальцев, RFID сканер, кнопку администрирования и посылает по com порту команды ожидания.
  2. Как только в поле зрения считывателей появляется палец посылаем команду в com порт и 1с видит либо ID пальца, либо UID метки через чтение переменных.
  3. Кнопка нужна для администирования отпечатков. При её нажатии 1с опрашивает пароль-логин и дальше может присвоить сотруднику либо ID сканера либо UID карты через систему сообщений.

Для связи с 1с используется следующие строки (обработку я делал для своей конфы и своего табеля, она в проекте просто для примера но включена в исходники):

Подключение к com порту

Процедура СтартСистемы()
ComPort = Новый COMОбъект("MsCommLib.MsComm");
Попытка
ComPort.CommPort        = 3;
ComPort.Settings        = "9600,N,8,1";
ComPort.Handshaking     = 0;
ComPort.InBufferCount   = 0;
ComPort.InBufferSize    = 70;
ComPort.InputLen        = 0;
ComPort.InputMode       = 1;
ComPort.NullDiscard     = 0;
ComPort.PortOpen        = Истина;
Исключение
Предупреждение("Не возможно открыть порт!");
ЭтаФорма.Закрыть();
КонецПопытки;

чСекунд = 0;
ПодключитьОбработчикОжидания("ВывестиДанныеСПорта", 1, Ложь); // Подключим обработчик для мониторинга порта
КонецПроцедуры

Отключение от com порта

Процедура КонецСистемы()
ОтключитьОбработчикОжидания("ВывестиДанныеСПорта");
ComPort.PortOpen            = Ложь;
ComPort                     = "";
КонецПроцедуры

Считывание данных с com порта

Процедура ВывестиДанныеСПорта() Экспорт
ДанныеСПорта = "";
Если ComPort.PortOpen Тогда
//ComPort.Output = "1";
ДанныеСПорта = ComPort.Input;
ОбработатьЗашифрованнуюСтроку(ДанныеСПорта);

Если СокрЛП(ПредСотрудник) <> "" Тогда
чСекунд = чСекунд + 1;
КонецЕсли;
Если чСекунд > 60 Тогда
ПредСотрудник      = 0;
чСекунд         = 0;
КонецЕсли;

Иначе
Предупреждение("Порт не открывается");
ЭтаФорма.Закрыть();
КонецЕсли;
КонецПроцедуры

Процедура ОбработатьЗашифрованнуюСтроку(ДанныеСПорта)
Массив = ДанныеСПорта.Выгрузить();
ИндексМин = ДанныеСПорта.GetLowerBound(0);
ИндексМакс = ДанныеСПорта.GetUpperBound(0);

СтрокаИнфо = "";
Для Индекс = ИндексМин По ИндексМакс - 1 Цикл
СимволПолученный = СокрЛП(Массив.Получить(Индекс));
Если СимволПолученный = "13" Тогда
Если Не Приостановить Тогда
СтрокаИнфо = ОбработкаСтроки(СтрокаИнфо); //Тут обработка сообщений
КонецЕсли;
Иначе
СтрокаИнфо = СтрокаИнфо + Символ(Число(СимволПолученный));
КонецЕсли;
КонецЦикла;
КонецПроцедуры

Отправка информации в com порт

Процедура ОтправитьВПорт(Отправить)
Если ComPort.PortOpen Тогда
ComPort.Output         = СокрЛП(Отправить);
Иначе
Сообщить("Порт не открывается",СтатусСообщения.ОченьВажное);
КонецЕсли;
КонецПроцедуры

Код проекта для Arduino Mega


#include <Adafruit_Fingerprint.h>                               // подключаем библиотеку для работы с модулем отпечатков пальцев
#include <SoftwareSerial.h>                                     // подключаем библиотеку для работы с программным UART

#include <SPI.h>
#include <MFRC522.h>

const int     buttonPin = 2;                                    // номер входа, подключенный к кнопке для входа в режим программирования
int           buttonState = 0;                                  // переменная для хранения состояния кнопки

int           modeState = 0;                                    // переменная для хранения состояния устройства. 0 - ожидание сканера отпечатков. 1 - программирование

uint8_t       id;                                               // идентификационный номер, под которым будет сохранён шаблон отпечатка пальца

String        frcUID = "";                                      // идентификационный номер считывателя rfid
int           rfidYes = 0;                                      // успешный ввод RFID

SoftwareSerial  mySerial(10, 11);                               // объявляем объект mySerial для работы с библиотекой SoftwareSerial ИМЯ_ОБЪЕКТА( RX, TX ); // Можно указывать любые выводы, поддерживающие прерывание PCINTx
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);  // объявляем объект finger   для работы с библиотекой Adafruit_Fingerprint ИМЯ_ОБЪЕКТА = Adafruit_Fingerprint(ПАРАМЕТР); // ПАРАМЕТР - ссылка на объект для работы с UART к которому подключен модуль, например: &Serial1

MFRC522 mfrc522(53, 5);                                         // Create MFRC522 instance

void setup() {

pinMode(buttonPin, INPUT);                                    // инициализируем пин, подключенный к кнопке, как вход

Serial.begin(9600);                                           // Инициализация аппаратного UART на скорости 9600
while (!Serial);                                              // Ожидание инициализации аппаратного UART

delay(500);
SPI.begin();                                                  // Init SPI bus
mfrc522.PCD_Init();                                           // Init MFRC522
mfrc522.PCD_DumpVersionToSerial();                            // Show details of PCD - MFRC522 Card Reader details

delay(500);                                                   // Ожидание инициализации модуля отпечатков пальцев
Serial.println(". . . Scan sensor . . .");                    // Вывод сообщения "Поиск сенсора"
finger.begin(57600);                                          // Инициализация программного UART на скорости 57600 (скорость модуля по умолчанию)
Serial.println(finger.verifyPassword());
if (finger.verifyPassword()) {
Serial.println(". . . Found sensor! . . .");                 // Если модуль отпечатков    обнаружен, выводим сообщение "сенсор обнаружен"
}
else {
Serial.println(". . . Did not find sensor . . .");          // Если модуль отпечатков не обнаружен, выводим сообщение "сенсор не обнаружен" и входим в бесконечный цикл: while(1);
while (1);
}
Serial.println(". . . Please put your finger on the scanner or rfid . . .");

}

void loop() {

//Работа с кнопкой!
buttonState = digitalRead(buttonPin); // считываем значения с входа кнопки

if (buttonState == HIGH) {
modeState = 1;  // входим в режим программирования ДАЛЕЕ
}

switch (modeState) {
case 0:

frcUID = "";
//Работа в режиме опроса отпечатков пальцев и rfid
if (finger.getImage()         == FINGERPRINT_OK) {      // Захватываем изображение, если результат выполнения равен константе FINGERPRINT_OK (корректная загрузка изображения), то проходим дальше
if (finger.image2Tz()         == FINGERPRINT_OK) {    // Конвертируем полученное изображение, если результат выполнения равен константе FINGERPRINT_OK (изображение сконвертировано), то проходим дальше
if (finger.fingerFastSearch() == FINGERPRINT_OK) {  // Находим соответствие в базе данных отпечатков пальцев, если результат выполнения равен константе FINGERPRINT_OK (найдено соответствие), то проходим дальше
frcUID = ". . . Found ID=" + String(finger.fingerID) + ", confidence=" + String(finger.confidence) + "! . . .";
Serial.println(frcUID);
}
}
}

if (mfrc522.PICC_IsNewCardPresent()) {
delay(100);
if (mfrc522.PICC_ReadCardSerial()) {
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
frcUID = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
frcUID = frcUID + (mfrc522.uid.uidByte[i]);
}
frcUID = ". . . Found RFID UID=" + frcUID + "@ . . .";
Serial.println(frcUID);
}
}

delay(100);                                             // Задержка перед следующим сканированием 0,5 сек (нет смысла запускать на полной скорости)
Serial.println(". . . Please put your finger on the scanner or rfid . . .");
break;

case 1:
Serial.println(". . . Programming mode . . .");         // Входим в режим программирования
delay(400);
Serial.println(". . . Programming mode . . .");         // Входим в режим программирования
delay(400);
Serial.println(". . . Programming mode . . .");         // Входим в режим программирования
delay(400);
Serial.println(". . . Programming mode . . .");         // Входим в режим программирования

id = readnumber();                                      // Ожидание получения цифры, введённой с COM-порта
if (id >= 255) {                                        // Если 255 (макс ид) то входим в режим ожидания снова
modeState = 0;
} else {
if (id < 254) {                                       // Если 254 то rfid иначе палец 0-253
modeState = 2;                                      // Пытаемся отсканировать палец
}
else {
modeState = 3;                                      // Пытаемся отсканировать rfid uid
}
}
break;

case 2:
while (!getFingerprintEnroll());                        // Пытаемся получить ответ об присваивании ID
modeState = 1;
break;

case 3:
rfidYes = 0;

Serial.println(". . . Put RFID in Scanner! . . .");
delay(400);
Serial.println(". . . Put RFID in Scanner! . . .");
delay(400);
Serial.println(". . . Put RFID in Scanner! . . .");
delay(5000);

if (mfrc522.PICC_IsNewCardPresent()) {                  // Пытаемся отсканировать rfid uid
delay(100);
if (mfrc522.PICC_ReadCardSerial()) {
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
frcUID = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
frcUID = frcUID + (mfrc522.uid.uidByte[i]);
}
frcUID = ". . . New RFID UID=" + frcUID + "@ . . .";
rfidYes = 1;
Serial.println(frcUID);
delay(400);
Serial.println(frcUID);
delay(400);
Serial.println(frcUID);
delay(400);
Serial.println(frcUID);
}
}

if (rfidYes == 0) {
Serial.println(". . . RFID error! . . .");
delay(400);
}

modeState = 1;
break;
}
}

// функция возвращает номер, введённый с COM-порта
uint8_t readnumber(void) {
int num = -1;                                                 // Переменная с номером, который требуется вернуть
while (num < 0) {                                             // Вход в цикл, пока переменная num не станет >= 0
while (!Serial.available());                                // Ожидание пока в буфере COM-порта нет появятся данные
while (Serial.available()) {                                // Цикл пока в буфере COM-порта не закончатся данные
char c = Serial.read();                                   // Присваиваем очередной символ из COM-порта в переменную c
if (isdigit(c)) {                                         // Если значение переменной с - цифра, то ...
if (num < 0) {
num = 0; // Увеличиваем значение num на один порядок
} else {
num *= 10;
}
num += c - '0';                                         // Прибавляем к значению num цифру из переменной c
} delay(5);                                               // Задержка на 5мс, чтоб в буфер COM-порта успели догрузиться следующие символы (если таковые имеются)
}
}
return num;                                                   // Возвращение введённого числа
}

uint8_t getFingerprintEnroll() {
int p;                                                                                                                // Переменная для получения результатов выполнения функций
//Загрузка первого изображения отпечатка пальца
p = -1;
Serial.println(". . . Please put your new finger on the scanner . . .");                                              // Вывод сообщения "Пожалуйста положите Ваш палец на сканер"
delay(400);
Serial.println(". . . Please put your new finger on the scanner . . .");                                              // Вывод сообщения "Пожалуйста положите Ваш палец на сканер"
delay(400);
Serial.println(". . . Please put your new finger on the scanner . . .");                                              // Вывод сообщения "Пожалуйста положите Ваш палец на сканер"
delay(400);
Serial.println(". . . Please put your new finger on the scanner . . .");                                              // Вывод сообщения "Пожалуйста положите Ваш палец на сканер"

while (p != FINGERPRINT_OK) {                                                                                         // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_OK (корректная загрузка изображения)
p = finger.getImage();                                                                                              // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p
switch (p) {                                                                                                        // Проверка ответа ...
case FINGERPRINT_OK:               Serial.println(" Ok!");                                              break;    // Изображение отпечатка пальца корректно загрузилось
case FINGERPRINT_NOFINGER:         Serial.println(". . . Please put your new finger on the scanner . . ."); break;// Сканер не обнаружил отпечаток пальца
case FINGERPRINT_PACKETRECIEVEERR: Serial.println(". . . Communication error . . .");                   break;    // Ошибка соединения
case FINGERPRINT_IMAGEFAIL:        Serial.println(". . . Imaging error Please try again . . .");        break;    // Ошибка изображения
default:                           Serial.println(". . . Unknown error Please try again . . .");        break;    // Неизвестная ошибка
}
}
//Конвертирование изображения первого отпечатка пальца
p = finger.image2Tz(1);                Serial.print  (". . . Image converting . . .");                                // Конвертируем первое изображение и возвращаем результат выполнения данной операции в переменную p
switch (p) {                                                                                                          // Проверка ответа ...
case FINGERPRINT_OK:                 Serial.println("Ok!");                                               break;    // Изображение сконвертировано
case FINGERPRINT_IMAGEMESS:          Serial.println(". . . Image too messy . . .");                       return p; // Изображение слишком нечеткое
case FINGERPRINT_PACKETRECIEVEERR:   Serial.println(". . . Communication error . . .");                   return p; // Ошибка соединения
case FINGERPRINT_FEATUREFAIL:        Serial.println(". . . No fingerprint on image . . .");               return p; // Ошибка конвертирования
case FINGERPRINT_INVALIDIMAGE:       Serial.println(". . . No fingerprint on image . . .");               return p; // Ошибка изображения
default:                             Serial.println(". . . Unknown error . . .");                         return p; // Неизвестная ошибка
}
//Просим убрать палец от сканера
p = 0;
while (p != FINGERPRINT_NOFINGER) {                                                                                // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_NOFINGER (сканер не обнаружил отпечаток пальца)
Serial.println(". . . Please remove your finger from the scanner . . .");                                        // Вывод сообщения "Пожалуйста уберите Ваш палец со сканера"
delay(400);

p = finger.getImage();                                                                                           // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p
}
Serial.println(" Ok!");

//Загрузка второго изображения отпечатка пальца
p = -1;
Serial.println(". . . Place same finger again . . .");                                                              // Вывод сообщения "Пожалуйста положите тот же палец еще раз"
delay(400);

while (p != FINGERPRINT_OK) {                                                                                      // Вход в цикл, пока переменная p не станет равна константе FINGERPRINT_OK (корректная загрузка изображения)
p = finger.getImage();                                                                                           // Захватываем изображение и возвращаем результат выполнения данной операции в переменную p
switch (p) {                                                                                                     // Проверка ответа ...
case FINGERPRINT_OK:               Serial.println(" Ok!");                                      break;         // Изображение отпечатка пальца корректно загрузилось
case FINGERPRINT_NOFINGER:         Serial.println(". . . Place same finger again . . .");       break;         // Сканер не обнаружил отпечаток пальца
case FINGERPRINT_PACKETRECIEVEERR: Serial.println(". . . Communication error . . .");           break;         // Ошибка соединения
case FINGERPRINT_IMAGEFAIL:        Serial.println(". . . Imaging error . . .");                 break;         // Ошибка изображения
default:                           Serial.println(". . . Unknown error . . .");                 break;         // Неизвестная ошибка
}
}

//Конвертирование изображения второго отпечатка пальца
p = finger.image2Tz(2);                Serial.print  (". . . Image 2 converting . . .");                              // Конвертируем второе изображение и возвращаем результат выполнения данной операции в переменную p
switch (p) {                                                                                                          // Проверка ответа ...
case FINGERPRINT_OK:                 Serial.println("Ok!");                                               break;    // Изображение сконвертировано
case FINGERPRINT_IMAGEMESS:          Serial.println(". . . Image too messy . . .");                       return p; // Изображение слишком нечеткое
case FINGERPRINT_PACKETRECIEVEERR:   Serial.println(". . . Communication error . . .");                   return p; // Ошибка соединения
case FINGERPRINT_FEATUREFAIL:        Serial.println(". . . No fingerprint on image . . .");               return p; // Ошибка конвертирования
case FINGERPRINT_INVALIDIMAGE:       Serial.println(". . . No fingerprint on image . . .");               return p; // Ошибка изображения
default:                             Serial.println(". . . Unknown error . . .");                         return p; // Неизвестная ошибка
}
//Создание модели (шаблона) отпечатка пальца, по двум изображениям
p = finger.createModel();              Serial.print  (". . . Creating model . . .");                        // Создание модели (шаблона) отпечатка пальца, по двум изображениям
if (p == FINGERPRINT_OK              ) {
Serial.println(". . . Model create! Ok! . . .");
} else // Модель (шаблон) отпечатка пальца создана
if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println(". . . Communication error . . .");
return p;
} else // Ошибка соединения
if (p == FINGERPRINT_ENROLLMISMATCH  ) {
Serial.println(". . . Fingerprints did not match . . .");
return p;
} else // Отпечатки пальцев не совпадают
{
Serial.println(". . . Unknown error . . .");                                  // Неизвестная ошибка
return p;
}
//Сохранение, ранее созданной, модели (шаблона) отпечатка пальца, под определённым ранее, идентификационным номером
p = finger.storeModel(id);
//Serial.println(". . . Saving model . . .");
Serial.println(". . . Saving model . . .");

//Serial.println(". . . Saving model in ID="); Serial.print(id); Serial.print(": ");  // Сохранение модели (шаблона) отпечатка пальца, по двум изображениям
if (p == FINGERPRINT_OK              ) {
frcUID = ". . . Model save in ID=" + String(id) + "! . . .";
Serial.println(frcUID);
delay(1500);
Serial.println(frcUID);
delay(400);
Serial.println(frcUID);
delay(400);
Serial.println(frcUID);

} else // Модель (шаблон) отпечатка пальца сохранена
if (p == FINGERPRINT_PACKETRECIEVEERR) {
Serial.println(". . . Communication error . . .");
return p;
} else // Ошибка соединения
if (p == FINGERPRINT_BADLOCATION     ) {
Serial.println(". . . Could not store in that location . . .");
return p;
} else // Не удалось сохранить в этом месте
if (p == FINGERPRINT_FLASHERR        ) {
Serial.println(". . . Error writing to flash . . .");
return p;
} else // Ошибка записи в flash память
{
Serial.println(". . . Unknown error . . .");                              // Неизвестная ошибка
return p;
}
}


 

Эпилог

Цена планшета около 10 000 руб. (на самом деле от 7000 новые можно купить с 1 Gb ОЗУ но с 4Gb 1с будет поприятнее двигаться, я вообще взял б.у. с рук за 6000 в идеальном состоянии с 1Gb но повозился с оптимизацией).

Проходная делалась для мебельного производства поэтому корпус я изготовил там же. Думаю что можно напилить "смесь опилок с картоном" в магазине за 1 000 руб. и скрутить саморезами/склеить суперклеем. В крайнем случае можно взять готовый ящик (например электрошкафчик) и выпилить там окно.

Модули ардуинки и прочее около 2 000 руб.

Удовольствие от мозгового штурма и изготовления — бесценно!

 

39 Comments

  1. Черный Плащ

    А почему нельзя было использовать обычный usb сканер отпечатка пальца ?

    Reply
  2. Fator26

    (1)В Вас пропадает дух авантюризма…

    Reply
  3. Region102

    А как обрабатываются сбои, зависание arduinы, зависание 1С, зависание com порта? Внедряя проф скуд на предприятии, первые несколько месяцев были постоянные скандалы с опозданцами. Помогало видео наблюдение на проходной.

    Reply
  4. pro-rok

    Как я понял ардуинка связана с планшетом по usb. На планшете 1С (подключенная через Wi-Fi) обрабатывает посылки от ардуино.

    В 1С вызывается внешнее событие или какое-то регламентное задание опрашивает ?

    Так и не понял назначение MsCommLib.MsComm, она эмулирует com порт?

    Reply
  5. DGorgoN

    (1) А есть готовые примеры реализации?

    Reply
  6. DGorgoN

    (4) В 1с с помощью MsComm считывается ком порт и посылаются туда значения с помощью обработки ожидания

    Reply
  7. DGorgoN

    (3) Честно говоря пока никак, единственное что можно перезагрузить всё.

    Reply
  8. pro-rok

    (6) Я подобную связь организовывал напрямую через ком. В 1С говорил например что на com 3 висит сканер ШК и подключал обработчик внешнего события. Как только ардуинка ловива показания от датчиков она отправляла значение в ком порт, предварительно ставил префикс события например D1 ( первый датчик), что бы понимать каккой датчик сработал. 1С отрабатывала как внешнее событие от сканера и передавала мне ШК, т.е. показание датчика.

    Reply
  9. TitanLuchs

    (3) У «Меги» есть встроенный таймер, отслеживающий зависание. При его срабатывании контроллер перезагружается.

    Reply
  10. TitanLuchs

    Нормуль, но лучше все-таки было бы разобраться с http-сервисами и сделать все на них. Было бы более масштабируемо, надежнее и дешевле. Ардуина легко работает как с ethernert, так и с wi-fi. Планшет исключаем, вместо него можно поставить дисплей: или обычный сегментный, или LCD — они сейчас стоят копейки. Таким образом уходит еще одно слабое звено в виде соединения дуни с планшетом через сом-порт, заодно и лицензия одна сэкономится. При сканировании отпечатка или карты дергаем 1С через http-сервис, можно даже сразу от нее получать ответ, разрешение на вход, например, и при необходимости показывать на экране. Итого стоимость запчастей обойдется в 2500 рублей (это по максимуму).

    Но в целом лайк, конечно.

    Reply
  11. DGorgoN

    (10) Я всё понимаю но это будет следующая версия

    Reply
  12. DGorgoN

    (9)о, разберу вопрос

    Reply
  13. DGorgoN

    (8) Напрямую через com это как?

    Reply
  14. TitanLuchs

    (12) Там 3 строчки кода. Подключаешь стандартную библиотеку

    #include <avr/wdt.h>

    В setup() Устанавливаешь время, через которое должен сработать таймер:

    wdt_enable(WDTO_2S);

    WDTO_2S — это константа, в данном случае 2 секунды. Можно ставить от 15 мсек до 8 сек.

    В цикле loop() сбрасываешь таймер:

    wdt_reset();

    Если контроллер зависает, то программа перестает сбрасывать таймер и через указанное в сетапе время происходит хард-резет. Именно хард, аналогичный нажатию кнопки «Сброс».

    Reply
  15. DGorgoN

    Просто еще нужно учесть что понятно что было бы прикольно экран к малине или ардуино и там свой софт без лицензии но ведь и устройство получилось ну очень интересным. Зная код на 1с можно управлять всякими ардуинами без посредников. Даешь робота на 1с!

    Reply
  16. TitanLuchs
  17. pro-rok

    (13) С планшетом я не эксперементировал, но при подключении ардуинки к ПК через USB она автоматом эмулирует COM порт (через который собственно и прошивается само железо). В 1С я подключаю сканер ШК говорю что он работает через СОМ в качестве номера порта указываю тот, который эмулирует драйвер ардуино. Как только ардуино что то посылает в СОМ порт в 1С срабатывает обработка события. Тут правда получается односторонняя связь. В обратную сторону при необходимости можно использовать Ethernet, код не сложный нужна только плата.

    void loop()
    {
    
    char* params;                              // переменная для хранения полученного запроса
    if (params = ethernet.serviceRequest())    //Если чтото пришло, то считываем и выполняем код
    {
    if(params[0] == ‘1’){   // Если пришла команда 1 то …
    digitalWrite(10, LOW);   // выключаем реле
    ethernet.print(ch1);   // отправляем ответ «1»
    }
    else if(params[0] == ‘2’){   // иначе если пришла команда 2 то…
    digitalWrite(10, HIGH);       // включаем реле
    ethernet.print(ch2);         // отправляем ответ «2»
    

    Показать

    Reply
  18. DGorgoN

    (10) И еще по поводу слабого звена. Через 1с ведь можно любой интерфейс нарисовать. Ещё там админка есть, которая сразу у аппарата позволяет присвоить человеку свой код

    Reply
  19. DGorgoN

    (17) 1.Мне очень важна двухсторонняя связь

    2. Планшет это тот же ПК на Win, они только форм-фактором различаются.

    Reply
  20. TitanLuchs

    (18) Я ж не настаиваю на своем варианте ) Все зависит от того, какой в итоге функционал вы хотите реализовать. Если интерфейс нужен более продвинутый, чем просто отображение одной строчки с сообщением, то конечно планшет с 1С тут выигрывает.

    Reply
  21. Region102

    Честно говоря к данной реализации отношусь скептически, ладно если работает, а что если при зависании одного из компонентов пропадут проходы тысячи сотрудников. Думаю вы услышите множество лестных слов в свой адрес. Не вник в код на ардуине, вы пишите проходы в постоянную память?

    Reply
  22. DGorgoN

    (21) Проходы сразу пишутся в базу 1с, если устройство зависнет то ребут.

    Причём 1с сразу выводит на экране сотрудника, который проходит да еще вдобавок и пикает. Т.е. если ожидаемого не происходит то ребут. Никто не пройдет незамеченным.

    Reply
  23. Region102

    (22) Что происходит если 1С зависает? На проходной 100 человек и все хотят зайти. Я понимаю ребут ардуины по таймеру, а вот ребут 1С это дело не 30 секунд. Я не стараюсь критиковать, я стараюсь улучшить ваш продукт ). Сам люблю ардуинку, но 1С в нашей СКУД выполняла только роль backend-а, туда регламентым заданием забирались данные о проходах и строились отчеты из базы Firebase СКУД. В столовой у нас был подключен считыватель по вашему принципу, и были периодические глюки и зависания, вот основные по приоритетам:

    1. Зависло регламентное задание опрашивающие считыватель и выводящее данные на дисплей.

    2. Завис хаб.

    3. Завис комп с 1С

    4. Завис считыватель. Очень редко, но обычно удавалось вытащить проходы из его памяти.

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

    Reply
  24. DGorgoN

    (23) Если 1с зависает то это очень и очень плохо. У меня 1с по настоящему зависала два раза в год из-за проблем с оборудованием. Всё остальное время она работала 2424. Мне сложно представить что такое бывает.

    Я проверю реализацию после эксплуатации и напишу вам!

    Reply
  25. DGorgoN

    (14) «но дело в том, что все это работает только в Arduino Uno, а на Arduino Mega, Mini и Nano все это работает ровно наоборот, т.е. не работает совсем :)»

    Ахах (

    Reply
  26. TitanLuchs

    (25) Загрузка нового бутлоадера решает проблему. В интернетах много информации на эту тему.

    Reply
  27. DGorgoN

    (26) Это понятно, буду мучать уже следующую версию, думаю всё таки если время будет то мучать буду уже по http

    Reply
  28. pro-rok

    (23) Зависание хаба, компа или считывателя возможно даже если используется не 1С+Arduino, а нечто другое.

    Reply
  29. Region102

    (28) Использовали проф СКУД, считыватели за несколько лет не зависли ни разу. Внутренняя память в считывателе на 90тыс событий решала все проблемы с зависанием остальных компонентов. Зависали считыватели другого производителя, но они и стоили в 5 раз дешевле, правда зависание было своеобразным, считыватель переставал опрашиваться через сеть, но проходы продолжал писать в память.

    Reply
  30. DGorgoN

    Ну сделать рестарт на Ардуино это плюс 400 рублей денег. Поставить Ардуино мини и мониторить оба устройства и уже 2 надежность.

    Reply
  31. taishy

    + напечатать корпус под это все на 3Д-принтере

    Reply
  32. alexander-lubich

    нормальное решение, считыватель может быть подключен к локальной базе , которую можно назвать «СКУД» и ее задача будет — накопление и информации и отправка ее в основную базу . зависание ардуино — 1 минута, перезагрузка компа с локальной базой — 3 минуты. + проработать пару сценариев развития учета в случае долговременного отказа , например второй комплект оборудования (комп+ считыватель на аруине) для ряда проектов вполне себе решение.

    мне интересно как малину с 1С соединить, в ардуине тесно.

    Reply
  33. alexander-lubich

    если Ардуина работает c атоловским драйвером через UART и мы имеем подключение USB устройства к компьютеру то для Расберри я иного кроме вебсервисов не вижу пока.

    Reply
  34. Rik30

    Ну рукожопам всегда почёт и уважуха,хорошо описал тему. Вот только в стабильности данной разработки сомневаюсь.У меня 1500 чел.проходят в день через Anviz- и то траблов хватает.(Хотя это монолитное устройство) — только результаты считывай — ID сотрудника и время прихода-ухода по Ethetnetу.А тут такой «головняк».Каждое зависание данного устройства или его компонента -будет вызывать недоверие в его адекватности работы. Соответственно жуликоватые сотрудники- которые привыкли опаздывать — будут себя пяткой в грудь бить и говорить, что они отмечались, а эта электронная штуковина засбоила. Но в любом случае — работа хорошая — добавляю в закладки.

    P.S, — Цена устройства Anviz (считывание отпечатков и карт) стоит порядка 12-14 тыс.

    Reply
  35. starik-2005

    Код на С — отдельная песня, но за то, что еще раз вспомнили про ардвинку — однозначно плюс.

    И да, в час, когда первые ступени многоразовых ракет приземляются на плавучие платформы в атлантических океанах, использовать что-то без WiFi (тот же ESP8266) — стыд и позор.

    Reply
  36. dmarenin

    (35) там не совсем с (обертка над c-avr)

    Reply
  37. starik-2005

    (36) и чем отличается от С?)))

    Reply
  38. danil7772

    Никто не пробовал реализовать хранение отпечатков пальцев в базе данных типа Постгре и тп. ,чтобы хранить более 1000 отпечатков?

    Reply
  39. tf-paritet

    Добрый день всем. Собрал данный девайс. Отпечаток работает, но только 1 раз. Для того чтобы отметиться повторно надо перезапускать обработку. На рисунке сканер подключен к шине 3.3 вольта, но по другим схемам что смотрел он должен был быть подключен в 5 Вольтовую шину «+» . Спрашиваю почему? RFID не работает и сканер отпечатков пальцев до тех пор пока RFID не отключить минусовой провод. Кто сталкивался с такой проблемой? RFID и Сканер «+» берут от 3.3V один разъем. Может обязательно необходимо дополнительное питания для АРДУИНО? Может причина нестабильной работы в питании? Коллеги подскажите)

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *