Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should this still work? #13

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
sudo: false
language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "3.6"
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# Smart Bartender
Why spend lots of money going out for drinks when you can have your own smart personal bartender at your service right in your home?! This bartender is built from a Raspberry Pi 3 and some common DIY electronics.

## Prerequisites for the Raspberry Pi
Make sure you can connect a screen and keyboard to your Raspberry Pi. I like to use VNC to connect to the Pi. I created a [tutorial](https://www.youtube.com/watch?v=2iVK8dn-6x4) about how to set that up on a Mac.
# Smart Bartender with Adafruit SSD1306

Make sure the following are installed:
* Python 2.7 (should already be installed on most Raspberry Pi)
Expand All @@ -23,7 +19,7 @@ See this [article](https://www.raspberrypi.org/documentation/hardware/raspberryp
Make sure i2c is also configured properly. Type

```
sudo vim /etc/modules
sudo nano /etc/modules
```

in the terminal
Expand All @@ -38,23 +34,24 @@ i2c-dev
press `esc` then `ZZ` to save and exit.

## OLED Setup
The Raspberry Pi Guy has a nice script to setup the OLED screen on your raspberry pi. Download the following repository on your Pi:

https://github.com/the-raspberry-pi-guy/OLED

then navigate to the folder with the terminal
You need to install the Adafruit Python SSD1306 library with

```
cd ~/path/to/directory
sudo python -m pip install --upgrade pip setuptools wheel
sudo pip install Adafruit-SSD1306
```

and run the installation script
Or alternatively:

```
sh OLEDinstall.sh
sudo python -m pip install --upgrade pip setuptools wheel
git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git
cd Adafruit_Python_SSD1306
sudo python setup.py install
```

There is also a [guide](https://learn.adafruit.com/adafruit-oled-displays-for-raspberry-pi/setting-up) on the Adafruit website if you get stuck.
There is also a [guide](https://learn.adafruit.com/ssd1306-oled-displays-with-raspberry-pi-and-beaglebone-black/usage) on the Adafruit website if you get stuck.

## Running the Code

Expand Down Expand Up @@ -135,7 +132,7 @@ from the repository folder. Copy this to your clipboard.
Next, type

```
sudo vim /etc/rc.local
sudo nano /etc/rc.local
```

to open the rc.local file. Next, press `i` to edit. Before the last line, add the following two lines:
Expand Down
114 changes: 80 additions & 34 deletions bartender.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import gaugette.ssd1306
import gaugette.platform
import gaugette.gpio
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import time
import sys
import RPi.GPIO as GPIO
import json
import threading
import traceback
import threading

import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

from dotstar import Adafruit_DotStar
from menu import MenuItem, Menu, Back, MenuContext, MenuDelegate
Expand All @@ -18,10 +25,10 @@
SCREEN_HEIGHT = 64

LEFT_BTN_PIN = 13
LEFT_PIN_BOUNCE = 1000
LEFT_PIN_BOUNCE = 200

RIGHT_BTN_PIN = 5
RIGHT_PIN_BOUNCE = 2000
RIGHT_PIN_BOUNCE = 200

OLED_RESET_PIN = 15
OLED_DC_PIN = 16
Expand All @@ -31,7 +38,15 @@
NEOPIXEL_CLOCK_PIN = 6
NEOPIXEL_BRIGHTNESS = 64

FLOW_RATE = 60.0/100.0
FLOW_RATE = 60.0/1500.0

# Raspberry Pi pin configuration:
RST = 14
# Note the following are only used with SPI:
DC = 15
SPI_PORT = 0
SPI_DEVICE = 0


class Bartender(MenuDelegate):
def __init__(self):
Expand All @@ -51,18 +66,27 @@ def __init__(self):
# configure screen
spi_bus = 0
spi_device = 0
gpio = gaugette.gpio.GPIO()
spi = gaugette.spi.SPI(spi_bus, spi_device)

# Very important... This lets py-gaugette 'know' what pins to use in order to reset the display
self.led = gaugette.ssd1306.SSD1306(gpio, spi, reset_pin=OLED_RESET_PIN, dc_pin=OLED_DC_PIN, rows=self.screen_height, cols=self.screen_width) # Change rows & cols values depending on your display dimensions.
self.led = disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) # Change rows & cols values depending on your display dimensions.

# Initialize library.
self.led.begin()
self.led.clear_display()

# Clear display.
self.led.clear()
self.led.display()
self.led.invert_display()
time.sleep(0.5)
self.led.normal_display()
time.sleep(0.5)


# Create image buffer.
# Make sure to create image with mode '1' for 1-bit color.
self.image = Image.new('1', (self.screen_width, self.screen_height))

# Load default font.
self.font = ImageFont.load_default()

# Create drawing object.
self.draw = ImageDraw.Draw(self.image)

# load the pump configuration from file
self.pump_configuration = Bartender.readPumpConfiguration()
Expand Down Expand Up @@ -99,10 +123,6 @@ def startInterrupts(self):
GPIO.add_event_detect(self.btn1Pin, GPIO.FALLING, callback=self.left_btn, bouncetime=LEFT_PIN_BOUNCE)
GPIO.add_event_detect(self.btn2Pin, GPIO.FALLING, callback=self.right_btn, bouncetime=RIGHT_PIN_BOUNCE)

def stopInterrupts(self):
GPIO.remove_event_detect(self.btn1Pin)
GPIO.remove_event_detect(self.btn2Pin)

def buildMenu(self, drink_list, drink_options):
# create a new main menu
m = Menu("Main Menu")
Expand Down Expand Up @@ -131,7 +151,7 @@ def buildMenu(self, drink_list, drink_options):
# add pump menus to the configuration menu
configuration_menu.addOptions(pump_opts)
# add a back button to the configuration menu
configuration_menu.addOption(Back("Back"))
configuration_menu.addOption(Back("Zurück"))
# adds an option that cleans all pumps to the configuration menu
configuration_menu.addOption(MenuItem('clean', 'Clean'))
configuration_menu.setParent(m)
Expand Down Expand Up @@ -220,14 +240,13 @@ def clean(self):
# sleep for a couple seconds to make sure the interrupts don't get triggered
time.sleep(2);

# reenable interrupts
# self.startInterrupts()
self.running = False

def displayMenuItem(self, menuItem):
print menuItem.name
self.led.clear_display()
self.led.draw_text2(0,20,menuItem.name,2)
self.led.clear()
self.draw.rectangle((0,0,self.screen_width,self.screen_height), outline=0, fill=0)
self.draw.text((0,20),str(menuItem.name), font=self.font, fill=255)
self.led.image(self.image)
self.led.display()

def cycleLights(self):
Expand Down Expand Up @@ -272,8 +291,10 @@ def pour(self, pin, waitTime):
def progressBar(self, waitTime):
interval = waitTime / 100.0
for x in range(1, 101):
self.led.clear_display()
self.led.clear()
self.draw.rectangle((0,0,self.screen_width,self.screen_height), outline=0, fill=0)
self.updateProgressBar(x, y=35)
self.led.image(self.image)
self.led.display()
time.sleep(interval)

Expand Down Expand Up @@ -327,32 +348,57 @@ def makeDrink(self, drink, ingredients):
self.running = False

def left_btn(self, ctx):
print("LEFT_BTN pressed")
if not self.running:
self.running = True
self.menuContext.advance()
print("Finished processing button press")
self.running = False

def right_btn(self, ctx):
print("RIGHT_BTN pressed")
if not self.running:
self.running = True
self.menuContext.select()
print("Finished processing button press")
self.running = 2
print("Starting button timeout")

def updateProgressBar(self, percent, x=15, y=15):
height = 10
width = self.screen_width-2*x
for w in range(0, width):
self.led.draw_pixel(w + x, y)
self.led.draw_pixel(w + x, y + height)
self.draw.point((w + x, y), fill=255)
self.draw.point((w + x, y + height), fill=255)
for h in range(0, height):
self.led.draw_pixel(x, h + y)
self.led.draw_pixel(self.screen_width-x, h + y)
self.draw.point((x, h + y), fill=255)
self.draw.point((self.screen_width-x, h + y), fill=255)
for p in range(0, percent):
p_loc = int(p/100.0*width)
self.led.draw_pixel(x + p_loc, h + y)
self.draw.point((x + p_loc, h + y), fill=255)

def run(self):
self.startInterrupts()
# main loop
try:
while True:
time.sleep(0.1)
try:

try:

while True:
letter = raw_input(">")
if letter == "l":
self.left_btn(False)
if letter == "r":
self.right_btn(False)

except EOFError:
while True:
time.sleep(0.1)
if self.running not in (True,False):
self.running -= 0.1
if self.running == 0:
self.running = False
print("Finished button timeout")

except KeyboardInterrupt:
GPIO.cleanup() # clean up GPIO on CTRL+C exit
Expand Down