Nalivator-9000: робот-бармен на Raspberry Pi и Go +34
Пару лет назад я наткнулся на проект Bartendro на Kickstarter. Мне понравилась идея, и я решил, что идеальное применение для моего недавно приобретенного Raspberry Pi найдено. Я прикинул какие детали понадобятся, и приступил к DIY реализации робота-бармена. Кратко расскажу что из этого получилось.
Hardware
Основной элемент всей конструкции, конечно — насосы. В оригинальном проекте Bartendro используются перистальтические насосы собственной разработки (кстати, весь проект доступен в github).
Перистальтический насос — это такой насос который толкает по трубке её содержимое, как будто тюбик с пастой выдавливает. Соответственно, один конец опускаем в бутылку, а второй в стакан. Гифка с Википедии с принципом действия:
Похожие на оригинальные из Bartendro насосы есть в продаже на Aliexpress. Практика показала, что они хороши в эксплуатации, т.к. у них снимается передняя панель с трубкой — очень удобно мыть после застолья.
У Raspberry Pi на плате расположены GPIO разъемы. С помощью них посылаются или принимаются сигналы «1» или «0», 3,3В и 0В, соотвественно. В спецификации к насосу указано, что его рабочее напряжение — 12В, и «малиновых» 3.3В здесь будет мало. Поэтому для работы понадобится еще блок питания, а управлять им можно с помощью транзисторного переключателя. Итоговая схема выглядит так:
Для выбора транзистора надо чтобы напряжение коллектор-эммитер и максимальный ток коллектора у него был минимум в 1.5-2 раза выше необходимых. Я выбрал BDX33B, у него напряжение коллектор-эмиттер — 80В, а максимальный ток коллектора — 10A, что с запасом хватит для насоса со стартовым током 2А и напряжением 12В. Для того чтобы открыть транзистор, на базе надо получить не больше 2.5В. Считаем делитель в каком-нибудь онлайн-калькуляторе — получаем R1=150 Ом, R2=300 Ом.
В качестве «свистелок» я добавил три светодиода, подключенных к трем другим GPIO пинам, которые будут обозначать работающий моторчик, а также понадобятся при визуализации синтезатора речи. На выходы GPIO можно повесить максимальную нагрузку 15 мА на пин, или 50 мА суммарно. Поэтому подключаю светодиоды через резисторы по 300 Ом, ток в этом случае будет ~4 мА на пин.
Теперь можно идти в ближайший магазин радиодеталей и пробовать собирать.
Software
Raspberry Pi вообще довольно медленная штука — например, Django, на котором я изначально хотел сделать веб-приложение, запускается несколько минут. Поэтому я решил отказаться от него в пользу чего-нибудь легковесного, а именно — Go. Он быстро компилируется, кросс-компиляция под linux-arm на моем ПК занимает около 20 секунд. На выходе получаем небольшого размера бинарник, который статически собран и несет внутри все зависимости. Его можно сразу rsync-ом копировать на raspberry pi и проверять. Очень удобно для таких небольших приложений. Параметры кросс-компилияции под linux-arm выглядят так:
GOOS=linux GOARCH=arm GOARM=6 go build
У разных версий Raspberry Pi разные версии ARM. Узнать свою версию можно в /proc/cpuinfo
Так как у насосов нет никаких датчиков объема налитого, но известна пропускная способность, то объем можно контролировать через время работы насоса. Эмперическим путем я выяснил — чтобы налить 100 миллилитров, надо насос держать включенным 30 секунд. Получается нужно написать приложение, которое по команде, по очереди включает насосы на определенное время. В данной реализации подразумевается, что Наливатор умеет делать только один коктейль, то есть у него есть только одна кнопка — «Налить».
Я сделал конфиг в котором описаны подключенные насосы и коктейль, который нужно наливать.
{
"cname": "санрайз",
"pumps": [
{
"name": "Tequila",
"pump_pin": 17,
"led_pin": 23,
"duration": 17
},
{
"name": "Juice",
"pump_pin": 22,
"led_pin": 25,
"duration": 49
},
{
"name": "Grenadine",
"pump_pin": 27,
"led_pin": 24,
"duration": 7
}
]
}
Этот конфиг читает Наливатор при запуске, и понимает какой пин на какое время нужно включать. Для работы с GPIO я использовал библиотеку go-rpigpio:
for _, v := range CurrentPumps.Pumps {
log.Printf("Nalivaem %s ;duration = %v; GPIO = %v", v.Name, v.Duration, v.Pump_pin)
//pump pin open
p, err := rpi.OpenPin(v.Pump_pin, rpi.OUT)
if err != nil {
panic(err)
}
defer p.Close()
//led pin open
l, l_err := rpi.OpenPin(v.Led_pin, rpi.OUT)
if l_err != nil {
log.Printf("LED - Can't set LED pin to output")
}
defer l.Close()
// pump on
p.Write(rpi.HIGH)
//led on
l.Write(rpi.HIGH)
time.Sleep(time.Second * time.Duration(v.Duration))
// pump off
p.Write(rpi.LOW)
//led off
l.Write(rpi.LOW)
}
}
Весь код в гитхабе — github.com/fote/nalivator9000
Осталось добавить веб-интерфейс и все готово. Насчет корпуса я не стал заморачиваться и разместил все в икеевской коробке. В этот момент я понял, что дизайнера из меня не выйдет. В общем над внешним обликом еще стоит поработать.
Когда пришло время испытаний, я пригласил друзей провести нагрузочное тестирование, но перед их приходом понял, что веб-интерфейс это не совсем удобно — он не доступен из интернета, а подключаться к запароленной wi-fi сети, вбивать IP-адрес в браузере… слишком сложно. Тогда я добавил telegram-бота, который ждёт что ему напишут имя коктейля и наливает его. Я не буду описывать как создать бота, т.к. уже есть множество хороших статей на эту тему, в том числе и для Golang.
Также я решил добавить синтез речи, воспользовавшись Yandex SpeechKit. API этого сервиса очень прост, а лицензионное соглашение позволяет пользоваться им бесплатно в некоммерческих целях. Перед отправкой сообщения от telegram-бота, я прогоняю фразу через SpeechKit, в ответ получаю .wav-файл и воспроизвожу его через подключенный по 3.5mm-jack динамик.
Заключение
Тестирование Наливатора прошло успешно — тестировщики остались довольны и оставили много фичереквестов.
Напоследок видео работы:
За ваше здоровье!
Комментарии (36)
Ryppka
24.04.2017 14:12+2Мне больше всего напомнило аппарат искусственного кровообращения или искусственную почку)
Virviil
24.04.2017 14:25+2Надо переделать конфиг на фазы.
Потому что текилу и сок можно наливать одновременно. А вот гренадин надо заливать потом4te
24.04.2017 14:53Спасибо за совет. Действительно, фазы выглядят очень уместно. Кажется, это не сильно усложнит код и даст хороший прирост в скорости наливания
x893
24.04.2017 14:36Как то у меня неправильно ссылка на насос открывается за 4600 руб.
Может такой подойдет насос?4te
24.04.2017 14:43Судя по описанию — питание DC 12 В. Должен подойти
x893
24.04.2017 14:55Заказал 6 таких.
Kolyuchkin
24.04.2017 15:05Готовы ждать почти 5 минут приготовления коктейля?
x893
24.04.2017 15:24Это только первый коктейль ждать надо. Потом быстрее пойдет.
Kolyuchkin
24.04.2017 15:46+1Я к тому, что производительность насоса предложенного автором 1000мл/мин, вашего же — 20-60мл/мин — разница больше, чем на порядок.
x893
24.04.2017 15:58Ну это не проблема. Шесть штук будут наливать 120-360 мл. Уже достаточно.
Кто то ставит за 4600, кто за 350.
Jedem das Seine
BubaVV
24.04.2017 15:10+5Как-то стремно подключен насос. Нужен встречный диод параллельно мотору. Ток GPIO с учетом коеэффициента усиления даст примерно 1.5А на коллекторе — для этого насоса впритык. Я бы поставил полевик
safari2012
24.04.2017 17:12+1У меня похожая система подает в аквариум удобрения. Только вместо транзисторного переключателя я поставил блок из 4х ардуинских синих релюшек, они со светодиодами и с опторазвязкой.
Apokalepsis
24.04.2017 17:34Если предположить что за вечер нужны сделать 7 разных коктейлей, как бороться с очисткой трубок? После каждого приготовления коктейля снимать и чистить?
4te
24.04.2017 17:42В данной реализации — никак. Нужно «горизонтально маштабировать». Ставить 7 насосов, ну или 5, например, у каждого свой напиток, из них наливать разные коктейли. У меня насоса всего 3, с ними особо не разгуляешься в плане разных коктейлей
Vladal
25.04.2017 21:29В игре Сибирь (Syberia) есть интересный пример горизонтального масштабирования автоматона для коктейлей. Правда, виртуальный с механическим управлением.
TeosHM
24.04.2017 17:36Делал подобный аппарат, но на основе проекта BarMixVah, используя связку RPI2+arduino UNO. Реализация этого проекта очень понравилась, за счет удобного и понятного WEB-интерфейса. Хотел отказаться от ардуинки, получая команду напрямую с GPIO, но т.к. насосы новые не удалось купить, идея заглохла.
ПРобовал на 12в насосах с али по 300р\штука, но при заявленных 100мл\мин они выдают по факту 50-60мл.
Хотел собрать на насосах как у автора, но встала проблема с доставкой — связывался с поставщиком — они готовы отправлять насосы только ЕМС доставкой, которая дороже самого насоса :(
Может подскажете, как и где их купить, без такой доставки лютой?
olekl
24.04.2017 18:50Сразу же напрашивается улучшение — подключаем все напитки, какие есть, вносим в конфиг «номер насоса — напиток», и получаем меню доступных коктейлей в зависимости от подключенных напитков. Моторчиков надо будет побольше, да :)
vagran
24.04.2017 22:42+1Забавный расчёт транзисторного каскада. Биполярный транзистор в таком включении не напряжением, а током управляется. Никакого делителя там не надо. Просто прикинуть нужный базовый ток, чтоб он вошёл в насыщение с некоторым запасом, и поставить один соответствующий резистор. Ну и защитный диод обязателен параллельно мотору.
RazorRunner
24.04.2017 22:54+1А если вытеснять жидкость из бутылок сжатым воздухом, а подачу контролировать клапанами? Это и тише и быстрее будет, имхо. Аквариумный компресор (один на все бутылки) + клапаны на выпуск + весы для контроля налитого.
Vasyutka
24.04.2017 23:28+1Ну, такое уже когда-то было на хабре: https://geektimes.ru/post/257270/ :)
Ivanii
А вычислительной мощности Raspberry Pi хватило?
4te
Вычислительной мощности для чего? Компиляция происходит на локальной машине, а на raspberry pi я загружаю уже скомпилированный бинарник в котором никаких вычислений нет, только включение/выключение GPIO — для этого, конечно, хватает :)
AntonKop
мне кажется это был сарказм…