added Screens

This commit is contained in:
Nils Schulte 2020-03-19 22:34:50 +01:00
parent d95bfb212d
commit ca058725e8
9 changed files with 331 additions and 93 deletions

View File

@ -39,4 +39,4 @@ class Button():
pass pass
def isPushed(self): def isPushed(self):
return self.pin.value() ^ self.inverted return not (self.pin.value() ^ self.inverted)

69
Buzzer.py Normal file
View File

@ -0,0 +1,69 @@
import machine
import uasyncio as asyncio
c = 261 #Hz
d = 294 #Hz
e = 329 #Hz
f = 349 #Hz
g = 392 #Hz
a = 440 #Hz
b = 493 #Hz
C = 523 #Hz
# (Duration,Freq)
# If Last Duration is None play endlessly
# 0: Silent
# 1: BeepBeep
# 2: Alle Meine Entchen
SOUNDS = [((0,None),),\
((700,1000),(100,None),(600,1000)),\
((400,c),(100,None),(400,d),(100,None),(400,e),(100,None),(400,f),(100,None),\
(900,g),(100,None),(900,g),(100,None),(400,a),(100,None),(400,a),(100,None),\
(400,a),(100,None),(400,a),(100,None),(1900,g),(100,None),(400,a),(100,None),\
(400,a),(100,None),(400,a),(100,None),(400,a),(100,None),(1900,g),(100,None),\
(400,f),(100,None),(400,f),(100,None),(400,f),(100,None),(400,f),(100,None),\
(900,e),(100,None),(900,e),(100,None),(400,d),(100,None),(400,d),(100,None),\
(400,d),(100,None),(400,d),(100,None),(2000,c))]#,(None,None)
class Buzzer():
def __init__(self,pin,duty = 100):
self._pwm = machine.PWM(machine.Pin(2), freq=0, duty=0)
self.sound = None
self.duty = duty
self.newSound = True
loop = asyncio.get_event_loop()
loop.create_task(self._update_async())
async def _update_async(self):
while True:
if self.sound == None:
await asyncio.sleep_ms(200)
self._pwm.duty(0)
else:
self.newSound = False
for i in range(len(self.sound)):
s = self.sound[i]
if s[0] == None:
i = 0
if (s[1] != None):
self._pwm.freq(s[1])
self._pwm.duty(self.duty)
else:
self._pwm.duty(0)
await asyncio.sleep_ms(s[0])
if self.newSound:
break
if (not self.newSound):
self.sound = None
self.newSound = False
def playSound(self,sound):
self.newSound = True
self.sound = sound
def stop(self):
self.sound = None
def isPlaying(self):
return self.sound == None

31
HousingLEDs.py Normal file
View File

@ -0,0 +1,31 @@
import uasyncio as asyncio
import machine
import neopixel
class LEDs():
def __init__(self, pin):
self.neop = neopixel.NeoPixel(machine.Pin(pin, machine.Pin.OUT),5)
self.rate = 0
self.clear()
loop = asyncio.get_event_loop()
loop.create_task(self._update_async())
async def _update_async(self):
while True:
if self.rate <= 0:
await asyncio.sleep_ms(200)
else:
self.toggle()
await asyncio.sleep_ms(int(500 / self.rate))
def fill(self,color):
self.neop.fill(color)
self.neop.write()
def clear(self):
self.fill((0,0,0))
def upper(self,color):
self.neop[3] = color
self.neop.write()

40
LED.py Normal file
View File

@ -0,0 +1,40 @@
import uasyncio as asyncio
import machine
class LED():
def __init__(self, pin):
self.pin = machine.Pin(pin,machine.Pin.OUT)
self.rate = 0
loop = asyncio.get_event_loop()
loop.create_task(self._update_async())
async def _update_async(self):
while True:
if self.rate <= 0:
await asyncio.sleep_ms(200)
else:
self.toggle()
await asyncio.sleep_ms(int(500 / self.rate))
def toggle(self):
self.pin.value(not self.pin.value())
def flash(self, rate):
"""rate:\t flashing speed in Herz"""
self.rate = rate
def on(self,overwriteFlashing=True):
self.pin.on()
if overwriteFlashing:
self.rate = 0
def off(self,overwriteFlashing=True):
self.pin.off()
if overwriteFlashing:
self.rate = 0
def value(self,value=None):
if value!=None:
self.pin.value(value)
return self.pin.value()

