… следующая волна экономических бедствий… будет результатом быстрой поступи автоматизации, которая упраздняет многие хорошие рабочие места уровня среднего класса (Б. Обама)
Как это работает
- Клиент приезжает на мойку
- Вносит деньги через купюроприёмник (на табло отображается сумма)
- Нажимает кнопку необходимого оборудования
- Клиент самостоятельно моет машину
- При желании нажимает стоп, либо выбирает другое оборудование
- Табло отсчитывает сумму за услуги (в зависимости от включенного оборудования)
- При обнулении оборудование выключается
- При необходимости повторить с п.2
При этом сетевые возможности аппарата позволяют:
- Видеть все внесённые платежи
- Менять настройки цен за услуги
- Включать/выключать оборудование
- Вести лог операций и ошибок на сервере
Состав оборудования
- Arduino Uno R3
- Матричный модуль типа MAX7219 на 4 знака
- Ethernet шилд W5100
- Модуль на 8 реле
- Кнопки
- Резисторы
- Провода
- Купюроприёмник Cashcode SM
- Щит электрический (степень защиты чем больше, тем лучше)
Всё закуплено на Aliexpress (кроме купюроприёмника и щита).
Схема сборки
Сетевой шилд просто втыкается сверху. Далее всё собирается через него.
Arduino — Cashcode
A0 — 11 (TxD TTL)
A1 — 16 (RxD TTL)
GND — 4 (GND)
Arduino — MAX7219
A4 — CLK
A3 — CS
A2 — DIN
GND — GND
+5V — VCC
Arduino — Реле
2-7 — in1-in6
GND — GND
+5V — VCC
Кнопки собираются по схеме делителя напряжения и подключены на A5. У меня резисторы от 200Ом до 3,2КОм.
Программирование
Инициализация табло и реле:
#define DIN 16
#define CS 17
#define CLK 18
#define max7219_reg_decodeMode 0x09
#define max7219_reg_intensity 0x0a
#define max7219_reg_scanLimit 0x0b
#define max7219_reg_shutdown 0x0c
#define max7219_reg_displayTest 0x0f
const unsigned char alf[] = {0,
28, 34, 34, 34, 34, 34, 34, 28,
8, 24, 8, 8, 8, 8, 8, 28,
28, 34, 2, 4, 8, 16, 32, 62,
28, 34, 2, 4, 2, 2, 34, 28,
34, 34, 34, 34, 62, 2, 2, 2,
62, 32, 32, 60, 2, 2, 2, 60,
28, 32, 32, 60, 34, 34, 34, 28,
62, 2, 2, 4, 8, 16, 32, 32,
28, 34, 34, 28, 34, 34, 34, 28,
28, 34, 34, 30, 2, 2, 2, 28
};
void setup()
{
pinMode(DIN,OUTPUT); pinMode(CS,OUTPUT); pinMode(CLK,OUTPUT); digitalWrite(CS, HIGH);
initLed();
pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT);
pinMode (A5, INPUT);
}
void setCommand(byte command, byte value)
{
digitalWrite(CS, LOW);
for (int i=0; i<4; i++) { shiftOut(DIN,CLK, MSBFIRST, command); shiftOut(DIN,CLK, MSBFIRST, value); }
digitalWrite(CS, HIGH);
}
void initLed()
{
setCommand(max7219_reg_scanLimit, 0x07);
setCommand(max7219_reg_decodeMode, 0x00);
setCommand(max7219_reg_shutdown, 0x01);
setCommand(max7219_reg_displayTest, 0x00);
setCommand(max7219_reg_intensity, 1);
}
Отображение числа на табло (текущее значение на случай отключения питания хранится в ячейках EEPROM 10 и 11):
int printNumber(int add)
{
int n=EEPROM.read(10)+EEPROM.read(11)*256;
if(add!=0) { n+=add; EEPROM.write(10, n%256); EEPROM.write(11, n>>8); }
int k;
for (char i=1; i<=8; i++)
{
digitalWrite(CS, LOW);
for (char j=3; j>=0; j--) { k=n/pow(10,j); shiftOut(DIN,CLK, MSBFIRST,i); shiftOut(DIN,CLK, MSBFIRST,alf[i+(k%10)*8]); }
digitalWrite(CS, HIGH);
}
return n;
}
Считывание кнопки (keydown отслеживает возврат кнопок в исходное для исключения дребезга реле, числа в условиях подбираются опытным путём):
int key = analogRead (5);
if(keydown && key<100) keydown=0;
if((EEPROM.read(10)>0 || EEPROM.read(11)>0) && !keydown)
{
if(key>910 && key<980) setRele(1);
if(key>810 && key<880) setRele(2);
if(key>710 && key<760) setRele(3);
if(key>550 && key<690) setRele(4);
if(key>400 && key<500) setRele(5);
if(key>330 && key<400) setRele(0);
}
Работа реле (в ячейках EEPROM 1-9 хранятся цены услуг за минуту использования):
void setRele(char r)
{
rele=r;
keydown=1;
for(char i=1;i<6;i++) digitalWrite(i+1, HIGH);
if(rele)
{
digitalWrite(rele+1, LOW);
timeRele=millis();
timeAllRele=60000/EEPROM.read(rele);
}
}
Счетчик денег (при включенном реле и превышении счетчика милисекунд заданного значения вычитаем 1):
if(rele>0 && rele<=5 && (millis()-timeRele)>timeAllRele)
{
if(printNumber(-1)==0) setRele(0);
timeRele+=timeAllRele;
}
Сетевые клиент и сервер взяты из стандартных библиотек Arduino. Купюроприёмник работает по протоколу CCNET.
В следующих частях более подробное описание их работы и аппарата следующего поколения на одноплатнике Orange Pi с экраном 17" и тачскрином.
Комментарии (15)
Germanets
26.01.2017 09:15+1Полученное устройство где-то было практически применено, или так и осталось образцом?
Неоднократно читал(хотя сам и не сталкивался), что Arduino Uno и другие Arduino-платы, кроме топовых Arduino MEGA являются достаточно ненадёжными и могут и самопроизвольно зависать, под воздействием помех или сами по себе. Были ли какие-то проблемы, жалобы на поведение устройства? Какой-то аналог WatchDog'а был использован?intsurfer
26.01.2017 09:41делал погодную станцию на ардуинке, работала несколько месяцев и отсылала данные на сайт любительского мониторинга, пока не сдох датчик температуры и влажности.
Mixalych
26.01.2017 11:16+1Продолжение интересно почитать, а также посмотреть видео о работе (принятие купюр, циферки на экране и пр.).
Интересно также детали по поводу «3. Нажимает кнопку необходимого оборудования». Сколько выходит себестоимость плат, ящика, купюроприемника (тут я бы даже отдельную статью почитал по подключению и настройке, протоколу...). Сколько выходит стоимость мойки, используя разное оборудование — вода, пена, воск, что еще?
На реальной (у нас) мойке дела обстоят так: платишь в кассу 100 р. за 6 минут, вот в эти 6 минут входит все доступное оборудование (пена, воск и вода), активируется время если из «корзины» достаешь пистолет, останавливается отсчет — когда пистолет ставишь обратно (там просто кнопка срабатывает от веса пистолета), ничего вручную нажимать не надо. К тому же на самом пистолете несколько положений и режимов, что хочешь использовать в данный момент — это гораздо удобнее, чем наматывать круги вокруг машины, нажимая кнопочку на блоке.
NetRat
26.01.2017 12:19Настоятельно не рекомендую использовать китайский релейный модуль. Выкинул таких же как у вас 4 шт. Через непродолжительное время реле залипают даже на половине заявленного тока. Залипшее реле доставляет куда больше неприятностей чем просто не сработавшее. Обязательно делайте обратную связь.
noonv
26.01.2017 15:26Интересная реализация.
А у нас был проект реализации общения с платёжной системой по протоколу MDB.
Aleksandr_Zh
27.01.2017 00:14купюроприёмник у вам с сигналами уровня ttl?
чем обусловлен выбор этого купюрника? он старого типа, проблемы с обманом (выниманием купюры), на них уже трудно найти комплектующие для ремонта.
Про щит: я б вас на кол посадил за такой щит! чуть вода и вам кирдык! точнее, тому кто дотронется! вы бы правила изучили, а то трупы нам не нужны…
про заземление щита и оборудования вообще молчу!!!
я работаю с MDB устройствами, пощупал пяток моделей (разрабатывал торговые автоматы по продаже разливного молока, баночных напитков и прочее), считаю, что надо брать совмещенный: монеты + купюры.
а в идеале, все новые автоматы проектировать под оплату картами: не все носят с собой толстые кошельки с купюрами и монетами :)paul_155
27.01.2017 00:16ttl. их много дешевых б/у. щиты собирал не я. и честно говоря видел только на фотографиях.
igor_suhorukov
Расскажите пожалуйста про Cashcode SM, какие купюры принимает и как с ним взаимодействовать?
cat_crash
Неужели у Вас google заблокирован?
Сходу ссылки
igor_suhorukov
Да конечно можно поискать, но ценность хабра как раз в обсуждении с автором, который практически использовал этот аппарат «вживую».
vvmk
Пишу сейчас обработчик CCNET для купюрного валидатора CASHCODE
на PHP под Linux.
Есть в руках живая железка.
Список принимаемых купюр можно получить от самого валидатора. Скорее всего зависит от региональной прошивки.
paul_155
наш принимает 10, 50, 100, 500, 1000, 5000
пока не разбирался как это прошито и как добавить 200 и 2000
взаимодействую по CCNET
подробности в продолжении