Робот-бармен NALIVATOR-9000
5 октября 2017 г. golang raspberry_pi
Кросс-пост моей статьи на Хабрахабре. Пару лет назад я наткнулся на проект Bartendro на Kickstarter. Мне понравилась идея, и я решил, что идеальное применение для моего недавно приобретенного Raspberry Pi найдено.
Я прикинул какие детали понадобятся, и приступил к DIY реализации робота-бармена. Вот что в итоге получилось:
Перистальтический насос - это такой насос который толкает по трубке её содержимое, как будто тюбик с пастой выдавливает. Соответственно, один конец опускаем в бутылку, а второй в стакан. Гифка с Википедии с принципом действия: Похожие на оригинальные из 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 мА на пин.
Теперь можно идти в ближайший магазин радиодеталей и пробовать собирать.
$GOOS=linux GOARCH=arm GOARM=6 go build
Так как у насосов нет никаких датчиков объема налитого, но известна пропускная способность, то объем можно контролировать через время работы насоса. Эмперическим путем я выяснил - чтобы налить 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
}
]
}
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)
}
}
Осталось добавить веб-интерфейс и все готово. Насчет корпуса я не стал заморачиваться и разместил все в икеевской коробке. В этот момент я понял, что дизайнера из меня не выйдет. В общем над внешним обликом еще стоит поработать.
Когда пришло время испытаний, я пригласил друзей провести нагрузочное тестирование, но перед их приходом понял, что веб-интерфейс это не совсем удобно - он не доступен из интернета, а подключаться к запароленной wi-fi сети, вбивать IP-адрес в браузере… слишком сложно. Тогда я добавил telegram-бота, который ждёт что ему напишут имя коктейля и наливает его. Я не буду описывать как создать бота, т.к. уже есть множество хороших статей на эту тему, в том числе и для Golang.
Также я решил добавить синтез речи, воспользовавшись Yandex SpeechKit. API этого сервиса очень прост, а лицензионное соглашение позволяет пользоваться им бесплатно в некоммерческих целях. Перед отправкой сообщения от telegram-бота, я прогоняю фразу через SpeechKit, в ответ получаю .wav-файл и воспроизвожу его через подключенный по 3.5mm-jack динамик.
За ваше здоровье!
Оригинал: https://habrahabr.ru/post/327220/