diff --git a/Buzzer.py b/Buzzer.py index c7ece3f..027b946 100644 --- a/Buzzer.py +++ b/Buzzer.py @@ -24,13 +24,13 @@ ALARMTONES = (((300,1200),(100,None),(200,1200),(300,None),(None,10)), ((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,a),(100,None),(400,a),(100,None),(400,a),(100,None),(1600,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)),) + (400,d),(100,None),(400,d),(100,None),(1600,c)),) class Buzzer(): - def __init__(self,pin,duty = 100): + def __init__(self,pin,duty = 1000): self._pwm = machine.PWM(machine.Pin(2), freq=0, duty=0) self.sound = None self.duty = duty @@ -46,7 +46,7 @@ class Buzzer(): else: self.newSound = False timesPlayed = 0 - print("Play sound!") + #print("Play sound!") for i in range(len(self.sound)): s = self.sound[i] if s[0] == None: @@ -56,8 +56,8 @@ class Buzzer(): i = 0 timesPlayed += 1 if (s[1] != None): - #self._pwm.freq(s[1]) - #self._pwm.duty(self.duty) + self._pwm.freq(s[1]) + self._pwm.duty(self.duty) pass else: self._pwm.duty(0) diff --git a/Hardware.py b/Hardware.py index 387b3ce..ef31256 100644 --- a/Hardware.py +++ b/Hardware.py @@ -5,7 +5,7 @@ import StepperL298M import HousingLEDs import LED import Button - +import HousingCapButton #Initialise the time module with the RTC try: @@ -34,6 +34,7 @@ leftButton = Button.Button(pin=34,inverted=True) middleButton = Button.Button(pin=39,inverted=True) rightButton = Button.Button(pin=36,inverted=True) +housingButton = HousingCapButton.HousingCapButton(pin=15) buttons = (leftButton,middleButton,rightButton) leds = (leftButtonLED,middleButtonLED,rightButtonLED) \ No newline at end of file diff --git a/HousingCapButton.py b/HousingCapButton.py new file mode 100644 index 0000000..066c4dc --- /dev/null +++ b/HousingCapButton.py @@ -0,0 +1,23 @@ +import uasyncio as asyncio +import machine +import Hardware as HW + +class HousingCapButton(): + def __init__(self, pin): + self.tp = machine.TouchPad(machine.Pin(15)) + reading = self.tp.read() + self.value_avrg = [reading]*3 + self.value_avrg2 = [reading]*4 + loop = asyncio.get_event_loop() + #loop.create_task(self._update_async()) + + async def _update_async(self): + while True: + await asyncio.sleep_ms(100) + reading = self.tp.read() + self.value_avrg = [reading*(10**-i) + (1-(10**-i))*v for i,v in enumerate(self.value_avrg)] + #self.value_avrg2 = [max(v,max(self.value_avrg[1:i])) for i,v in enumerate(self.value_avrg[1:])] + print("\t".join([str(v) for v in self.value_avrg])) + if self.value_avrg[1] <= 80: #and not HW.buzzer.isPlaying() + HW.buzzer.playSound(HW.Buzzer.BEEP) + diff --git a/HousingLEDs.py b/HousingLEDs.py index d3238ae..e6e8904 100644 --- a/HousingLEDs.py +++ b/HousingLEDs.py @@ -2,6 +2,9 @@ import uasyncio as asyncio import machine import neopixel +WHITE = (140,70,255) +YELLOW = (127,0,255) + class LEDs(): def __init__(self, pin): self.neop = neopixel.NeoPixel(machine.Pin(pin, machine.Pin.OUT),5) @@ -26,7 +29,26 @@ class LEDs(): def clear(self): self.fill((0,0,0)) + + def lower(self,color): + self.neop[1] = color + self.neop.write() + + def right(self,color): + self.neop[2] = color + self.neop.write() + def upper(self,color): self.neop[3] = color self.neop.write() + def left(self,color): + self.neop[4] = color + self.neop.write() + + def set(self,colors): + self.neop[0] = (0,0,0) + for i,c in enumerate(colors): + self.neop[i+1] = c + self.neop.write() + diff --git a/Screens.py b/Screens.py index fca4b45..a199496 100644 --- a/Screens.py +++ b/Screens.py @@ -3,64 +3,8 @@ import uasyncio as asyncio import Buzzer import Settings import Hardware as HW - -class InitHandsScreen(): - def __await__(self): - self.running = True - self.mode=0 # 0: Minutes, 1: Hours - HW.housingLEDs.fill((0,0,0)) - HW.stepperminu.rotateTo(0) - HW.stepperhour.rotateTo(0) - HW.leds[1].flash(0.7) - for number,button in enumerate(HW.buttons): - button.setCallbacks(\ - onPushDown=lambda i=number:self.onButtonPressed(i),\ - onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime)) - # Wait for the Hands to move up - while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget(): - await asyncio.sleep_ms(200) - HW.housingLEDs.upper((50,50,50)) - - while self.running: - await asyncio.sleep_ms(200) - HW.housingLEDs.fill((0,0,0)) - self.cleanup() - - __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 - def finish(self): - self.running = False - for b in HW.buttons: - b.setCallbacks()#Clear Callbacks - for l in HW.leds: - l.off() - def __init__(self): - self.running = False - - def onButtonPressed(self,button): - if button == 1: - HW.leds[button].on(overwriteFlashing=False) - else: - HW.leds[button].on() - if self.mode == 0: - HW.stepperminu.rotateTo(direction=(1 if button == 0 else -1)) - elif self.mode == 1: - HW.stepperhour.rotateTo(direction=(1 if button == 0 else -1)) - - def onButtonReleased(self,button,time): - HW.leds[button].off(overwriteFlashing=(button!=1)) - if button == 1: - self.mode+=1 - if self.mode == 2: - self.finish() - else: - if self.mode == 0: - HW.stepperminu.stop() - else: - HW.stepperhour.stop() - - def cleanup(self): - HW.stepperhour.reset() # Set the new Zero - HW.stepperminu.reset() +import math +import network class ClockScreen(): def __await__(self): @@ -81,7 +25,7 @@ class ClockScreen(): self.light = False self.clock = StepperClock.StepperClock() - COLORS = ((255,0,0),(255,0,127),(127,0,255),(0,0,255),(0,127,255),(0,255,127),(0,255,0),(127,255,0),(255,127,0)) + COLORS = ((255,0,0),(255,0,127),(127,0,255),(0,0,255),(0,127,255),(140,70,255),(0,255,127),(0,255,0),(127,255,0),(255,127,0)) BRIGHTNESS = (5,10,50,100,160,255) def onButtonPressed(self,button): @@ -93,7 +37,7 @@ class ClockScreen(): if button == 0: Settings.selectedBrightness=(Settings.selectedBrightness+1)%len(ClockScreen.BRIGHTNESS) elif button == 1: - if pushDownTime > 1100: + if pushDownTime > 700: self.finish() return self.light = not self.light @@ -111,48 +55,274 @@ class ClockScreen(): def cleanup(self): self.clock.stop() -class RingtoneSettingsScreen(): +class InitHandsScreen(): + def __iter__(self): + HW.stepperminu.rotateTo(0) + HW.stepperhour.rotateTo(0) + HW.housingLEDs.upper((50,50,50)) + timeScreen = GetTimeScreen(\ + startTime=(0,0),\ + onStart=lambda _: HW.buzzer.playSound(HW.Buzzer.BEEP),\ + onSelectedTimeChange=None,\ + onPicked=lambda _: Settings.save()) + await timeScreen + HW.stepperhour.reset() # Set the new Zero + HW.stepperminu.reset() + HW.housingLEDs.fill((0,0,0)) + +class SetAlarmTimeScreen(): + def setAlarmTime(self,selectedTime): + Settings.alarmTime = selectedTime + def __iter__(self): + HW.housingLEDs.fill((255,0,0)) + timeScreen = GetTimeScreen(\ + startTime=Settings.alarmTime,\ + onStart=lambda _: HW.buzzer.playSound(HW.Buzzer.BEEP),\ + onSelectedTimeChange=self.setAlarmTime,\ + onPicked=lambda _: Settings.save()) + await timeScreen + HW.housingLEDs.fill((0,0,0)) + +class RingtoneSettingsScreen(): + def playAndSetSound(self,number): + Settings.selectedSound = number + HW.buzzer.playSound(HW.Buzzer.ALARMTONES[number]) + def __iter__(self): + numberScreen = GetNumberScreen([i for i in range(len(HW.Buzzer.ALARMTONES))],\ + startNumber=Settings.selectedSound,\ + onStart=self.playAndSetSound,\ + onNumberChange=self.playAndSetSound,\ + onPicked=lambda _:Settings.save()) + await numberScreen + +class ShowIpScreen(): + def __init__(self): + self.IP = "0" + async def beepAndWaitIP(self,digitShown): + HW.housingLEDs.fill(HW.HousingLEDs.WHITE) + ipdigit = digitShown+self.IP[:digitShown].count(".") + if (ipdigit >= len(self.IP) or self.IP[ipdigit] == "."): + HW.buzzer.playSound(HW.Buzzer.BEEPBEEP) + await asyncio.sleep_ms(1800) + else: + HW.buzzer.playSound(HW.Buzzer.BEEP) + await asyncio.sleep_ms(1100) + HW.housingLEDs.fill((0,0,0)) + def __iter__(self): + sta_if = network.WLAN(network.STA_IF) + if sta_if.status() != network.STAT_GOT_IP: + HW.housingLEDs.fill((255,0,0)) + HW.buzzer.playSound(HW.Buzzer.BEEP) + await asyncio.sleep_ms(1000) + else: + self.IP = sta_if.ifconfig()[0] + showNumberScreen = ShowNumberScreen(number=[int(i) for i in self.IP.replace(".","")],onDigitShown=self.beepAndWaitIP) + await showNumberScreen + HW.housingLEDs.fill((0,0,0)) + +class ShowNumberScreen(): + def __init__(self,number,onDigitShown): + self.number = number + self.digit_shown = 0 + self.onDigitShown = onDigitShown + self.running = False + def onButtonReleased(self,pushDownTime): + HW.leds[1].off() + if pushDownTime > 700: + self.running = False + def __await__(self): + self.running = True + HW.buttons[1].setCallbacks(onPushUp=self.onButtonReleased,onPushDown=lambda :HW.leds[1].on()) + HW.stepperminu.rotateTo(0) + HW.stepperhour.rotateTo(0) + self.digit_shown = 0 + await self.onDigitShown(self.digit_shown) + while self.digit_shown < len(self.number): + HW.stepperminu.rotateTo(-((self.number[self.digit_shown]%10)/12)) + while self.running and (not HW.stepperminu.isAtTarget() or not HW.stepperhour.isAtTarget()): + await asyncio.sleep_ms(200) + if not self.running: + return + self.digit_shown=self.digit_shown+1 + await self.onDigitShown(self.digit_shown) + HW.buttons[1].setCallbacks() + __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 + +class GetNumberScreen(): + def __init__(self,acceptedInputNumbers,startNumber = None,onStart=None,onNumberChange = None,onPicked = None): + self.acceptedInputNumbers = acceptedInputNumbers + self.onStart = onStart + self.onNumberChange = onNumberChange + self.onPicked = onPicked + self.running = False + if startNumber: + self.number = startNumber + else: + self.number = acceptedInputNumbers[0] + def __await__(self): self.running = True for i,b in enumerate(HW.buttons): b.setCallbacks(onPushDown=lambda i=i:self.onButtonPressed(i),onPushUp=lambda pushDownTime,button=i:self.onButtonReleased(button,pushDownTime)) - # Turn LEDs Red and play the selected Sound and turn the minute-hand to the selected sound - HW.housingLEDs.fill((200,0,0)) - HW.buzzer.playSound(HW.Buzzer.ALARMTONES[Settings.selectedSound]) - HW.stepperminu.rotateTo(-Settings.selectedSound/12) + HW.stepperminu.rotateTo(-(self.number/12)) HW.stepperhour.rotateTo(0) while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget(): await asyncio.sleep_ms(200) + if self.onStart: + self.onStart(self.number) while self.running: await asyncio.sleep_ms(200) - HW.housingLEDs.fill((0,0,0)) - self.cleanup() + if self.onPicked: + self.onPicked(self.number) + return self.number __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 - def __init__(self): - self.running = False - def finish(self): - self.running = False - for b in HW.buttons: - b.setCallbacks()#Clear Callbacks - def onButtonPressed(self,button): HW.leds[button].on() def onButtonReleased(self,button,pushDownTime): - print("Ring Select push down",pushDownTime) + print("NumberSel push down",pushDownTime) HW.leds[button].off() if button == 1: - if pushDownTime > 1100: - Settings.save() + if pushDownTime > 700: self.finish() return else: if pushDownTime < 500: - Settings.selectedSound=(Settings.selectedSound+ (1 if button == 2 else -1))%len(Buzzer.ALARMTONES) - HW.stepperminu.rotateTo(-Settings.selectedSound/12) - HW.buzzer.playSound(HW.Buzzer.ALARMTONES[Settings.selectedSound]) + self.number=self.acceptedInputNumbers[(self.acceptedInputNumbers.index(self.number) + (1 if button == 2 else -1)) % len(self.acceptedInputNumbers)] + HW.stepperminu.rotateTo(-(self.number/12)) + if self.onNumberChange: + self.onNumberChange(self.number) - def cleanup(self): - HW.housingLEDs.fill((0,0,0)) - HW.buzzer.stop() \ No newline at end of file + def finish(self): + self.running = False + for b in HW.buttons: + b.setCallbacks()#Clear Callbacks + +class GetTimeScreen(): + def __init__(self,startTime = (0,0),onStart=None,onSelectedTimeChange = None,onPicked = None): + self.onStart = onStart + self.onSelectedTimeChange = onSelectedTimeChange + self.onPicked = onPicked + self.running = False + self.pickedTime = startTime + self.mode = 0 + + def __await__(self): + self.running = True + self.mode=0 # 0: Minutes, 1: Hours + HW.stepperminu.rotateTo(-(self.pickedTime[1])/12) + HW.stepperhour.rotateTo(-(self.pickedTime[0])/12) + HW.leds[1].flash(1) + for number,button in enumerate(HW.buttons): + button.setCallbacks(\ + onPushDown=lambda i=number:self.onButtonPressed(i),\ + onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime)) + # Wait for the Hands to move up + while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget(): + await asyncio.sleep_ms(200) + if self.onStart: + self.onStart(self.pickedTime) + while self.running: + await asyncio.sleep_ms(200) + if self.onPicked: + self.onPicked(self.pickedTime) + + __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 + def finish(self): + self.running = False + for b in HW.buttons: + b.setCallbacks()#Clear Callbacks + for l in HW.leds: + l.off() + + def onButtonPressed(self,button): + if button == 1: + HW.leds[button].on(overwriteFlashing=False) + else: + HW.leds[button].on() + if self.mode == 0: + HW.stepperminu.rotateTo(direction=(1 if button == 0 else -1)) + elif self.mode == 1: + HW.stepperhour.rotateTo(direction=(1 if button == 0 else -1)) + + def onButtonReleased(self,button,time): + HW.leds[button].off(overwriteFlashing=(button!=1)) + if button == 1: + self.mode=(1+self.mode )% 2 + if time > 700: + self.finish() + else: + if self.mode == 0: + HW.stepperminu.stop() + else: + HW.stepperhour.stop() + if self.onSelectedTimeChange: + # TODO This is probably not save as its super unstable around the hour-increments + minutes = (60-HW.stepperminu.getOrientation()*60) + hours = (12-HW.stepperminu.getOrientation()*12) + self.onSelectedTimeChange(self.pickedTime) + + +# TODO +class GetTimeOnePressScreen(): + def __init__(self,startTime = (0,0),onStart=None,onSelectedTimeChange = None,onPicked = None): + self.onStart = onStart + self.onSelectedTimeChange = onSelectedTimeChange + self.onPicked = onPicked + self.running = False + self.pickedTime = startTime + + def __await__(self): + self.running = True + HW.stepperminu.rotateTo(-(self.pickedTime[1])/12) + HW.stepperhour.rotateTo(-(self.pickedTime[0])/12) + HW.leds[1].flash(1) + for number,button in enumerate(HW.buttons): + button.setCallbacks(\ + onPushDown=lambda i=number:self.onButtonPressed(i),\ + onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime)) + # Wait for the Hands to move up + while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget(): + await asyncio.sleep_ms(200) + if self.onStart: + self.onStart(self.pickedTime) + while self.running: + await asyncio.sleep_ms(200) + if self.onPicked: + self.onPicked(self.pickedTime) + + __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 + def finish(self): + self.running = False + for b in HW.buttons: + b.setCallbacks()#Clear Callbacks + for l in HW.leds: + l.off() + + def onButtonPressed(self,button): + if button == 1: + HW.leds[button].on(overwriteFlashing=False) + else: + HW.leds[button].on() + if self.mode == 0: + HW.stepperminu.rotateTo(direction=(1 if button == 0 else -1)) + elif self.mode == 1: + HW.stepperhour.rotateTo(direction=(1 if button == 0 else -1)) + + def onButtonReleased(self,button,time): + HW.leds[button].off(overwriteFlashing=(button!=1)) + if button == 1: + self.mode=(1+self.mode )% 2 + if time > 700: + self.finish() + else: + if self.mode == 0: + HW.stepperminu.stop() + else: + HW.stepperhour.stop() + if self.onSelectedTimeChange: + # TODO This is probably not save as its super unstable around the hour-increments + minutes = (60-HW.stepperminu.getOrientation()*60) + hours = (12-HW.stepperminu.getOrientation()*12) + self.onSelectedTimeChange(self.pickedTime) \ No newline at end of file diff --git a/Settings.py b/Settings.py index 06f1ab9..5517f65 100644 --- a/Settings.py +++ b/Settings.py @@ -1,8 +1,8 @@ selectedSound=0 selectedBrightness=0 selectedColor=0 -alarmTime=((1,2,3,4),(8,),(0,)) - +alarmTime=(8,0) +alarmOn=False def printState(): print("selectedSound=",selectedSound) diff --git a/StepperL298M.py b/StepperL298M.py index 3700b15..059ea4a 100644 --- a/StepperL298M.py +++ b/StepperL298M.py @@ -5,7 +5,7 @@ import uasyncio as asyncio 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],[0,0,1,0]] class Stepper: - def __init__(self,pins,stepsPerRev=400,stepDurationMs=10,inverted=False): + def __init__(self,pins,stepsPerRev=400,stepDurationMs=8,inverted=False): self._pins = [Pin(p, Pin.OUT) for p in pins] self.reset() self.stepDurationMs = stepDurationMs diff --git a/main.py b/main.py index 022eebd..390960d 100644 --- a/main.py +++ b/main.py @@ -1,23 +1,37 @@ import time import uasyncio as asyncio import Hardware as HW +import Settings import Screens #Async loop = asyncio.get_event_loop() -async def run_screens(): - InitScreen = Screens.InitHandsScreen() - await InitScreen - modus = 0 - screens = (Screens.ClockScreen(),\ - Screens.RingtoneSettingsScreen()) + +async def run_screens(): + screens = ( \ + (Screens.ClockScreen(),(140,70,255)),\ + (Screens.SetAlarmTimeScreen(),(255,0,0)),\ + (Screens.RingtoneSettingsScreen(),(255,0,127)),\ + (Screens.InitHandsScreen(),(0,0,255)),\ + (Screens.ShowIpScreen(),HW.HousingLEDs.YELLOW),\ + ) + colorSet = lambda number: HW.housingLEDs.fill(screens[number][1]) + selectScreen = Screens.GetNumberScreen([i for i in range(len(screens))],\ + startNumber=0,\ + onStart=colorSet,\ + onNumberChange=colorSet,\ + onPicked=lambda number: HW.housingLEDs.fill((0,0,0))) + + initScreen = Screens.InitHandsScreen() + await initScreen + + activeScreen = 0 while True: HW.buzzer.playSound(HW.Buzzer.BEEP) - await screens[modus] - for b in HW.buttons: - b.setCallbacks()#Clear Callbacks - modus = (modus+1)%len(screens) + await screens[activeScreen][0] + # Get the new screen from the screen selection screen + activeScreen = await selectScreen loop.run_until_complete(run_screens()) \ No newline at end of file