121
Screens.py Normal file
View File

@ -0,0 +1,121 @@
import StepperClock
import uasyncio as asyncio
import Buzzer
import Settings
class ClockScreen():
def __init__(self,stepperhour,stepperminu,buttons,leds):
self.clock = StepperClock.StepperClock(stepperhour,stepperminu)
self.running = False
self.buttons = buttons
self.leds = leds
def stopIfAllPressed(self,button):
self.leds[button].on()
for b in self.buttons:
if not b.isPushed():
break
else:
self.running = False
def __await__(self):
for i,b in enumerate(self.buttons):
b.setCallbacks(onPushDown=lambda i=i:self.stopIfAllPressed(i),onPushUp=lambda i=i:self.leds[i].off())
self.running = True
self.clock.start()
while self.running:
await asyncio.sleep_ms(200)
self.clock.stop()
__iter__ = __await__ # https://github.com/micropython/micropython/issues/2678
class SettingsScreen():
def __init__(self,stepperhour,stepperminu,buttons,leds,housingLEDs,buzzer):
self.stepperminu = stepperminu
self.stepperhour = stepperhour
self.running = False
self.buttons = buttons
self.leds = leds
self.housingLEDs = housingLEDs
self.buzzer = buzzer
# TODO load these form file
def onButtonPressed(self,button):
self.leds[button].on(overwriteFlashing=False)
for b in self.buttons:
if not b.isPushed():
break
else:
self.running = False
return
if not self.buttons[1].isPushed():
if button == 0 :
if self.mode == 0:
self.stepperminu.rotateTo(direction=1)
if self.mode == 1:
self.stepperhour.rotateTo(direction=1)
elif button == 2:
if self.mode == 0:
self.stepperminu.rotateTo(direction=-1)
if self.mode == 1:
self.stepperhour.rotateTo(direction=-1)
def onButtonReleased(self,button):
self.leds[button].off(overwriteFlashing=False)
if button == 0:#left
if self.mode == 0 or self.mode == 1:
self.stepperminu.stop()
self.stepperhour.stop()
if self.mode == 3:
Settings.selectedSound =(Settings.selectedSound -1) % len(Buzzer.SOUNDS)
self.buzzer.playSound(Buzzer.SOUNDS[Settings.selectedSound ])
elif button == 2:#right
if self.mode == 0 or self.mode == 1:
self.stepperminu.stop()
self.stepperhour.stop()
if self.mode == 3:
Settings.selectedSound =(Settings.selectedSound +1) % len(Buzzer.SOUNDS)
self.buzzer.playSound(Buzzer.SOUNDS[Settings.selectedSound ])
elif button == 1: #middle
self.mode=(self.mode+1)%4
if self.mode == 3:
self.buzzer.playSound(Buzzer.SOUNDS[Settings.selectedSound ])
else:
self.buzzer.stop()
if self.mode == 2:
self.leds[0].flash(0.7)
self.leds[1].flash(0.7)
self.leds[2].flash(0.7)
else:
self.leds[0].off()
self.leds[1].off()
self.leds[2].off()
if self.mode == 0 or self.mode == 1:
self.housingLEDs.upper((50,50,50))
else:
self.housingLEDs.clear()
def __await__(self):
self.mode = 0
self.stepperminu.rotateTo(0)
self.stepperhour.rotateTo(0)
while not self.stepperhour.isAtTarget() or not self.stepperminu.isAtTarget():
await asyncio.sleep_ms(200)
self.housingLEDs.upper((50,50,50))
for led in self.leds:
led.off()
for i,b in enumerate(self.buttons):
b.setCallbacks(onPushDown=lambda i=i:self.onButtonPressed(i),onPushUp=lambda i=i:self.onButtonReleased(i))
self.running = True
while self.running:
await asyncio.sleep_ms(200)
for led in self.leds:
led.off()
self.housingLEDs.clear()
self.stepperhour.reset()
self.stepperminu.reset()
__iter__ = __await__ # https://github.com/micropython/micropython/issues/2678

2
Settings.py Normal file
View File

@ -0,0 +1,2 @@
selectedSound = 0

View File

@ -12,8 +12,6 @@ class StepperClock:
def start(self): def start(self):
if not self.started_async: if not self.started_async:
self.started_async = True self.started_async = True
self._stepperMinute.start()
self._stepperHour.start()
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
loop.create_task(self._update_async()) loop.create_task(self._update_async())

