implmented new hardware
This commit is contained in:
parent
e9e85907bb
commit
416d9e7860
14
Buzzer.py
14
Buzzer.py
@ -15,9 +15,9 @@ C = 523 #Hz
|
|||||||
# (Duration,Freq)
|
# (Duration,Freq)
|
||||||
# If Last Duration is None play last Freq times (negative = infinite)
|
# If Last Duration is None play last Freq times (negative = infinite)
|
||||||
|
|
||||||
BEEP = ((100,1100),)
|
BEEP = ((100,1100),(100,None))
|
||||||
BEEPBEEP = ((700,1100),(100,None),(600,1100))
|
BEEPBEEP = ((700,1100),(100,None),(600,1100))
|
||||||
BOOP = ((100,120),)
|
BOOP = ((100,120),(100,None))
|
||||||
|
|
||||||
# 0: BEEEEP BEEEEP BEEEEEP
|
# 0: BEEEEP BEEEEP BEEEEEP
|
||||||
# 1: Alle Meine Entchen
|
# 1: Alle Meine Entchen
|
||||||
@ -72,9 +72,17 @@ class Buzzer():
|
|||||||
if not self.newSound:
|
if not self.newSound:
|
||||||
self.newSound = False
|
self.newSound = False
|
||||||
self.sound = None
|
self.sound = None
|
||||||
|
self._pwm.duty(0)
|
||||||
|
|
||||||
|
async def awaitFinish(self):
|
||||||
|
while self.isPlaying():
|
||||||
|
await asyncio.sleep_ms(50)
|
||||||
|
|
||||||
|
def awaitFinish_nonasync(self):
|
||||||
|
asyncio.get_event_loop().run_until_complete(self.awaitFinish())
|
||||||
|
|
||||||
def playSound(self,sound):
|
def playSound(self,sound):
|
||||||
self.newSound = True
|
self.newSound = sound != None
|
||||||
self.sound = sound
|
self.sound = sound
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import StepperL298M
|
#import StepperL298M
|
||||||
import time
|
import time
|
||||||
import Hardware as HW
|
import Hardware as HW
|
||||||
import uasyncio as asyncio
|
import uasyncio as asyncio
|
||||||
|
|
||||||
class StepperClock:
|
class Clock:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.started_async = False
|
self.started_async = False
|
||||||
self._async_running = False
|
self._async_running = False
|
||||||
@ -27,12 +27,12 @@ class StepperClock:
|
|||||||
def update(self):
|
def update(self):
|
||||||
hour = time.localtime()[3]
|
hour = time.localtime()[3]
|
||||||
minute = time.localtime()[4]
|
minute = time.localtime()[4]
|
||||||
HW.stepperhour.rotateTo(1-((hour%12)/12+minute/(12*60)))
|
HW.motorHour.rotateTo(1-((hour%12)/12+minute/(12*60)))
|
||||||
HW.stepperminu.rotateTo(1-minute/60)
|
HW.motorMinu.rotateTo(1-minute/60)
|
||||||
|
|
||||||
def disablePower(self):
|
def disablePower(self):
|
||||||
HW.stepperhour.disablePower()
|
HW.motorHour.disablePower()
|
||||||
HW.stepperminu.disablePower()
|
HW.motorMinu.disablePower()
|
||||||
#HW.stepperhour.disablePower()
|
#HW.stepperhour.disablePower()
|
||||||
|
|
||||||
def isRunning(self):
|
def isRunning(self):
|
25
Hardware.py
25
Hardware.py
@ -3,12 +3,20 @@ import ntptime
|
|||||||
import time
|
import time
|
||||||
import DS3231
|
import DS3231
|
||||||
import Buzzer
|
import Buzzer
|
||||||
import StepperL298M
|
#import StepperL298M
|
||||||
|
import MotorPot
|
||||||
import HousingLEDs
|
import HousingLEDs
|
||||||
import LED
|
import LED
|
||||||
import Button
|
import Button
|
||||||
import HousingCapButton
|
import HousingCapButton
|
||||||
import Bme280
|
import Bme280
|
||||||
|
import uasyncio as asyncio
|
||||||
|
|
||||||
|
#>>> pins = [machine.Pin(i,machine.Pin.OUT) for i in (12,27,26,25)]
|
||||||
|
#>>> adcs = [machine.ADC(machine.Pin(i)) for i in (32,33)]
|
||||||
|
#def f(t):
|
||||||
|
#... pins[1].value(1);time.sleep(t);pins[1].value(0);
|
||||||
|
#... print([ads.read() for ads in adcs])
|
||||||
|
|
||||||
#Init i2c Bus on 17,18
|
#Init i2c Bus on 17,18
|
||||||
i2cBus = machine.I2C(sda = machine.Pin(17), scl=machine.Pin(18))
|
i2cBus = machine.I2C(sda = machine.Pin(17), scl=machine.Pin(18))
|
||||||
@ -29,21 +37,23 @@ except Exception as e:
|
|||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
print("timesync error trying again",i)
|
print("timesync error trying again",i)
|
||||||
time.sleep(0.5)
|
asyncio.sleep_ms(500)
|
||||||
|
|
||||||
#Init Buzzer
|
#Init Buzzer
|
||||||
buzzer = Buzzer.Buzzer(pin=2)
|
buzzer = Buzzer.Buzzer(pin=2)
|
||||||
|
|
||||||
#Initalise the Motors
|
#Initalise the Motors
|
||||||
stepperminu = StepperL298M.Stepper((19,21,22,23),inverted=False)
|
#stepperminu = StepperL298M.Stepper((19,21,22,23),inverted=False)
|
||||||
stepperhour = StepperL298M.Stepper((12,27,26,25),inverted=True)
|
#stepperhour = StepperL298M.Stepper((12,27,26,25),inverted=True)
|
||||||
|
motorHour = MotorPot.MotorPot((12,27),33,steps_per_turn = 192)
|
||||||
|
motorMinu = MotorPot.MotorPot((26,25),32,steps_per_turn = 192)
|
||||||
|
|
||||||
#Init LEDs
|
#Init LEDs
|
||||||
housingLEDs = HousingLEDs.LEDs(pin=16)
|
housingLEDs = HousingLEDs.LEDs(pin=16)
|
||||||
|
|
||||||
leftButtonLED = LED.LED(13)
|
leftButtonLED = LED.LED(13)
|
||||||
middleButtonLED = LED.LED(33)
|
middleButtonLED = LED.LED(22)
|
||||||
rightButtonLED = LED.LED(32)
|
rightButtonLED = LED.LED(23)
|
||||||
|
|
||||||
#Init Buttons
|
#Init Buttons
|
||||||
leftButton = Button.Button(pin=34,inverted=True)
|
leftButton = Button.Button(pin=34,inverted=True)
|
||||||
@ -61,4 +71,5 @@ try:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
def reset():
|
||||||
|
machine.reset()
|
||||||
|
307
MotorPot.py
Normal file
307
MotorPot.py
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
from machine import Pin, ADC, PWM
|
||||||
|
import time
|
||||||
|
import uasyncio as asyncio
|
||||||
|
import Hardware as HW
|
||||||
|
import os
|
||||||
|
# import PID
|
||||||
|
# # [(0.0, 3071), (0.08333334, 2634), (0.1666667, 2286), (0.25, 1847),
|
||||||
|
# # (0.3333333, 1453), (0.4166667, 1110), (0.5, 809), (0.5833333, 442),
|
||||||
|
# # (0.6666667, 105), (0.75, 518), (0.8333333, 4095), (0.9166667, 3599)]
|
||||||
|
|
||||||
|
# # >>> m.pid.Ki
|
||||||
|
# # -1
|
||||||
|
# # >>> m.pid.Kd
|
||||||
|
# # 10
|
||||||
|
# # >>> m.pid.Kp
|
||||||
|
# # -2
|
||||||
|
# # >>> m.pid.windup_guard
|
||||||
|
# # 200
|
||||||
|
# # >>>
|
||||||
|
|
||||||
|
|
||||||
|
# class MotorPot:
|
||||||
|
# def __init__(self, pins, adcPin, updateRate=100, freq=40, inverted=False):
|
||||||
|
# self._pins = [PWM(Pin(p, Pin.OUT), freq=freq, duty=0) for p in pins]
|
||||||
|
# for p in self._pins:
|
||||||
|
# p.freq(freq)
|
||||||
|
# self._adc = ADC(Pin(adcPin))
|
||||||
|
# self._adc.atten(ADC.ATTN_11DB) # Enable 3.6V Ranges
|
||||||
|
# self.reset()
|
||||||
|
# self.updateRate = updateRate
|
||||||
|
# self.inverted = inverted
|
||||||
|
# self._adcAngleMap = []
|
||||||
|
# self._okTargetDiff = 0.1
|
||||||
|
# self.pid = PID.PID(P=-2, D=10, I=-1)
|
||||||
|
# self.pid.setWindup(200)
|
||||||
|
# self.min_duty = 100
|
||||||
|
# # self._maxSpeed = 1
|
||||||
|
# self._duty = 500
|
||||||
|
# self.calib_number = None
|
||||||
|
# #loop = asyncio.get_event_loop()
|
||||||
|
# #loop.create_task(self._update_async())
|
||||||
|
|
||||||
|
# def reset(self):
|
||||||
|
# self._rotTarget = 0
|
||||||
|
# self.rotDirection = 0
|
||||||
|
|
||||||
|
# def getStepsToTarget(self):
|
||||||
|
# # return ((self._rotTarget - self.stepnum)
|
||||||
|
# # *self.rotDirection)%self.stepsPerRev
|
||||||
|
# return 0
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
# If target is None moves infinitely in direction
|
||||||
|
# (if direction is 0 then hold position with power)."""
|
||||||
|
# if target is None:
|
||||||
|
# self._rotTarget = None
|
||||||
|
# self.rotDirection = direction
|
||||||
|
# else:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
# def stop(self):
|
||||||
|
# for p in self._pins:
|
||||||
|
# p.duty(0)
|
||||||
|
# self.rotDirection = 0
|
||||||
|
# self._rotTarget = None
|
||||||
|
|
||||||
|
# async def _update_async(self):
|
||||||
|
# while(True):
|
||||||
|
# await asyncio.sleep_ms(self.updateRate)
|
||||||
|
# self._update()
|
||||||
|
|
||||||
|
# def _update_block(self):
|
||||||
|
# while(self.isAtTarget()):
|
||||||
|
# await asyncio.sleep_ms(self.updateRate)
|
||||||
|
# self._update()
|
||||||
|
|
||||||
|
# def _update(self):
|
||||||
|
# # duty = int(self._duty)
|
||||||
|
# # if self._rotTarget is not None:
|
||||||
|
# # targetDiff = self.getOrientation() - self._rotTarget
|
||||||
|
# # if not self.isAtTarget():
|
||||||
|
# # self.rotDirection = 1 if targetDiff > 0 else -1
|
||||||
|
# # # TODO duty = min(abs(targetDiff)*kp,1)*duty
|
||||||
|
# # else:
|
||||||
|
# # self.rotDirection = 0
|
||||||
|
# # self._pins[0].duty(duty if self.rotDirection < 0 else 0)
|
||||||
|
# # self._pins[1].duty(duty if self.rotDirection > 0 else 0)
|
||||||
|
# self.pid.SetPoint = self._rotTarget
|
||||||
|
# self._adcValue = self._adc.read()
|
||||||
|
# self.pid.update(self._adcValue)
|
||||||
|
# v = int(self.pid.output)
|
||||||
|
# print("target", self._rotTarget,
|
||||||
|
# "adcValue", self._adcValue,
|
||||||
|
# "output:", v)
|
||||||
|
# self._pins[0].duty(-v if v < -self.min_duty else 0)
|
||||||
|
# self._pins[1].duty(v if v > self.min_duty else 0)
|
||||||
|
|
||||||
|
# def getOrientation(self):
|
||||||
|
# adcValueNow = self._adc.read()
|
||||||
|
# for i in range(len(self._adcAngleMap)-1):
|
||||||
|
# if(self._adcAngleMap[i][1] <= adcValueNow
|
||||||
|
# and self._adcAngleMap[i+1][1] > adcValueNow):
|
||||||
|
# r = (adcValueNow - self._adcAngleMap[i][0]) / (
|
||||||
|
# self._adcAngleMap[i+1][0] - self._adcAngleMap[i][0])
|
||||||
|
# r = self._adcAngleMap[i][1] + r * \
|
||||||
|
# (self._adcAngleMap[i+1][1] - self._adcAngleMap[i][1])
|
||||||
|
# return r
|
||||||
|
# # return didn't trigger, so the pot is in the deadzone
|
||||||
|
# # TODO Calc a possible orientation based on time of last duty command
|
||||||
|
# return 0
|
||||||
|
|
||||||
|
# def getTarget(self):
|
||||||
|
# return self._rotTarget
|
||||||
|
|
||||||
|
# def isAtTarget(self):
|
||||||
|
# if self._rotTarget is None:
|
||||||
|
# return self.rotDirection == 0
|
||||||
|
# targetDiff = self.getOrientation() - self._rotTarget
|
||||||
|
# return (abs(targetDiff) < self._okTargetDiff)
|
||||||
|
|
||||||
|
# def printAdcValues(self, duty=200, sleepTime=0.01, pin=0):
|
||||||
|
# start = self._adc.read()
|
||||||
|
# while abs(start - self._adc.read()) <= 30:
|
||||||
|
# self._pins[pin].duty(duty)
|
||||||
|
# time.sleep(sleepTime)
|
||||||
|
# self._pins[pin].duty(0)
|
||||||
|
# print(self._adc.read())
|
||||||
|
# while abs(start - self._adc.read()) > 30:
|
||||||
|
# self._pins[pin].duty(duty)
|
||||||
|
# time.sleep(sleepTime)
|
||||||
|
# self._pins[pin].duty(0)
|
||||||
|
# print(self._adc.read())
|
||||||
|
|
||||||
|
class MotorPot:
|
||||||
|
def __init__(self,pins, adcPin, stepTime=3, stepWait=130,steps_per_turn = None,adc_map = None,tolerance = 30,inverted=False):
|
||||||
|
self._pins = [Pin(p,Pin.OUT) for p in pins]
|
||||||
|
self._adc = ADC(Pin(adcPin))
|
||||||
|
self._adc.atten(ADC.ATTN_11DB) # Enable 3.6V Ranges
|
||||||
|
self.inverted = inverted
|
||||||
|
self.stepTime = stepTime
|
||||||
|
self.stepWait = stepWait
|
||||||
|
self.steps_per_turn = steps_per_turn
|
||||||
|
self.rotation_current = 0
|
||||||
|
self.rotation_target = 0
|
||||||
|
self.tolerance = tolerance
|
||||||
|
self._adc_max_value = 4096
|
||||||
|
self._adc_map = adc_map
|
||||||
|
self.load_settings()
|
||||||
|
self.calib_number = 1
|
||||||
|
self._calibrating = False
|
||||||
|
if(self._adc_map is None):
|
||||||
|
self._adc_map = [(4095, 0.8333333-1-1/12), (3599, 0.9166667-1-1/12), (3071, 0.0-1/12), (2634, 0.08333334-1/12), (2286, 0.1666667-1/12), (1847, 0.25-1/12), (1453, 0.3333333-1/12), (1110, 0.4166667-1/12), (809, 0.5-1/12), (442, 0.5833333-1/12), (105, 0.6666667-1/12)]
|
||||||
|
self.save_settings()
|
||||||
|
#[(4095, 0.8333333-1-1/12), (3599, 0.9166667-1-1/12), (3071, 0.0-1/12), (2634, 0.08333334-1/12), (2286, 0.1666667-1/12), (1847, 0.25-1/12), (1453, 0.3333333-1/12), (1110, 0.4166667-1/12), (809, 0.5-1/12), (442, 0.5833333-1/12), (105, 0.6666667-1/12)]
|
||||||
|
#self._adc_map = [(d[0],(d[1]+0.5)%1-0.5) for d in self._adc_map]
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.create_task(self._update_async())
|
||||||
|
|
||||||
|
async def _getStepsPerTurn_async(self,steps_dir = 1):
|
||||||
|
startV = self._adc.read()
|
||||||
|
while (startV == 0 or startV == self._adc_max_value):
|
||||||
|
self._step(steps_dir)
|
||||||
|
startV = self._adc.read()
|
||||||
|
steps = 0
|
||||||
|
while (startV - self.tolerance - self._adc.read())%self._adc_max_value > self.tolerance:
|
||||||
|
self._step(steps_dir)
|
||||||
|
await asyncio.sleep_ms(self.stepWait)
|
||||||
|
steps += abs(steps_dir)
|
||||||
|
print("waiting for:",(startV - self.tolerance - self._adc.read())%self._adc_max_value)
|
||||||
|
self.steps_per_turn = steps
|
||||||
|
#[(0.0, 3071), (0.08333334, 2634), (0.1666667, 2286), (0.25, 1847), (0.3333333, 1453), (0.4166667, 1110), (0.5, 809), (0.5833333, 442), (0.6666667, 105), (0.8333333, 4095), (0.9166667, 3599)]
|
||||||
|
|
||||||
|
def _getStepsPerTurn(self,steps_dir = 1):
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(self._getStepsPerTurn_async(steps_dir))
|
||||||
|
return self.steps_per_turn
|
||||||
|
|
||||||
|
def _step(self,direc):
|
||||||
|
direcBool = self.inverted != (direc>0)
|
||||||
|
p = self._pins[1 if direcBool else 0]
|
||||||
|
adc_before = self._adc.read()
|
||||||
|
p.on()
|
||||||
|
#await asyncio.sleep_ms(self.stepTime)
|
||||||
|
time.sleep_ms(self.stepTime)
|
||||||
|
p.off()
|
||||||
|
if(self._calibrating):
|
||||||
|
return
|
||||||
|
oldR = self.rotation_current
|
||||||
|
self.rotation_current = (self.rotation_current + direc / self.steps_per_turn)%1
|
||||||
|
self.update_rotation_from_adc()
|
||||||
|
#print("rotation updated:",oldR," -> ", self.rotation_current," t",self.rotation_target)
|
||||||
|
def update_rotation_from_adc(self):
|
||||||
|
adc_after = self._adc.read()
|
||||||
|
if not (self._adc_map[0][1] > self.rotation_current > self._adc_map[-1][1]):
|
||||||
|
i = 0
|
||||||
|
for i in range(len(self._adc_map)-1):
|
||||||
|
if (min(self._adc_map[i+1][0],self._adc_map[i][0]) < adc_after < max(self._adc_map[i+1][0],self._adc_map[i][0])):
|
||||||
|
self.rotation_current = (self._adc_map[i+1][1]+((adc_after-self._adc_map[i][0])/(self._adc_map[i+1][0]-self._adc_map[i][0]))*(self._adc_map[i+1][1]-self._adc_map[i][1]))%1
|
||||||
|
break
|
||||||
|
|
||||||
|
async def run_until_target_async(self):
|
||||||
|
while(not self.isAtTarget()):
|
||||||
|
self._step(1 if (self.rotation_current - self.rotation_target+0.5)%1<0.5 else -1)
|
||||||
|
await asyncio.sleep_ms(self.stepWait)
|
||||||
|
|
||||||
|
def run_until_target_block(self,target):
|
||||||
|
self.rotation_target = target
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(self.run_until_target_async())
|
||||||
|
return self.steps_per_turn
|
||||||
|
|
||||||
|
async def _update_async(self):
|
||||||
|
while(True):
|
||||||
|
await self.run_until_target_async()
|
||||||
|
await asyncio.sleep_ms(self.stepWait)
|
||||||
|
#self.update_rotation_from_adc()
|
||||||
|
|
||||||
|
def set_current_rotation(self,curr):
|
||||||
|
self._adc_map = [(a[0],(a[1]-self.rotation_current+curr+0.5)%1-0.5) for a in self._adc_map]
|
||||||
|
|
||||||
|
def get_filename(self):
|
||||||
|
return (str(self._pins)+str(self._adc)).replace(" ","").replace("(","").replace(")","").replace(",","").replace("]","").replace("[","")
|
||||||
|
|
||||||
|
def save_settings(self):
|
||||||
|
foldername = "/motor_settings"
|
||||||
|
try:
|
||||||
|
os.remove(foldername+"/"+self.get_filename())
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
try:
|
||||||
|
os.mkdir(foldername)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
with open(foldername+"/"+self.get_filename(),'w') as f:
|
||||||
|
f.write(str(self._adc_map)+"\n")
|
||||||
|
f.write(str(self.steps_per_turn)+"\n")
|
||||||
|
|
||||||
|
def load_settings(self):
|
||||||
|
foldername = "/motor_settings"+"/"+self.get_filename()
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(foldername,'r') as f:
|
||||||
|
s=f.readline()
|
||||||
|
print(foldername,":\n"," _adc_map =",s)
|
||||||
|
self._adc_map = eval(s)
|
||||||
|
s=f.readline()
|
||||||
|
print(" steps_per_turn =",s)
|
||||||
|
self.steps_per_turn = eval(s)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
for p in self._pins:
|
||||||
|
p.off()
|
||||||
|
|
||||||
|
def calib_onButtonReleased(self, button, pushdown):
|
||||||
|
HW.leds[button].off()
|
||||||
|
if button == 1:
|
||||||
|
if pushdown > 700:
|
||||||
|
self._calibrating = False
|
||||||
|
self.stop()
|
||||||
|
else:
|
||||||
|
self._adc_map.append(
|
||||||
|
(self._adc.read(), (self.calib_number-1 % 12)/12))
|
||||||
|
self._adc_map.sort(key=lambda x: -x[0])
|
||||||
|
self.calib_number = (self.calib_number) % 12+1
|
||||||
|
print(self._adc_map)
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def calib_onButtonPressed(self, button):
|
||||||
|
HW.leds[button].on()
|
||||||
|
self._step(button - 1)
|
||||||
|
|
||||||
|
def calibrate(self):
|
||||||
|
self._adc_map = []
|
||||||
|
self.calib_number = 1
|
||||||
|
self._calibrating = True
|
||||||
|
for i, b in enumerate(HW.buttons):
|
||||||
|
b.setCallbacks(
|
||||||
|
onPushDown=lambda i=i: self.calib_onButtonPressed(i),
|
||||||
|
onPushUp=lambda pushDownTime, button=i:
|
||||||
|
self.calib_onButtonReleased(button, pushDownTime))
|
||||||
|
# await asyncio.sleep_ms(self.updateRate)
|
||||||
|
self._rotTarget = None
|
||||||
|
HW.buzzer.playSound(HW.Buzzer.BEEP*self.calib_number)
|
||||||
|
HW.buzzer.awaitFinish_nonasync()
|
||||||
|
currNum = self.calib_number
|
||||||
|
while self._calibrating:
|
||||||
|
while currNum == self.calib_number:
|
||||||
|
time.sleep(0.1)
|
||||||
|
currNum = self.calib_number
|
||||||
|
HW.buzzer.playSound(HW.Buzzer.BEEP*self.calib_number)
|
||||||
|
HW.buzzer.awaitFinish_nonasync()
|
||||||
|
|
||||||
|
def rotateTo(self,target):
|
||||||
|
self.rotation_target = -target%1
|
||||||
|
|
||||||
|
def getOrientation(self):
|
||||||
|
return self.rotation_current
|
||||||
|
|
||||||
|
def getTarget(self):
|
||||||
|
return self.rotation_target
|
||||||
|
|
||||||
|
def isAtTarget(self):
|
||||||
|
return abs(self.rotation_current - self.rotation_target)%1 < self.tolerance/self._adc_max_value
|
58
Screens.py
58
Screens.py
@ -1,4 +1,4 @@
|
|||||||
import StepperClock
|
import Clock
|
||||||
import uasyncio as asyncio
|
import uasyncio as asyncio
|
||||||
import Buzzer
|
import Buzzer
|
||||||
import Settings
|
import Settings
|
||||||
@ -39,7 +39,7 @@ class ClockScreen():
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
self.light = False
|
self.light = False
|
||||||
self.clock = StepperClock.StepperClock()
|
self.clock = Clock.Clock()
|
||||||
self.alarmTrunedOff = False
|
self.alarmTrunedOff = False
|
||||||
self.alarmPlaying = False
|
self.alarmPlaying = False
|
||||||
|
|
||||||
@ -91,8 +91,8 @@ class ClockScreen():
|
|||||||
|
|
||||||
class InitHandsScreen():
|
class InitHandsScreen():
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
HW.stepperminu.rotateTo(0)
|
HW.motorHour.rotateTo(0)
|
||||||
HW.stepperhour.rotateTo(0)
|
HW.motorMinu.rotateTo(0)
|
||||||
HW.housingLEDs.upper((50,50,50))
|
HW.housingLEDs.upper((50,50,50))
|
||||||
HW.leds[1].setOffState(pwmDuty=500,blinkRate=1.2)
|
HW.leds[1].setOffState(pwmDuty=500,blinkRate=1.2)
|
||||||
timeScreen = Get2PositionsScreen(\
|
timeScreen = Get2PositionsScreen(\
|
||||||
@ -101,8 +101,8 @@ class InitHandsScreen():
|
|||||||
onSelectedTimeChange=None,\
|
onSelectedTimeChange=None,\
|
||||||
onPicked=lambda _: Settings.save())
|
onPicked=lambda _: Settings.save())
|
||||||
await timeScreen
|
await timeScreen
|
||||||
HW.stepperhour.reset() # Set the new Zero
|
HW.motorHour.reset() # Set the new Zero
|
||||||
HW.stepperminu.reset()
|
HW.motorMinu.reset()
|
||||||
HW.housingLEDs.fill((0,0,0))
|
HW.housingLEDs.fill((0,0,0))
|
||||||
HW.leds[1].setOffState()
|
HW.leds[1].setOffState()
|
||||||
|
|
||||||
@ -213,13 +213,13 @@ class ShowLongNumberScreen():
|
|||||||
def __await__(self):
|
def __await__(self):
|
||||||
self.running = True
|
self.running = True
|
||||||
HW.buttons[1].setCallbacks(onPushUp=self.onButtonReleased,onPushDown=lambda :HW.leds[1].on())
|
HW.buttons[1].setCallbacks(onPushUp=self.onButtonReleased,onPushDown=lambda :HW.leds[1].on())
|
||||||
HW.stepperminu.rotateTo(0)
|
HW.motorMinu.rotateTo(0)
|
||||||
HW.stepperhour.rotateTo(0)
|
HW.motorHour.rotateTo(0)
|
||||||
self.digit_shown = 0
|
self.digit_shown = 0
|
||||||
await self.onDigitShown(self.digit_shown)
|
await self.onDigitShown(self.digit_shown)
|
||||||
while self.digit_shown < len(self.number):
|
while self.digit_shown < len(self.number):
|
||||||
HW.stepperminu.rotateTo(-((self.number[self.digit_shown]%10)/12))
|
HW.motorMinu.rotateTo(-((self.number[self.digit_shown]%10)/12))
|
||||||
while self.running and (not HW.stepperminu.isAtTarget() or not HW.stepperhour.isAtTarget()):
|
while self.running and (not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget()):
|
||||||
await asyncio.sleep_ms(200)
|
await asyncio.sleep_ms(200)
|
||||||
if not self.running:
|
if not self.running:
|
||||||
return
|
return
|
||||||
@ -245,10 +245,10 @@ class ShowNumberScreen():
|
|||||||
while self.running:
|
while self.running:
|
||||||
if self.update != None:
|
if self.update != None:
|
||||||
self.number = self.update()
|
self.number = self.update()
|
||||||
while (not HW.stepperminu.isAtTarget() or not HW.stepperhour.isAtTarget()):
|
while (not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget()):
|
||||||
await asyncio.sleep_ms(200)
|
await asyncio.sleep_ms(200)
|
||||||
HW.stepperminu.rotateTo(-((self.number%10)/12))
|
HW.motorMinu.rotateTo(-((self.number%10)/12))
|
||||||
HW.stepperhour.rotateTo(-((self.number//10)/12))
|
HW.motorrHou.rotateTo(-((self.number//10)/12))
|
||||||
await asyncio.sleep_ms(500)
|
await asyncio.sleep_ms(500)
|
||||||
HW.buttons[1].setCallbacks()
|
HW.buttons[1].setCallbacks()
|
||||||
__iter__ = __await__ # https://github.com/micropython/micropython/issues/2678
|
__iter__ = __await__ # https://github.com/micropython/micropython/issues/2678
|
||||||
@ -269,9 +269,9 @@ class GetNumberScreen():
|
|||||||
self.running = True
|
self.running = True
|
||||||
for i,b in enumerate(HW.buttons):
|
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))
|
b.setCallbacks(onPushDown=lambda i=i:self.onButtonPressed(i),onPushUp=lambda pushDownTime,button=i:self.onButtonReleased(button,pushDownTime))
|
||||||
HW.stepperminu.rotateTo(-(self.number/12))
|
HW.motorMinu.rotateTo(-(self.number/12))
|
||||||
HW.stepperhour.rotateTo(0)
|
HW.motorHour.rotateTo(0)
|
||||||
while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget():
|
while not HW.motorHour.isAtTarget() or not HW.motorMinu.isAtTarget():
|
||||||
await asyncio.sleep_ms(200)
|
await asyncio.sleep_ms(200)
|
||||||
if self.onStart:
|
if self.onStart:
|
||||||
self.onStart(self.number)
|
self.onStart(self.number)
|
||||||
@ -294,7 +294,7 @@ class GetNumberScreen():
|
|||||||
else:
|
else:
|
||||||
if pushDownTime < 500:
|
if pushDownTime < 500:
|
||||||
self.number=self.acceptedInputNumbers[(self.acceptedInputNumbers.index(self.number) + (1 if button == 2 else -1)) % len(self.acceptedInputNumbers)]
|
self.number=self.acceptedInputNumbers[(self.acceptedInputNumbers.index(self.number) + (1 if button == 2 else -1)) % len(self.acceptedInputNumbers)]
|
||||||
HW.stepperminu.rotateTo(-(self.number/12))
|
HW.motorMinu.rotateTo(-(self.number/12))
|
||||||
if self.onNumberChange:
|
if self.onNumberChange:
|
||||||
self.onNumberChange(self.number)
|
self.onNumberChange(self.number)
|
||||||
|
|
||||||
@ -315,14 +315,14 @@ class Get2PositionsScreen():
|
|||||||
def __await__(self):
|
def __await__(self):
|
||||||
self.running = True
|
self.running = True
|
||||||
self.mode=0 # 0: Minutes, 1: Hours
|
self.mode=0 # 0: Minutes, 1: Hours
|
||||||
HW.stepperminu.rotateTo(-(self.pickedTime[1])/12)
|
HW.motorMinu.rotateTo(-(self.pickedTime[1])/12)
|
||||||
HW.stepperhour.rotateTo(-(self.pickedTime[0])/12)
|
HW.motorHour.rotateTo(-(self.pickedTime[0])/12)
|
||||||
for number,button in enumerate(HW.buttons):
|
for number,button in enumerate(HW.buttons):
|
||||||
button.setCallbacks(\
|
button.setCallbacks(\
|
||||||
onPushDown=lambda i=number:self.onButtonPressed(i),\
|
onPushDown=lambda i=number:self.onButtonPressed(i),\
|
||||||
onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime))
|
onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime))
|
||||||
# Wait for the Hands to move up
|
# Wait for the Hands to move up
|
||||||
while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget():
|
while not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget():
|
||||||
await asyncio.sleep_ms(200)
|
await asyncio.sleep_ms(200)
|
||||||
if self.onStart:
|
if self.onStart:
|
||||||
self.onStart(self.pickedTime)
|
self.onStart(self.pickedTime)
|
||||||
@ -344,9 +344,9 @@ class Get2PositionsScreen():
|
|||||||
HW.leds[button].on()
|
HW.leds[button].on()
|
||||||
if button != 1:
|
if button != 1:
|
||||||
if self.mode == 0:
|
if self.mode == 0:
|
||||||
HW.stepperminu.rotateTo(direction=(1 if button == 0 else -1))
|
HW.motorMinu.rotateTo(direction=(1 if button == 0 else -1))
|
||||||
elif self.mode == 1:
|
elif self.mode == 1:
|
||||||
HW.stepperhour.rotateTo(direction=(1 if button == 0 else -1))
|
HW.motorHour.rotateTo(direction=(1 if button == 0 else -1))
|
||||||
|
|
||||||
def onButtonReleased(self,button,time):
|
def onButtonReleased(self,button,time):
|
||||||
HW.leds[button].off()
|
HW.leds[button].off()
|
||||||
@ -356,13 +356,13 @@ class Get2PositionsScreen():
|
|||||||
self.finish()
|
self.finish()
|
||||||
else:
|
else:
|
||||||
if self.mode == 0:
|
if self.mode == 0:
|
||||||
HW.stepperminu.stop()
|
HW.motorMinu.stop()
|
||||||
else:
|
else:
|
||||||
HW.stepperhour.stop()
|
HW.motorHour.stop()
|
||||||
if self.onSelectedTimeChange:
|
if self.onSelectedTimeChange:
|
||||||
# TODO This is probably not save as its super unstable around the hour-increments
|
# TODO This is probably not save as its super unstable around the hour-increments
|
||||||
minutes = (60-HW.stepperminu.getOrientation()*60)
|
minutes = (60-HW.motorMinu.getOrientation()*60)
|
||||||
hours = (12-HW.stepperminu.getOrientation()*12)
|
hours = (12-HW.motorMinu.getOrientation()*12)
|
||||||
self.pickedTime = (hours,minutes)
|
self.pickedTime = (hours,minutes)
|
||||||
self.onSelectedTimeChange(self.pickedTime)
|
self.onSelectedTimeChange(self.pickedTime)
|
||||||
|
|
||||||
@ -387,13 +387,13 @@ class GetTimeScreen():
|
|||||||
onPushDown=lambda i=number:self.onButtonPressed(i),\
|
onPushDown=lambda i=number:self.onButtonPressed(i),\
|
||||||
onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime))
|
onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime))
|
||||||
# Wait for the Hands to move up
|
# Wait for the Hands to move up
|
||||||
while not HW.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget():
|
while not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget():
|
||||||
await asyncio.sleep_ms(200)
|
await asyncio.sleep_ms(200)
|
||||||
if self.onStart:
|
if self.onStart:
|
||||||
self.onStart(self.calcTupleTime())
|
self.onStart(self.calcTupleTime())
|
||||||
while self.running:
|
while self.running:
|
||||||
HW.stepperminu.rotateTo(-(self.pickedTime/60))
|
HW.motorMinu.rotateTo(-(self.pickedTime/60))
|
||||||
HW.stepperhour.rotateTo(-(self.pickedTime/60/12))
|
HW.motorHour.rotateTo(-(self.pickedTime/60/12))
|
||||||
# Color the Top LED to indikate AM or PM
|
# Color the Top LED to indikate AM or PM
|
||||||
self.AM = (self.pickedTime < 12*60)
|
self.AM = (self.pickedTime < 12*60)
|
||||||
HW.housingLEDs.upper(HW.HousingLEDs.BLUE if self.AM else HW.HousingLEDs.YELLOW)
|
HW.housingLEDs.upper(HW.HousingLEDs.BLUE if self.AM else HW.HousingLEDs.YELLOW)
|
||||||
|
@ -27,7 +27,7 @@ class Stepper:
|
|||||||
self._pins[2].value(level[2])
|
self._pins[2].value(level[2])
|
||||||
self._pins[3].value(level[3])
|
self._pins[3].value(level[3])
|
||||||
|
|
||||||
def getStepsToTarget(self):
|
def _getStepsToTarget(self):
|
||||||
#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)
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class Stepper:
|
|||||||
self.rotDirection = 1 if (self._rotTarget > self.stepnum) else -1
|
self.rotDirection = 1 if (self._rotTarget > self.stepnum) else -1
|
||||||
else:
|
else:
|
||||||
self.rotDirection = direction
|
self.rotDirection = direction
|
||||||
self._speedMs = max(int(self.stepDurationMs),duration*1000/self.getStepsToTarget())
|
self._speedMs = max(int(self.stepDurationMs),duration*1000/self._getStepsToTarget())
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._rotTarget = self.stepnum
|
self._rotTarget = self.stepnum
|
||||||
|
30
boot.py
30
boot.py
@ -1,14 +1,21 @@
|
|||||||
import network
|
import network
|
||||||
import webrepl
|
import webrepl
|
||||||
import uasyncio as asyncio
|
import uasyncio as asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
webrepl.start()
|
webrepl.start()
|
||||||
|
|
||||||
sta_if = network.WLAN(network.STA_IF)
|
sta_if = network.WLAN(network.STA_IF)
|
||||||
|
sta_if.active(False)
|
||||||
|
time.sleep(0.1)
|
||||||
sta_if.active(True)
|
sta_if.active(True)
|
||||||
sta_if.config(dhcp_hostname="stepper-wecker")
|
time.sleep(0.1)
|
||||||
|
sta_if.config(dhcp_hostname="wecker")
|
||||||
|
|
||||||
|
#print("sta_if.config")
|
||||||
|
|
||||||
|
|
||||||
async def connect():
|
async def connect():
|
||||||
connectingFor = 0
|
connectingFor = 0
|
||||||
@ -22,21 +29,22 @@ async def connect():
|
|||||||
try:
|
try:
|
||||||
availableNetworkSSIDs = [s[0].decode() for s in sta_if.scan()]
|
availableNetworkSSIDs = [s[0].decode() for s in sta_if.scan()]
|
||||||
if len(availableNetworkSSIDs) > 0:
|
if len(availableNetworkSSIDs) > 0:
|
||||||
print("availableNetworkSSIDs:\n",availableNetworkSSIDs)
|
print("availableNetworkSSIDs:\n", availableNetworkSSIDs)
|
||||||
#load wifi credentials from file
|
# load wifi credentials from file
|
||||||
with open("wifi-credentials","r") as f:
|
with open("wifi-credentials", "r") as f:
|
||||||
while sta_if.status() != network.STAT_GOT_IP:
|
while sta_if.status() != network.STAT_GOT_IP:
|
||||||
ssid = f.readline()
|
ssid = f.readline()
|
||||||
password = f.readline()#
|
password = f.readline()
|
||||||
if not ssid or not password:
|
if not ssid or not password:
|
||||||
break
|
break
|
||||||
ssid = ssid.replace("\n","")
|
ssid = ssid.replace("\n", "")
|
||||||
password = password.replace("\n","")
|
password = password.replace("\n", "")
|
||||||
if ssid in availableNetworkSSIDs:
|
if ssid in availableNetworkSSIDs:
|
||||||
print("Connecting to",ssid)
|
print("Connecting to", ssid)
|
||||||
sta_if.connect(ssid,password)
|
sta_if.connect(ssid, password)
|
||||||
break
|
break
|
||||||
except:
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
await asyncio.sleep(60*2)
|
await asyncio.sleep(60*2)
|
||||||
|
7
main.py
7
main.py
@ -17,9 +17,9 @@ async def run_screens():
|
|||||||
(Screens.TemperatureScreen(),(0,50,200)),\
|
(Screens.TemperatureScreen(),(0,50,200)),\
|
||||||
(Screens.HumidityScreen(),(0,50,200)),\
|
(Screens.HumidityScreen(),(0,50,200)),\
|
||||||
(Screens.SetTimeScreen(),(100,200,50)),\
|
(Screens.SetTimeScreen(),(100,200,50)),\
|
||||||
(Screens.InitHandsScreen(),(0,0,255)),\
|
|
||||||
(Screens.ShowIpScreen(),HW.HousingLEDs.YELLOW),\
|
(Screens.ShowIpScreen(),HW.HousingLEDs.YELLOW),\
|
||||||
)
|
)
|
||||||
|
#(Screens.InitHandsScreen(),(0,0,255)),\
|
||||||
colorSet = lambda number: HW.housingLEDs.fill(screens[number][1])
|
colorSet = lambda number: HW.housingLEDs.fill(screens[number][1])
|
||||||
selectScreen = Screens.GetNumberScreen([i for i in range(len(screens))],\
|
selectScreen = Screens.GetNumberScreen([i for i in range(len(screens))],\
|
||||||
startNumber=0,\
|
startNumber=0,\
|
||||||
@ -27,8 +27,8 @@ async def run_screens():
|
|||||||
onNumberChange=colorSet,\
|
onNumberChange=colorSet,\
|
||||||
onPicked=lambda number: HW.housingLEDs.fill((0,0,0)))
|
onPicked=lambda number: HW.housingLEDs.fill((0,0,0)))
|
||||||
|
|
||||||
initScreen = Screens.InitHandsScreen()
|
#initScreen = Screens.InitHandsScreen()
|
||||||
await initScreen
|
#await initScreen
|
||||||
|
|
||||||
activeScreen = 0
|
activeScreen = 0
|
||||||
while True:
|
while True:
|
||||||
@ -38,3 +38,4 @@ async def run_screens():
|
|||||||
activeScreen = await selectScreen
|
activeScreen = await selectScreen
|
||||||
|
|
||||||
loop.run_until_complete(run_screens())
|
loop.run_until_complete(run_screens())
|
||||||
|
loop.run_forever()
|
Loading…
x
Reference in New Issue
Block a user