Code-Outlet von Andreas Bahr, Zürich
Der Durst-O-Mat ist eine Spielmaschine in der Tradition des "einarmigen Banditen". Die Maschine produziert ein zufällig zusammengestelltes Cocktail-Rezept.
Das Gerät wurde von DJ Fridgemonster mit Hilfe eines Lasercutter gebaut. Meine Aufgabe: Hard- & Software der Maschine zu realisieren.
Wenn das Resultat nicht gefällt, können die einzelnen Walzen mittels der korrespondierenden Tasten nochmals gestartet werden.
Die Elektronik der Maschine besteht aus Microcontroller-Komponenten rund um das Modell CORE des chinesischen Herstellers M5. Die Schrittmotoren sind vom TYP NEMA 17.
Die Maschine wird mit einem 12V 1A Netzteil betrieben.
Zur Zeit in Arbeit ist ein weiterer M5 Microcontroller vom Typ ATOM, mit Treiber für einen einzelnen Schrittmotor für die "Gemüse" Auswahl. Trotz identischer Chips funktioniert die bereits bewährte Software dort fehlerhaft.
Ausserdem arbeitet DJ Fridgemonster an weiteren Modulen...
In der M5-Welt wird mit MicroPython in einer Web-IDE programmiert.
Bei meinen ersten Tests machten die Schrittmotoren bei starten verrückte Dinge. Vermutlich haben die Anlauf-Ströme der drei gleichzeitig gestarteten Motoren das Controller-Board überlastet. Das Problem konnte durch gestaffeltes Anlaufen der Motoren gelöst werden.
Den Inhalt der hier angebotenen Datei können Sie in die offizielle IDE kopieren. Sie lässt sich aber auch mit einem normalen Text-Editor lesen.
"""
DURST-O-MAT v0.2.3
Target: M5Stack Core
2022 Andreas Bahr
---------------------
Stepmotor Driver 13.2:
X = Left Wheel
L0 = Start Game
L1 = Left Wheel Trigger
-----------------------
4 Relay:
Relay 1: start game button lamp
Relay 2: wheel buttons lamps
"""
from m5stack import *
from m5ui import *
from uiflow import *
import machine
import i2c_bus
import unit
import time
import random
from numbers import Number
# setup:
motorIntMs = 4
# wheels control variables
trigger = False
triggerX = False
triggerY = False
triggerZ = False
wheelX = 0
wheelY = 0
wheelZ = 0
finitoX = None
finitoY = None
finitoZ = None
def blinkGreen(relayBar):
if relayBar.get_relay_status(1):
relayBar.set_relay_status(1, 0) # green lamp OFF
else:
relayBar.set_relay_status(1, 1) # green lamp ON
# display
setScreenColor(0x33cc00)
lcd.font(lcd.FONT_DejaVu18)
lcd.print('Startup...', 0, 0, 0x000000)
# stepmotor driver setup
pin0 = machine.Pin(16, mode=machine.Pin.OUT, pull=0x00) # step X
pin1 = machine.Pin(17, mode=machine.Pin.OUT, pull=0x00) # direction X
pin1.on() # off = turn left, on = turn right
pin2 = machine.Pin(12, mode=machine.Pin.OUT, pull=0x00) # step Y
pin3 = machine.Pin(13, mode=machine.Pin.OUT, pull=0x00) # direction X
pin3.on() # off = turn left, on = turn right
pin4 = machine.Pin(0, mode=machine.Pin.OUT, pull=0x00) # direction Z
pin4.on() # off = turn left, on = turn right
pin4 = machine.Pin(15, mode=machine.Pin.OUT, pull=0x00) # step Z
i2c0 = i2c_bus.easyI2C(i2c_bus.PORTA, 0x00, freq=400000) # port expander
i2c0.addr=(0x27)
i2c0.write_u8(0x03, 0x0F) # config I/O
# relay module setup
relayBar = unit.get(unit.RELAY4, unit.PORTA)
relayBar.set_mode(1)
# loop-o-grande
lcd.clear()
while True:
randomRecipe = ''
lcd.print('DURST-O-MAT v0.2.3', 0, 0, 0x000000)
relayBar.set_relay_status(1, 1) # green lamp ON
relayBar.set_relay_status(2, 1) # red lamps ON
# wait for trigger's
trigger = (~(i2c0.read_u8(0x00) & 0x01) & 0x01)
triggerX = (i2c0.read_u8(0x00) & 0x02) >> 1
triggerX = not triggerX
triggerY = (i2c0.read_u8(0x00) & 0x04) >> 2
triggerY = not triggerY
triggerZ = (i2c0.read_u8(0x00) & 0x08) >> 3
triggerZ = not triggerZ
if (trigger | triggerX | triggerY | triggerZ):
lcd.print('Play Game', 0, 25, 0x000000)
relayBar.set_relay_status(1, 0) # green lamp OFF
relayBar.set_relay_status(2, 0) # red lamps OFF
if trigger:
wheelX = 1800 + (random.randint(0, 7) * 25) - 60
randomRecipe = str(wheelX + 60)
elif triggerX:
wheelX = 1000 + (random.randint(0, 7) * 25)
randomRecipe = str(wheelX) + '-0-0'
if trigger:
wheelY = 2000 + (random.randint(0, 7) * 25) - 30
randomRecipe = randomRecipe + '-' + str(wheelY + 30)
elif triggerY:
wheelY = 1000 + (random.randint(0, 7) * 25)
randomRecipe = '0-' + str(wheelY) + '-0'
if trigger:
wheelZ = 2200 + (random.randint(0, 7) * 25)
randomRecipe = randomRecipe + '-' + str(wheelZ)
elif triggerZ:
wheelZ = 1000 + (random.randint(0, 7) * 25)
randomRecipe = '0-0-' + str(wheelZ)
lcd.print(randomRecipe, 0, 50, 0x000000)
finitoX = False
finitoY = False
finitoZ = False
# switch motors ON
i2c0.write_u8(0x01, 0x00)
wait_ms(200)
# spin up the wheels, 1 by 1, max. 60 steps
if trigger:
for count in range(30):
pin0.on()
wait_ms(motorIntMs)
pin0.off()
wait_ms(motorIntMs)
for count in range(30):
pin0.on()
pin2.on()
wait_ms(motorIntMs)
pin0.off()
pin2.off()
wait_ms(motorIntMs)
# spin the wheels
i = 0
while not (finitoX & finitoY & finitoZ):
if wheelX == 0:
finitoX = True
else:
pin0.on()
wheelX = wheelX - 1
if wheelY == 0:
finitoY = True
else:
pin2.on()
wheelY = wheelY - 1
if wheelZ == 0:
finitoZ = True
else:
pin4.on()
wheelZ = wheelZ - 1
wait_ms(motorIntMs)
pin0.off()
pin2.off()
pin4.off()
wait_ms(motorIntMs)
# green blinkr
if i == 99:
blinkGreen(relayBar)
i = 0
else:
i = i + 1
# hold position
lcd.print('Motors on hold', 0, 75, 0x000000)
wait_ms(2000)
# switch motors OFF
i2c0.write_u8(0x01, 0x10)
lcd.clear()
wait_ms(20)