Автоматическая камера хранения на 24 ячейки + сканер отпечатка + купюроприемник (разработка с нуля)
- Войдите на сайт для отправки комментариев
Оцените пожалуйста масштабы задачи и мое понимание реализации, а также, разумеется, озвучьте примерную стоимость написания программной части. Необходима всесторонняя поддержка, так как знаний в аппаратной/программной части, к сожалению, не хватает. Буду рад услышать как советы так и критику. В идеале, получить бы краткий вводный курс и скетч с комментариями. Т.е. хотелось не просто собрать, но и понять как оно работает.
Исходный список "железа" (обсуждаемо):
1. Arduino (Uno имеется в наличии)
2. Ethernet shield/GPRS shield (для возможности удаленного мониторинга, обсуждаемо)
3. RTC модуль (например DS1307)
4. Fingerprint scaner FPM10A - описание полного аналога можно найти здесь: http://www.adafruit.com/datasheets/ZFM%20user%20manualV15.pdf и саму железку тут http://www.aliexpress.com/item/Free-Shipping-Fingerprint-Recognition-Module-FPM10A-Optical-fingerprint-Fingerprint-Module-For-Arduino-in-stock-Best-quality/1663157893.html Модуль имеется в наличии, готовые библиотеки есть на Adafuit, хранит отпечатки в своей энергонезависимой памяти, в режиме распознавания возвращает номер ячейки памяти в которой хранится отпечаток.
5. SD Card модуль (для оперативных данных, например времени на балансе ячейки хранения и, возможно, отчетности)
6. Сдвиговые регистры (например MCP23017)
7. Блоки реле 2х16 для управления замками. Например http://www.aliexpress.com/item/Free-shipping-12V-16-Channel-Relay-Module-Interface-Board-For-Arduino-PIC-ARM-DSP-PLC-With/1834575608.html
8. Замки с обратной связью (датчик открытия). Например http://www.aliexpress.com/store/product/Electric-Cabinet-Lock-MA1208S/1018446_1400342102.html
9. ЖК дисплей
10. Купюроприемник (как я понимаю нужен поддерживающий Pulse, тут необходим совет по выбору). Возможность принимать 2 номинала (1 и 5 у.е.). Выдача сдачи не подразумевается. Вот например http://www.aliexpress.com/item/Bill-acceptor-or-note-acceptors-with-MDB-or-RS232-or-Pulse-or-CCtalk-interface/688126227.html
11. Buzzer сигнализирующий о незакрытой двери.
// Интерфейс пользователя:
- Сканер отпечатка
- Дисплей с информацией о текущем системном времени, загруженной сумме и времени на балансе
- Клавиша "1" вызова режима постановки на хранение
- Клавиша "2" вызова режима временного открытия
- Клавиша "3" вызова режима изъятия
// Алгоритм работы:
- Нажимается клавиша "1"
- Вставляется купюра (купюры), согласно сумме на экране отображается время хранения (к примеру 1 у.е. = 1 час, 2 у.е. = 2 часа, 3 у.е. = 3 часа, итд)
- Включается fingerprint, прикладывается палец (дважды, как этого требует FPM10A) Желателен вывод подсказки на ЖК-дисплей.
- Открывается первая свободная ячейка
- Срабатывает сигнализация незакрытой двери, пищит до закрытия.
- По закрытию ячейки записывается номер ячейки+текущее время на SD карту и запускается обратный отсчет времени (после достижения 0 счетчик уходит в минус, для изъятия требует ввода недостающего количества купюр)
- Ячейка принимает статус занятой и привязаной к конкретному отпечатку пальца (в интервале оплаченного времени пользователь может открывать ячейку сколько угодно раз при помощи клавиши "2" и верификации отпечатка)
Для изъятия из ячейки:
- Нажимается клавиша "3"
- Проводится верификация отпечатка
- Если не требуется доплата, ячейка открывается
- Отпечаток удаляется из памяти FPM10A
- Ячейка отмечается как свободная (предположительно это запись в файле на SD карте, я не представляю как еще её сделать энергонезависимой и защищенной от случайных сбоев по питанию)
Спасибо за внимание.
Электромыло для связи: avadanliq () gmail.com
Дело в том, что не у каждого будут все комплектующие. Стоимост у них не малая.
UNO будет маловато для такой задачи - памяти мало.
1. Рекомендовал бы Mega2560+Ethernet Sheild(есть слот microSD) - а интернет вводить с роутера, который или Wi-Fi или GPRS или по проводу.
2. Все что выведено к пользователю замок и датчик в замке - должно быть запитанно от отдельного источника питания и электрически развязано от ардуины - чтобы статичеким электричеством не вызвать выход из строя контроллера и открывание всех ячеек.
Дело в том, что не у каждого будут все комплектующие. Стоимост у них не малая.
Да, согласен. Тоже думал над этим вопросом. По одним даташитам скетч не напишешь. Пересылка комплектующих туда-обратно тоже не вариант - я не в России. Пока без идей как это провернуть.
UNO будет маловато для такой задачи - памяти мало.
1. Рекомендовал бы Mega2560+Ethernet Sheild(есть слот microSD) - а интернет вводить с роутера, который или Wi-Fi или GPRS или по проводу.
Спасибо, буду иметь в виду. Тогда Mega2560+Ethernet с microSD, а для интернет-гейта можно взять TP-Link 3020 http://www.tp-link.com/lk/products/details/?model=TL-MR3020. На него всякие WRT накатываются, есть поддержка 3G модемов.
2. Все что выведено к пользователю замок и датчик в замке - должно быть запитанно от отдельного источника питания и электрически развязано от ардуины - чтобы статичеким электричеством не вызвать выход из строя контроллера и открывание всех ячеек.
Указанные блоки реле судя по всему имеют оптронную развязку, с замками ардуино напрямую не связана, остальные компоненты это кнопки, и сканер отпечатка, у них не будет проводящих поверхностей.
А что если разбить задачу на подзадачи и для начала поговорить о написании скетча для Fingerprint scaner FPM10A и четырёх кнопок. Буду рад вопросам, комментариям, исправлениям и дополнениям.
Дело в том, что Адафрут предоставляет в качестве примера работы с модулем два отдельных скетча - один на регистрацию отпечатков, второй на сверку с сохраненными в памяти модуля. Нужно сделать из них единый скетч, по возможности исключив лишнее и оставив только необходимый функционал. Вот библиотека от Adafruit.com: https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library. Страница продукта: https://www.adafruit.com/products/751
Скетчи:
1) Enroll - регистрация
001
/***************************************************
002
This is an example sketch for our optical Fingerprint sensor
003
004
Designed specifically to work with the Adafruit BMP085 Breakout
005
----> <a href="http://www.adafruit.com/products/751" rel="nofollow">http://www.adafruit.com/products/751</a>
006
007
These displays use TTL Serial to communicate, 2 pins are required to
008
interface
009
Adafruit invests time and resources providing this open source code,
010
please support Adafruit and open-source hardware by purchasing
011
products from Adafruit!
012
013
Written by Limor Fried/Ladyada for Adafruit Industries.
014
BSD license, all text above must be included in any redistribution
015
****************************************************/
016
017
#include <Adafruit_Fingerprint.h>
018
#if ARDUINO >= 100
019
#include <SoftwareSerial.h>
020
#else
021
#include <NewSoftSerial.h>
022
#endif
023
024
uint8_t getFingerprintEnroll(uint8_t id);
025
026
027
// pin #2 is IN from sensor (GREEN wire)
028
// pin #3 is OUT from arduino (WHITE wire)
029
#if ARDUINO >= 100
030
SoftwareSerial mySerial(2, 3);
031
#else
032
NewSoftSerial mySerial(2, 3);
033
#endif
034
035
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
036
037
void
setup
()
038
{
039
Serial
.begin(9600);
040
Serial
.println(
"fingertest"
);
041
042
// set the data rate for the sensor serial port
043
finger.begin(57600);
044
045
if
(finger.verifyPassword()) {
046
Serial
.println(
"Found fingerprint sensor!"
);
047
}
else
{
048
Serial
.println(
"Did not find fingerprint sensor :("
);
049
while
(1);
050
}
051
}
052
053
void
loop
()
// run over and over again
054
{
055
Serial
.println(
"Type in the ID # you want to save this finger as..."
);
056
uint8_t id = 0;
057
while
(
true
) {
058
while
(!
Serial
.available());
059
char
c =
Serial
.read();
060
if
(! isdigit(c))
break
;
061
id *= 10;
062
id += c -
'0'
;
063
}
064
Serial
.print(
"Enrolling ID #"
);
065
Serial
.println(id);
066
067
while
(! getFingerprintEnroll(id) );
068
}
069
070
uint8_t getFingerprintEnroll(uint8_t id) {
071
uint8_t p = -1;
072
Serial
.println(
"Waiting for valid finger to enroll"
);
073
while
(p != FINGERPRINT_OK) {
074
p = finger.getImage();
075
switch
(p) {
076
case
FINGERPRINT_OK:
077
Serial
.println(
"Image taken"
);
078
break
;
079
case
FINGERPRINT_NOFINGER:
080
Serial
.println(
"."
);
081
break
;
082
case
FINGERPRINT_PACKETRECIEVEERR:
083
Serial
.println(
"Communication error"
);
084
break
;
085
case
FINGERPRINT_IMAGEFAIL:
086
Serial
.println(
"Imaging error"
);
087
break
;
088
default
:
089
Serial
.println(
"Unknown error"
);
090
break
;
091
}
092
}
093
094
// OK success!
095
096
p = finger.image2Tz(1);
097
switch
(p) {
098
case
FINGERPRINT_OK:
099
Serial
.println(
"Image converted"
);
100
break
;
101
case
FINGERPRINT_IMAGEMESS:
102
Serial
.println(
"Image too messy"
);
103
return
p;
104
case
FINGERPRINT_PACKETRECIEVEERR:
105
Serial
.println(
"Communication error"
);
106
return
p;
107
case
FINGERPRINT_FEATUREFAIL:
108
Serial
.println(
"Could not find fingerprint features"
);
109
return
p;
110
case
FINGERPRINT_INVALIDIMAGE:
111
Serial
.println(
"Could not find fingerprint features"
);
112
return
p;
113
default
:
114
Serial
.println(
"Unknown error"
);
115
return
p;
116
}
117
118
Serial
.println(
"Remove finger"
);
119
delay(2000);
120
p = 0;
121
while
(p != FINGERPRINT_NOFINGER) {
122
p = finger.getImage();
123
}
124
125
p = -1;
126
Serial
.println(
"Place same finger again"
);
127
while
(p != FINGERPRINT_OK) {
128
p = finger.getImage();
129
switch
(p) {
130
case
FINGERPRINT_OK:
131
Serial
.println(
"Image taken"
);
132
break
;
133
case
FINGERPRINT_NOFINGER:
134
Serial
.print(
"."
);
135
break
;
136
case
FINGERPRINT_PACKETRECIEVEERR:
137
Serial
.println(
"Communication error"
);
138
break
;
139
case
FINGERPRINT_IMAGEFAIL:
140
Serial
.println(
"Imaging error"
);
141
break
;
142
default
:
143
Serial
.println(
"Unknown error"
);
144
break
;
145
}
146
}
147
148
// OK success!
149
150
p = finger.image2Tz(2);
151
switch
(p) {
152
case
FINGERPRINT_OK:
153
Serial
.println(
"Image converted"
);
154
break
;
155
case
FINGERPRINT_IMAGEMESS:
156
Serial
.println(
"Image too messy"
);
157
return
p;
158
case
FINGERPRINT_PACKETRECIEVEERR:
159
Serial
.println(
"Communication error"
);
160
return
p;
161
case
FINGERPRINT_FEATUREFAIL:
162
Serial
.println(
"Could not find fingerprint features"
);
163
return
p;
164
case
FINGERPRINT_INVALIDIMAGE:
165
Serial
.println(
"Could not find fingerprint features"
);
166
return
p;
167
default
:
168
Serial
.println(
"Unknown error"
);
169
return
p;
170
}
171
172
173
// OK converted!
174
p = finger.createModel();
175
if
(p == FINGERPRINT_OK) {
176
Serial
.println(
"Prints matched!"
);
177
}
else
if
(p == FINGERPRINT_PACKETRECIEVEERR) {
178
Serial
.println(
"Communication error"
);
179
return
p;
180
}
else
if
(p == FINGERPRINT_ENROLLMISMATCH) {
181
Serial
.println(
"Fingerprints did not match"
);
182
return
p;
183
}
else
{
184
Serial
.println(
"Unknown error"
);
185
return
p;
186
}
187
188
p = finger.storeModel(id);
189
if
(p == FINGERPRINT_OK) {
190
Serial
.println(
"Stored!"
);
191
}
else
if
(p == FINGERPRINT_PACKETRECIEVEERR) {
192
Serial
.println(
"Communication error"
);
193
return
p;
194
}
else
if
(p == FINGERPRINT_BADLOCATION) {
195
Serial
.println(
"Could not store in that location"
);
196
return
p;
197
}
else
if
(p == FINGERPRINT_FLASHERR) {
198
Serial
.println(
"Error writing to flash"
);
199
return
p;
200
}
else
{
201
Serial
.println(
"Unknown error"
);
202
return
p;
203
}
204
}
2) Fingerprint - распознавание
001
/***************************************************
002
This is an example sketch for our optical Fingerprint sensor
003
004
Designed specifically to work with the Adafruit BMP085 Breakout
005
----> <a href="http://www.adafruit.com/products/751" rel="nofollow">http://www.adafruit.com/products/751</a>
006
007
These displays use TTL Serial to communicate, 2 pins are required to
008
interface
009
Adafruit invests time and resources providing this open source code,
010
please support Adafruit and open-source hardware by purchasing
011
products from Adafruit!
012
013
Written by Limor Fried/Ladyada for Adafruit Industries.
014
BSD license, all text above must be included in any redistribution
015
****************************************************/
016
017
018
#include <Adafruit_Fingerprint.h>
019
#if ARDUINO >= 100
020
#include <SoftwareSerial.h>
021
#else
022
#include <NewSoftSerial.h>
023
#endif
024
025
int
getFingerprintIDez();
026
027
// pin #2 is IN from sensor (GREEN wire)
028
// pin #3 is OUT from arduino (WHITE wire)
029
#if ARDUINO >= 100
030
SoftwareSerial mySerial(2, 3);
031
#else
032
NewSoftSerial mySerial(2, 3);
033
#endif
034
035
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
036
037
void
setup
()
038
{
039
Serial
.begin(9600);
040
Serial
.println(
"fingertest"
);
041
042
// set the data rate for the sensor serial port
043
finger.begin(57600);
044
045
if
(finger.verifyPassword()) {
046
Serial
.println(
"Found fingerprint sensor!"
);
047
}
else
{
048
Serial
.println(
"Did not find fingerprint sensor :("
);
049
while
(1);
050
}
051
Serial
.println(
"Waiting for valid finger..."
);
052
}
053
054
void
loop
()
// run over and over again
055
{
056
getFingerprintIDez();
057
}
058
059
uint8_t getFingerprintID() {
060
uint8_t p = finger.getImage();
061
switch
(p) {
062
case
FINGERPRINT_OK:
063
Serial
.println(
"Image taken"
);
064
break
;
065
case
FINGERPRINT_NOFINGER:
066
Serial
.println(
"No finger detected"
);
067
return
p;
068
case
FINGERPRINT_PACKETRECIEVEERR:
069
Serial
.println(
"Communication error"
);
070
return
p;
071
case
FINGERPRINT_IMAGEFAIL:
072
Serial
.println(
"Imaging error"
);
073
return
p;
074
default
:
075
Serial
.println(
"Unknown error"
);
076
return
p;
077
}
078
079
// OK success!
080
081
p = finger.image2Tz();
082
switch
(p) {
083
case
FINGERPRINT_OK:
084
Serial
.println(
"Image converted"
);
085
break
;
086
case
FINGERPRINT_IMAGEMESS:
087
Serial
.println(
"Image too messy"
);
088
return
p;
089
case
FINGERPRINT_PACKETRECIEVEERR:
090
Serial
.println(
"Communication error"
);
091
return
p;
092
case
FINGERPRINT_FEATUREFAIL:
093
Serial
.println(
"Could not find fingerprint features"
);
094
return
p;
095
case
FINGERPRINT_INVALIDIMAGE:
096
Serial
.println(
"Could not find fingerprint features"
);
097
return
p;
098
default
:
099
Serial
.println(
"Unknown error"
);
100
return
p;
101
}
102
103
// OK converted!
104
p = finger.fingerFastSearch();
105
if
(p == FINGERPRINT_OK) {
106
Serial
.println(
"Found a print match!"
);
107
}
else
if
(p == FINGERPRINT_PACKETRECIEVEERR) {
108
Serial
.println(
"Communication error"
);
109
return
p;
110
}
else
if
(p == FINGERPRINT_NOTFOUND) {
111
Serial
.println(
"Did not find a match"
);
112
return
p;
113
}
else
{
114
Serial
.println(
"Unknown error"
);
115
return
p;
116
}
117
118
// found a match!
119
Serial
.print(
"Found ID #"
);
Serial
.print(finger.fingerID);
120
Serial
.print(
" with confidence of "
);
Serial
.println(finger.confidence);
121
}
122
123
// returns -1 if failed, otherwise returns ID #
124
int
getFingerprintIDez() {
125
uint8_t p = finger.getImage();
126
if
(p != FINGERPRINT_OK)
return
-1;
127
128
p = finger.image2Tz();
129
if
(p != FINGERPRINT_OK)
return
-1;
130
131
p = finger.fingerFastSearch();
132
if
(p != FINGERPRINT_OK)
return
-1;
133
134
// found a match!
135
Serial
.print(
"Found ID #"
);
Serial
.print(finger.fingerID);
136
Serial
.print(
" with confidence of "
);
Serial
.println(finger.confidence);
137
return
finger.fingerID;
138
}
Как работает "из коробки":
1) Модуль подключается к Ардуине, грузится скетч регистрации, регистрируется отпечаток, с клавиатуры ПК (запись в порт) вводится номер ячейки в которую будет сохранен "образ" отпечатка (изображение никуда не сохраняется, только некая контрольная сумма), после чего эта запись остается в энергонезависимой памяти самого модуля.
Найденый глюк, выдаваемый за особенность службой поддержки - нельзя ввести номер ячейки без ввода печатного символа (буквы) до номера ячейки.
2) Основной (автономный) режим работы это сверка поступающих со сканера отпечатков и, при совпадении, выдача в порт номера ячейки, при ошибке распознавания - номера ошибки, итд. Для перехода в этот режим необходима загрузка отдельного скетча. При этом постоянно работает подсветка сканера, т.е. устройство ждет палец. Иногда подглючивает, подсветка пропадает на несколько секунд и, видимо, скетч перезагружается, после чего нормально работает снова. Может быть это обнуляется какой-то счетчик в скрипте.
Видео от Адафрут: https://www.youtube.com/watch?v=1diFaa5OsFg
Хотелось бы что бы единый скетч v.:0.1 работал следующим образом:
К Ардуино подключен модуль FPM10A;
На microSD (на Ethernet шилде), лежит текстовый файл cellstatus.txt с где на каждой из 24 строк, соответствующих номеру ячейки, стоит '1', '2', '3', '4' или '5' (статус "свободно", "занято", "открыто", "блокировано" или "прочее");
Подключены 4 кнопки (Положить, Открыть, Изъять, Отмена);
Пищалка для подачи звуковых сигналов (buzzer)
А) Не нажата ни одна из кнопок
- модуль FPM10A отключен, например по питанию (не создаст ли это ошибки в выполнении скетча?), для того, чтобы не горела подсветка сканера
B) Нажата кнопка 1 (Размещение на хранение):
* тут в дальнейшем планируется разместить обработку событий купюроприемника и возврат количества купюр (часов на баланс), отображение информации на LCD
- включается FPM10A
- скетч построчно читает cellstatus.txt , пишет номер первой строки с '1' в переменную freecell.
- вызывается процедура регистрации, из переменной freecell скетч сообщает модулю номер ячейки в которую следует записать данный отпечаток.
- после успешной регистрации номер записывается в переменную unlockcell
* тут в дальнейшем планируется разместить вызов функции открытия ячейки (реле замка) с аргументом unlockcell, которая поместит '3' (открыто) на строку № unlockcell в файле cellstatus.txt, попищит buzzer'ом до получения от датчика замка сигнала о закрытии, затем запишет в строку '2' (занято).
* тут в дальнейшем планируется разместить функции регистрации текущего времени с модуля RTC в отдельный файл, аналогичный файлу статусов ячеек. Например строки типа от ЧЧ:ММ ДД:ММ:ГГ до ЧЧ:ММ ДД:ММ:ГГ (+1, +2, +3, итд часов, в зависимости от количества и номинала загруженных купюр)
- скетч выходит в режим "A"
C) Нажата кнопка 2 (Временное открытие):
- включается FPM10A, переключается в режим распознавания
- возвращается в режим "А" если нет ответа от FPM10A в течение 10 секунд
- возвращается в режим "А" если нажата кнопка 4 (Отмена)
- в случае распознания скетч получает от модуля номер ячейки, пишет его в переменную matchcell
* тут в дальнейшем планируется разместить функцию проверки времени на балансе ячейки № matchcell, при необходимости оплаты, вызова функции купюроприемника
- Присваевает unlockcell = matchcell
* тут в дальнейшем планируется разместить вызов функции открытия ячейки (реле замка) с аргументом == unlockcell, которая поместит '3' (открыто) на строку № unlockcell в файле cellstatus.txt, попищит buzzer'ом до получения от датчика замка сигнала о закрытии, затем запишет в строку '2' (занято).
- скетч выходит в режим "A"
D) Нажата кнопка 3 (Изъятие):
- включается FPM10A, переключается в режим распознавания
- возвращается в режим "А" если нет ответа от FPM10A в течение 10 секунд
- возвращается в режим "А" если нажата кнопка 4 (Отмена)
- в случае распознания скетч получает от модуля номер ячейки, пишет его в переменную matchcell
* тут в дальнейшем планируется разместить функцию проверки времени на балансе ячейки № matchcell, при необходимости оплаты, вызова функции купюроприемника
- Присваевает unlockcell = matchcell
* тут в дальнейшем планируется разместить вызов функции открытия ячейки (реле замка) с аргументом == unlockcell, которая поместит '3' (открыто) на строку № unlockcell в файле cellstatus.txt, попищит buzzer'ом до получения от датчика замка сигнала о закрытии, затем запишет в строку '1' (свободно).
- скетч выходит в режим "A"
Очень интересная тема. Жаль что разработчики к ней остались холодны.
попробуем разобраться. Ваши два скеча имеют
void
loop
() где и происходит обработка датчика отпечатков
берем код
http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichkuvoid
setup
()
02
{
03
04
pinMode(13, OUTPUT);
05
06
}
07
08
void
loop
()
09
10
{
11
if
(digitalRead(14)==HIGH)
//если кнопка нажата ...
12
{
13
digitalWrite(13,HIGH);
//включаем светодиод
14
}
15
else
//если не нажата...
16
{
17
digitalWrite(13,LOW);
//выключаем
18
}
19
20
}
и в эти места вставляем команды на запись нового отпечатка
для карточки вот схема включения http://cxem.net/arduino/arduino2.php
там же пример работы чтение запись
а вот еще http://arduino.ua/ru/prog/SD
с примером http://arduino.cc/en/Tutorial/ReadWrite
А кто нибудь купюроприемник приведенный автором топика использовал?
Может кто подскажет более дешевый купюроприемник, желательно хорошо работающий на Ардуине?
вот есть проект http://cxem.net/arduino/arduino85.php