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
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):
if not self.started_async:
self.started_async = True
self._stepperMinute.start()
self._stepperHour.start()
loop = asyncio.get_event_loop()
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:
def __init__(self,pins,stepsPerRev=400,stepDurationMs=10,inverted=False):
self._pins = [Pin(p, Pin.OUT) for p in pins]
self.stepnum = 0
self.rotDirection = 1
self._rotTarget = 0
self.reset()
self.stepDurationMs = stepDurationMs
self._speedMs = 0
self._lastStepTime = time.time()
self.stepsPerRev=stepsPerRev
self.started_async = False
self.inverted = inverted
loop = asyncio.get_event_loop()
loop.create_task(self._update_async())
def start(self):
if not self.started_async:
self.started_async = True
loop = asyncio.get_event_loop()
loop.create_task(self._update_async())
def reset(self):
self.stepnum = 0
self._rotTarget = 0
self.rotDirection = 0
def _setPins(self,level):
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)
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
it should rotate left or right"""
self._rotTarget = int(target*self.stepsPerRev)
if normalise:
rotTargetNorm = self._rotTarget%self.stepsPerRev
stepsNorm = self.stepnum%self.stepsPerRev
self._rotTarget = self.stepnum+rotTargetNorm-stepsNorm
if (self._rotTarget-self.stepnum) > self.stepsPerRev/2:
self._rotTarget-=self.stepsPerRev
elif(self._rotTarget-self.stepnum) < -self.stepsPerRev/2:
self._rotTarget+=self.stepsPerRev
it should rotate left or right.
If target is None moves infinitely in direction
(if direction is 0 then hold position with power)."""
if target == None:
self._rotTarget = None
self.rotDirection = direction
else:
self._rotTarget = int(target*self.stepsPerRev)
if normalise:
rotTargetNorm = self._rotTarget%self.stepsPerRev
stepsNorm = self.stepnum%self.stepsPerRev
self._rotTarget = self.stepnum+rotTargetNorm-stepsNorm
if (self._rotTarget-self.stepnum) > self.stepsPerRev/2:
self._rotTarget-=self.stepsPerRev
elif(self._rotTarget-self.stepnum) < -self.stepsPerRev/2:
self._rotTarget+=self.stepsPerRev
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())
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):
while(True):
@ -59,6 +65,7 @@ class Stepper:
if not self.isAtTarget():
self._update()
else:
self.rotDirection = 0
self.disablePower()
def _update(self):

96
main.py
View File

@ -1,11 +1,14 @@
import time
import machine
import uasyncio as asyncio
import DS3231
import Button
import uasyncio as asyncio
import LED
import HousingLEDs
import Buzzer
import StepperL298M
import StepperClock
import neopixel
import Screens
#Async
loop = asyncio.get_event_loop()
@ -18,69 +21,36 @@ try:
except:
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
stepDurationMs = 8
stepperminu = StepperL298M.Stepper([19,21,22,23],inverted=False,stepDurationMs=stepDurationMs)
stepperhour = StepperL298M.Stepper([12,27,26,25],inverted=True, stepDurationMs=stepDurationMs)
stepperminu = StepperL298M.Stepper([19,21,22,23],inverted=False)
stepperhour = StepperL298M.Stepper([12,27,26,25],inverted=True)
#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)
middleButtonLED = machine.Pin(33,machine.Pin.OUT)
rightButtonLED = machine.Pin(13,machine.Pin.OUT)
buttons = (leftButton,middleButton,rightButton)
leds = (leftButtonLED,middleButtonLED,rightButtonLED)
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)
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()
loop.run_until_complete(run_screens())