View File

@ -7,21 +7,19 @@ stepping = [[1,0,1,0],[1,0,0,0],[1,0,0,1],[0,0,0,1],[0,1,0,1],[0,1,0,0],[0,1,1,0
class Stepper: class Stepper:
def __init__(self,pins,stepsPerRev=400,stepDurationMs=10,inverted=False): def __init__(self,pins,stepsPerRev=400,stepDurationMs=10,inverted=False):
self._pins = [Pin(p, Pin.OUT) for p in pins] self._pins = [Pin(p, Pin.OUT) for p in pins]
self.stepnum = 0 self.reset()
self.rotDirection = 1
self._rotTarget = 0
self.stepDurationMs = stepDurationMs self.stepDurationMs = stepDurationMs
self._speedMs = 0 self._speedMs = 0
self._lastStepTime = time.time() self._lastStepTime = time.time()
self.stepsPerRev=stepsPerRev self.stepsPerRev=stepsPerRev
self.started_async = False
self.inverted = inverted self.inverted = inverted
loop = asyncio.get_event_loop()
loop.create_task(self._update_async())
def start(self): def reset(self):
if not self.started_async: self.stepnum = 0
self.started_async = True self._rotTarget = 0
loop = asyncio.get_event_loop() self.rotDirection = 0
loop.create_task(self._update_async())
def _setPins(self,level): def _setPins(self,level):
self._pins[0].value(level[0]) self._pins[0].value(level[0])
@ -33,25 +31,33 @@ class Stepper:
#return ((self._rotTarget - self.stepnum)*self.rotDirection)%self.stepsPerRev #return ((self._rotTarget - self.stepnum)*self.rotDirection)%self.stepsPerRev
return ((self._rotTarget - self.stepnum)*self.rotDirection) return ((self._rotTarget - self.stepnum)*self.rotDirection)
def rotateTo(self, target,duration=0,direction=0,normalise = True): def rotateTo(self, target=None,duration=0,direction=0,normalise = True):
"""sets the rotation target and (if direction == 0) calculates if """sets the rotation target and (if direction == 0) calculates if
it should rotate left or right""" it should rotate left or right.
self._rotTarget = int(target*self.stepsPerRev) If target is None moves infinitely in direction
if normalise: (if direction is 0 then hold position with power)."""
rotTargetNorm = self._rotTarget%self.stepsPerRev if target == None:
stepsNorm = self.stepnum%self.stepsPerRev self._rotTarget = None
self._rotTarget = self.stepnum+rotTargetNorm-stepsNorm self.rotDirection = direction
if (self._rotTarget-self.stepnum) > self.stepsPerRev/2: else:
self._rotTarget-=self.stepsPerRev self._rotTarget = int(target*self.stepsPerRev)
elif(self._rotTarget-self.stepnum) < -self.stepsPerRev/2: if normalise:
self._rotTarget+=self.stepsPerRev rotTargetNorm = self._rotTarget%self.stepsPerRev
stepsNorm = self.stepnum%self.stepsPerRev
if not self.isAtTarget(): self._rotTarget = self.stepnum+rotTargetNorm-stepsNorm
if (direction == 0): if (self._rotTarget-self.stepnum) > self.stepsPerRev/2:
self.rotDirection = 1 if (self._rotTarget > self.stepnum) else -1 self._rotTarget-=self.stepsPerRev
else: elif(self._rotTarget-self.stepnum) < -self.stepsPerRev/2:
self.rotDirection = direction self._rotTarget+=self.stepsPerRev
self._speedMs = max(int(self.stepDurationMs),duration*1000/self.getStepsToTarget()) if not self.isAtTarget():
if (direction == 0):
self.rotDirection = 1 if (self._rotTarget > self.stepnum) else -1
else:
self.rotDirection = direction
self._speedMs = max(int(self.stepDurationMs),duration*1000/self.getStepsToTarget())
def stop(self):
self._rotTarget = self.stepnum
async def _update_async(self): async def _update_async(self):
while(True): while(True):
@ -59,6 +65,7 @@ class Stepper:
if not self.isAtTarget(): if not self.isAtTarget():
self._update() self._update()
else: else:
self.rotDirection = 0
self.disablePower() self.disablePower()
def _update(self): def _update(self):

96
main.py
View File

@ -1,11 +1,14 @@
import time import time
import machine import machine
import uasyncio as asyncio
import DS3231 import DS3231
import Button import Button
import uasyncio as asyncio import LED
import HousingLEDs
import Buzzer
import StepperL298M import StepperL298M
import StepperClock
import neopixel import Screens
#Async #Async
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
@ -17,70 +20,37 @@ try:
rtc.init(dsRtc.DateTime()+[0]) rtc.init(dsRtc.DateTime()+[0])
except: except:
print("Error on DS3231-Inititalisation") print("Error on DS3231-Inititalisation")
housingLEDs = neopixel.NeoPixel(machine.Pin(16, machine.Pin.OUT),5)
housingLEDs.fill((0,0,0))
housingLEDs.write()
Buzzer = machine.PWM(machine.Pin(2), freq=10000, duty=0) #Init Buzzer
buzzer = Buzzer.Buzzer(pin=2)
#Initalise the Motors #Initalise the Motors
stepDurationMs = 8 stepperminu = StepperL298M.Stepper([19,21,22,23],inverted=False)
stepperminu = StepperL298M.Stepper([19,21,22,23],inverted=False,stepDurationMs=stepDurationMs) stepperhour = StepperL298M.Stepper([12,27,26,25],inverted=True)
stepperhour = StepperL298M.Stepper([12,27,26,25],inverted=True, stepDurationMs=stepDurationMs)
#Init LEDs
housingLEDs = HousingLEDs.LEDs(pin=16)
leftButtonLED = LED.LED(13)
middleButtonLED = LED.LED(33)
rightButtonLED = LED.LED(32)
#Init Buttons
leftButton = Button.Button(pin=34,inverted=True)
middleButton = Button.Button(pin=39,inverted=True)
rightButton = Button.Button(pin=36,inverted=True)
leftButtonLED = machine.Pin(32,machine.Pin.OUT) buttons = (leftButton,middleButton,rightButton)
middleButtonLED = machine.Pin(33,machine.Pin.OUT) leds = (leftButtonLED,middleButtonLED,rightButtonLED)
rightButtonLED = machine.Pin(13,machine.Pin.OUT)
modus = 0
screens = (Screens.ClockScreen(stepperhour,stepperminu,buttons,leds),\
Screens.SettingsScreen(stepperhour,stepperminu,buttons,leds,housingLEDs,buzzer))
async def run_screens():
global modus,screens
while True:
await screens[modus%len(screens)]
modus += 1
clock = StepperClock.StepperClock(stepperhour,stepperminu) loop.run_until_complete(run_screens())
def leftButtonClickDown():
leftButtonLED.on()
def leftButtonClickUp():
leftButtonLED.off()
def leftButtonClick():
if(clock.isRunning()):
stepperminu.stepnum = (stepperminu.stepnum+8)%stepperminu.stepsPerRev
else:
stepperminu.rotateTo(stepperminu.getOrientation()+0.25)
leftButton = Button.Button(pin=36,onPushDown=leftButtonClickDown,onPushUp=leftButtonClickUp,onClick=leftButtonClick,inverted=True)
def rightButtonClickDown():
rightButtonLED.on()
def rightButtonClickUp():
rightButtonLED.off()
def rightButtonClick():
if(clock.isRunning()):
stepperminu.stepnum = (stepperminu.stepnum+8)%stepperminu.stepsPerRev
else:
stepperminu.rotateTo(stepperminu.getOrientation()-0.25)
rightButton = Button.Button(pin=34,onPushDown=rightButtonClickDown,onPushUp=rightButtonClickUp,onClick=rightButtonClick,inverted=True)
def middleButtonClickDown():
pass
def middleButtonClickUp():
pass
def middleButtonClick():
middleButtonLED.value(not middleButtonLED.value())
if middleButtonLED.value():
clock.stop()
stepperminu.rotateTo(0)
stepperhour.rotateTo(0)
housingLEDs.fill((255,0,255))
housingLEDs.write()
else:
clock.start()
housingLEDs.fill((0,0,0))
housingLEDs.write()
middleButton = Button.Button(pin=39,onPushDown=middleButtonClickDown,onPushUp=middleButtonClickUp,onClick=middleButtonClick,inverted=True)
clock.start()
loop.run_forever()