kopia lustrzana https://github.com/GuyCarver/MicroPython
Porównaj commity
5 Commity
cb95afd55e
...
fc74cc6bc8
Autor | SHA1 | Data |
---|---|---|
Guy Carver | fc74cc6bc8 | |
Guy Carver | b2928fd83d | |
Guy Carver | 69cfdf97b9 | |
Guy Carver | 7cfa1a2096 | |
Guy Carver | 4095348af9 |
|
@ -0,0 +1 @@
|
|||
/mainbackup.py
|
|
@ -0,0 +1,201 @@
|
|||
#Driver for DFPlayer mini, MP3 player with SD card slot, using serial communication.
|
||||
|
||||
#See documentation at:
|
||||
# https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299
|
||||
|
||||
#0 Each command starts with byte 0x7E
|
||||
#1 Version # (set to 0xFF)
|
||||
#2 The number of bytes which follow (6, Not including checksum and termination)
|
||||
#3 The command to execute
|
||||
#4 Feedback indicator (0: no, 1: yes)
|
||||
#5 Argument high byte
|
||||
#6 Argument low byte
|
||||
#7-8 2 byte checksum
|
||||
#9 Termination byte 0xEF
|
||||
|
||||
#Commands
|
||||
#The next and prev commands wrap when they hit the end of the list.
|
||||
#0x01 next
|
||||
#0x02 prev
|
||||
#0x03 Track # 0-2999
|
||||
#0x04 volume +
|
||||
#0x05 volume -
|
||||
#0x06 volume #0-30
|
||||
#0x07 equalizer 0-5 (Normal, Pop, Rock, Jazz, Classical, Base)
|
||||
#0x08 playback mode 0-3 (Repeat, folder repeat, single repeat, random)
|
||||
#0x09 playback source 0-3 (U, TF, AUX, SLEEP, FLASH)
|
||||
#0x0A sleep mode
|
||||
#0x0B Normal mode
|
||||
#0x0C reset
|
||||
#0x0D play/resume
|
||||
#0x0E pause
|
||||
#0x0F specify folder 1-10
|
||||
#0x10 volume adjust (High byte = Open volume adjust, Low byte = volume gain 0-31)
|
||||
#0x11 repeat 0 = stop, 1 = repeat.
|
||||
|
||||
#Query commands
|
||||
#0x3F Send init parameters 0-0x0F.
|
||||
#0x41 Reply. The command byte is set to this on a reply read from the dfplayer as a reply if
|
||||
# the the feedback indicator was set on the command. Not very useful.
|
||||
#0x42 status
|
||||
#0x43 volume
|
||||
#0x44 eq
|
||||
#0x45 playback mode
|
||||
#0x46 software version
|
||||
#0x47 # of TF card files
|
||||
#0x48 # of SD card files
|
||||
#0x49 # of flash files
|
||||
#0x4A Keep on ?
|
||||
#0x4B Current TF card track
|
||||
#0x4C Current SD card track
|
||||
#0x4D Current flash track
|
||||
|
||||
#Results - These are sent as replies to certain commands.
|
||||
#0x3D Result of play, next, prev (param hi/lo is current file index)
|
||||
|
||||
# Folders are named 01, 02..99. Files 001, 002 ... 999.
|
||||
|
||||
from machine import UART
|
||||
from time import sleep_ms
|
||||
|
||||
class dfplayer(UART) :
|
||||
|
||||
_WAIT = const(10)
|
||||
|
||||
'''Initialize dfplayer at given UART 0-2'''
|
||||
def __init__(self, aUART, aBaud = 9600) :
|
||||
super(dfplayer, self).__init__(aUART, aBaud)
|
||||
self._buffer = bytearray(10)
|
||||
self._buffer[0] = 0x7E #commands always start with these bytes.
|
||||
self._buffer[1] = 0xFF #Version #
|
||||
self._buffer[2] = 6 #Commands are always 6 bytes
|
||||
self._buffer[4] = 0 #We never want results returned. (0x41) This is just an ack we don't use.
|
||||
self._buffer[9] = 0xEF #Command terminator.
|
||||
self._readbuffer = bytearray(20)
|
||||
|
||||
def _clear( self ) :
|
||||
while self.any() :
|
||||
self.readinto(self._readbuffer)
|
||||
|
||||
def _cmd( self, aCommand, aArg = 0 ) :
|
||||
'''Send aCommand to hc05 with given argument.'''
|
||||
self._buffer[3] = aCommand
|
||||
self._buffer[5] = aArg >> 8
|
||||
self._buffer[6] = aArg
|
||||
|
||||
cs = 0
|
||||
for i in range(1, 7) :
|
||||
cs -= self._buffer[i]
|
||||
|
||||
#Set the checksum.
|
||||
self._buffer[7] = cs >> 8
|
||||
self._buffer[8] = cs
|
||||
|
||||
self._clear() #Make sure return buffer is empty.
|
||||
self.write(self._buffer)
|
||||
|
||||
@property
|
||||
def readbuffer( self ):
|
||||
return self._readbuffer
|
||||
|
||||
def result( self ) :
|
||||
'''Wait for result and return # of bytes read. Result is in _readbuffer.'''
|
||||
for i in range(1, 100) :
|
||||
if self.any() :
|
||||
return self.readinto(self._readbuffer)
|
||||
sleep_ms(_WAIT)
|
||||
|
||||
return 0
|
||||
|
||||
def resultnum( self ) :
|
||||
'''Read result, then pull 16 bit # from it.'''
|
||||
res = self.result()
|
||||
if res >= 10 :
|
||||
return (self._readbuffer[5] << 8 | self._readbuffer[6])
|
||||
return 0
|
||||
|
||||
def printres( self ) :
|
||||
'''Print result as string of hex values.'''
|
||||
b = self.result()
|
||||
for i in range(0, b) :
|
||||
print(str(hex(self._readbuffer[i])) + ',', end='')
|
||||
print('/')
|
||||
|
||||
def next( self ) :
|
||||
'''Play next song.'''
|
||||
self._cmd(1)
|
||||
|
||||
def prev( self ) :
|
||||
'''Play previous song.'''
|
||||
self._cmd(2)
|
||||
|
||||
def play( self, aIndex ) :
|
||||
'''Play song at given index.'''
|
||||
self._cmd(3, aIndex)
|
||||
|
||||
def volume( self, aLevel ) :
|
||||
'''Set volume to absolute value.'''
|
||||
self._cmd(6, aLevel & 0x1E)
|
||||
|
||||
def qvolume( self ) :
|
||||
self._cmd(0x43)
|
||||
return self.resultnum()
|
||||
|
||||
def equalizer( self, aArg ) :
|
||||
'''Set equalizer type. (Normal, Pop, Rock, Jazz, Classical, Base)'''
|
||||
self._cmd(7, aArg)
|
||||
|
||||
def qequalizer( self ) :
|
||||
self._cmd(0x44)
|
||||
return self.resultnum()
|
||||
|
||||
def qsdfiles( self ) :
|
||||
'''return # of files on sd card.'''
|
||||
self._cmd(0x48)
|
||||
return self.resultnum()
|
||||
|
||||
def qsdtrack( self ) :
|
||||
'''return current sd card track #.'''
|
||||
self._cmd(0x4C)
|
||||
return self.resultnum()
|
||||
|
||||
def qflashfiles( self ) :
|
||||
'''return # of files in flash memory.'''
|
||||
self._cmd(0x49)
|
||||
return self.resultnum()
|
||||
|
||||
def qflashtrack( self ) :
|
||||
'''return current flash track #.'''
|
||||
self._cmd(0x4D)
|
||||
return self.resultnum()
|
||||
|
||||
def sleep( self, abSleep ) :
|
||||
'''Set/clear low power mode.'''
|
||||
self._cmd(0xA if abSleep else 0xB)
|
||||
|
||||
def reset( self ) :
|
||||
'''Reset the device.'''
|
||||
self._cmd(0x0C)
|
||||
|
||||
def pause( self, abTF ) :
|
||||
'''Pause or resume play.'''
|
||||
p = 0x0E if abTF else 0x0D
|
||||
self._cmd(0x0E)
|
||||
|
||||
def folder( self, aDir ) :
|
||||
'''Specify folder.'''
|
||||
self._cmd(0x0F, aDir)
|
||||
|
||||
def folderandfile( self, aFolder, aFile ) :
|
||||
'''Play specified file in specified folder.'''
|
||||
self._cmd(0x12, (aFolder << 8) | aFile)
|
||||
|
||||
def playback( self, aMode ) :
|
||||
'''Set playback mode: 0-Repeat, 1-Folder repeat, 2-Single repeat, 3-Random'''
|
||||
self._cmd(8, aMode)
|
||||
|
||||
def source( self, aSource ) :
|
||||
'''Set play source, 0-SD, 1-TF, 2-AUX, 3-SLEEP, 4-FLASH.
|
||||
I don't know what TF, AUX or SLEEP are.'''
|
||||
self._cmd(9, aSource)
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#Driver for JQ6500 MP3 player, using serial communication.
|
||||
|
||||
#See documentation at:
|
||||
# https://www.elecfreaks.com/wiki/index.php?title=JQ6500_Mini_MP3_Module
|
||||
# http://sparks.gogo.co.nz/jq6500/index.html
|
||||
|
||||
#Each command starts with byte 0x7E
|
||||
#Followed by a byte indicating the number of bytes which follow including the terminating byte (including termination)
|
||||
#Followed by a byte indicating the command to execute
|
||||
#Followed by an optional first argument byte
|
||||
#Followed by an optional second argument byte
|
||||
#Followed by the byte 0xEF as the termination byte
|
||||
|
||||
#The next and prev commands wrap when they hit the end of the list.
|
||||
#next (play next song) 0x7E 02 01 EF
|
||||
#prev (play prev song) 0x7E 02 02 EF
|
||||
#play song at index nn = 1-?? 0x7E 04 03 nn nn EF.
|
||||
#volume+ 0x7E 02 04 EF
|
||||
#volume- 0x7E 02 05 EF
|
||||
#assigned volume nn = 0-30 0x7E 03 06 nn EF
|
||||
#assigned eq nn (0-5) 0x7E 03 07 nn EF
|
||||
# Eq values are Normal, Pop, Rock, Jazz, Classical, Base
|
||||
#sleep mode 0x7E 02 0A EF
|
||||
#chip reset 0x7E 02 0C EF
|
||||
#play 0x7E 02 0D EF
|
||||
#pause 0x7E 02 0E EF
|
||||
#next/pref folder 1 = next, 0 = prev 0x7E 03 0F nn EF
|
||||
#play folder/file (mm,nn) 0x7E 04 12 mm nn EF
|
||||
# Folders are named 01, 02..99. Files 001, 002 ... 999.
|
||||
|
||||
from machine import UART
|
||||
|
||||
class jq6500(UART):
|
||||
'''Initialize jq6500 at given UART 0-2'''
|
||||
def __init__(self, aUART, aBaud = 9600):
|
||||
super(jq6500, self).__init__(aUART, aBaud)
|
||||
self._buffer = bytearray(8)
|
||||
self._buffer[0] = 0x7E #commands always start with this.
|
||||
|
||||
def _write( self, *aCommand ) :
|
||||
'''Write command bytes to device.'''
|
||||
i = 2 #Commands are always at least 2 in length.
|
||||
for v in aCommand :
|
||||
self._buffer[i] = v
|
||||
i += 1
|
||||
|
||||
self._buffer[1] = i - 1 #Set length of command string.
|
||||
self._buffer[i] = 0xEF #Put terminator at end of command string.
|
||||
self.write(self._buffer)
|
||||
|
||||
# def next( self ) :
|
||||
# '''Play next song.'''
|
||||
# self._write(01)
|
||||
#
|
||||
# def prev( self ) :
|
||||
# '''Play previous song.'''
|
||||
# self._write(02)
|
||||
|
||||
def play( self, aIndex ) :
|
||||
'''Play song at given index.'''
|
||||
self._write(03, aIndex >> 8, aIndex)
|
||||
|
||||
# def volumechange( self, aDir ) :
|
||||
# '''Adjust volume up/down by given amount.'''
|
||||
# if aDir < 0 :
|
||||
# d = 4
|
||||
# aDir = -aDir
|
||||
# else:
|
||||
# d = 5
|
||||
# for x in range(0, aDir):
|
||||
# self._write(d)
|
||||
|
||||
def volume( self, aLevel ) :
|
||||
'''Set volume to absolute value.'''
|
||||
self._write(06, aLevel & 0x1E)
|
||||
|
||||
def equalizer( self, aArg ) :
|
||||
'''Set equalizer type. (Normal, Pop, Rock, Jazz, Classical, Base)'''
|
||||
self._write(07, aArg)
|
||||
|
||||
def sleep( self ) :
|
||||
'''Go into low power mode.'''
|
||||
self._write(0x0A)
|
||||
|
||||
# def reset( self ) :
|
||||
# '''Reset the device.'''
|
||||
# self._write(0x0C)
|
||||
#
|
||||
# def pause( self, abTF ) :
|
||||
# '''Pause or resume play.'''
|
||||
# p = 0x0E if abTF else 0x0D
|
||||
# self._write(0x0E)
|
||||
#
|
||||
# def nextfolder( self, aDir ) :
|
||||
# '''Next folder.'''
|
||||
# self.write(0x0F, 1 if aDir else 0)
|
||||
#
|
||||
# def folderandfile( self, aFolder, aFile ) :
|
||||
# '''Play specified file in specified folder.'''
|
||||
# self.write(12, aFolder, aFile)
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# Controller for the quicrun 1060 Electronic Speed Control (ESP)
|
||||
#This controller works through the pca9865 servo controller.
|
||||
|
||||
from time import sleep_ms
|
||||
|
||||
#todo: May need to move speed values over time if the battery cannot handle it.
|
||||
|
||||
class quicrun(object):
|
||||
'''docstring for quicrun'''
|
||||
_STOP = const(50)
|
||||
_FORWARD_MAX = const(68)
|
||||
_FORWARD_MIN = const(52)
|
||||
_BACKWARD_MAX = const(30)
|
||||
_BACKWARD_MIN = const(48)
|
||||
_BACKWARD_INIT = const(45)
|
||||
|
||||
@staticmethod
|
||||
def getperc( aMin, aMax, aPerc ) :
|
||||
return (((aMax - aMin) * aPerc) // 100) + aMin
|
||||
|
||||
def __init__(self, aPCA, aIndex):
|
||||
'''aPCA = pca9865 object to use for PWM control of the ESC.
|
||||
aIndex = Servo index on pca9865 (0-15).
|
||||
'''
|
||||
super(quicrun, self).__init__()
|
||||
self._pca = aPCA
|
||||
self._index = aIndex
|
||||
self.reset()
|
||||
|
||||
def reset( self ) :
|
||||
self._pca.set(self._index, 75)
|
||||
sleep_ms(500)
|
||||
self._pca.set(self._index, 100)
|
||||
sleep_ms(500)
|
||||
self._pca.set(self._index, _STOP)
|
||||
self._curspeed = 0
|
||||
|
||||
def _set( self, aValue ) :
|
||||
self._pca.set(self._index, aValue)
|
||||
|
||||
def _reverse( self ) :
|
||||
if self._currspeed >= 0 :
|
||||
self._set(_STOP)
|
||||
sleep_ms(100)
|
||||
self._set(_BACKWARD_INIT)
|
||||
sleep_ms(100)
|
||||
self._set(_STOP)
|
||||
sleep_ms(100)
|
||||
|
||||
def speed( self, aSpeed ) :
|
||||
'''Set speed -100 to 100.'''
|
||||
aSpeed = max(min(100, aSpeed), -100)
|
||||
|
||||
if aSpeed == 0 :
|
||||
self._set(_STOP)
|
||||
else:
|
||||
if aSpeed > 0 :
|
||||
self._set(quicrun.getperc(_FORWARD_MIN, _FORWARD_MAX, aSpeed))
|
||||
else:
|
||||
self._reverse()
|
||||
self._set(quicrun.getperc(_BACKWARD_MAX, _BACKWARD_MIN, 100 + aSpeed))
|
||||
|
||||
self._currspeed = aSpeed
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
from machine import Pin
|
||||
|
||||
# 28byj stepper motor controller
|
||||
|
||||
#2, 0, 4, 5
|
||||
#WAVE and FULL steps don't really work at less than 500us timing.
|
||||
|
||||
class byj(object):
|
||||
'''docstring for byj '''
|
||||
|
||||
_STEPANGLE = 5.625
|
||||
_RATIO = 64.0
|
||||
_ANGH = _STEPANGLE / _RATIO
|
||||
_FULLROTATIONH = 360.0 / _ANGH
|
||||
# _FULLROTATIONH = 360.0 / _STEPANGLE * _RATIO
|
||||
|
||||
_HALFSTEP = (0x1, 0x3, 0x2, 0x6, 0x4, 0xC, 0x8, 0x9)
|
||||
_WAVESTEP = (0x1, 0x2, 0x4, 0x8, 0x1, 0x2, 0x4, 0x8)
|
||||
_FULLSTEP = (0x3, 0x6, 0xC, 0x9, 0x3, 0x6, 0xC, 0x9)
|
||||
_STEPLEN = len(_HALFSTEP)
|
||||
_STEPS = (_HALFSTEP, _WAVESTEP, _FULLSTEP)
|
||||
_DEG = (_ANGH, _ANGH * 2.0, _ANGH * 2.0)
|
||||
|
||||
_HALF, _WAVE, _FULL = range(len(_STEPS))
|
||||
|
||||
def __init__( self, aStepType, aPins ):
|
||||
super(byj, self).__init__()
|
||||
if len(aPins) != 4:
|
||||
raise('Need 4 pins')
|
||||
|
||||
self.steptype = aStepType
|
||||
self._pins = [Pin(p, Pin.OUT) for p in aPins]
|
||||
self._index = 0
|
||||
self._direction = 1
|
||||
self._angle = 0 #Angle in degrees.
|
||||
self._steps = 0
|
||||
|
||||
@property
|
||||
def angle( self ):
|
||||
return self._angle
|
||||
|
||||
@angle.setter
|
||||
def angle( self, aValue ):
|
||||
delta = aValue - self._angle
|
||||
self.move(delta)
|
||||
|
||||
def reset( self, aAngle ):
|
||||
''' '''
|
||||
self._angle = aAngle
|
||||
|
||||
def move( self, aDelta ):
|
||||
''' '''
|
||||
self.direction = aDelta
|
||||
self._angle = (self._angle + aDelta) % 360
|
||||
self._steps = abs(aDelta) / byj._DEG[self.steptype]
|
||||
|
||||
@property
|
||||
def moving( self ): return self._steps > 0
|
||||
|
||||
@property
|
||||
def steptype( self ):
|
||||
return self._steptype
|
||||
|
||||
@steptype.setter
|
||||
def steptype( self, aValue ):
|
||||
self._steptype = max(0, min(len(byj._STEPS), aValue))
|
||||
|
||||
@property
|
||||
def direction( self ):
|
||||
return self._direction
|
||||
|
||||
@direction.setter
|
||||
def direction( self, aValue ):
|
||||
self._direction = 1 if aValue >= 0 else -1
|
||||
|
||||
def _nextindex( self ):
|
||||
#This works as long as _STEPLEN is 8.
|
||||
self._index = (self._index + self.direction) & 0x07
|
||||
|
||||
def stop( self ):
|
||||
''' '''
|
||||
for p in self._pins:
|
||||
p.value(0)
|
||||
|
||||
def _setpins( self, aValue ):
|
||||
''' '''
|
||||
# print(aValue)
|
||||
for p in self._pins:
|
||||
v = aValue & 1
|
||||
aValue >>= 1
|
||||
p.value(v)
|
||||
|
||||
def update( self, aDT ):
|
||||
''' '''
|
||||
if self.moving:
|
||||
st = byj._STEPS[self.steptype]
|
||||
s = st[self._index]
|
||||
self._setpins(s)
|
||||
self._nextindex()
|
||||
self._steps -= 1;
|
||||
|
||||
from utime import sleep_us
|
||||
def make(aType):
|
||||
return byj(aType, (2, 0, 4, 5))
|
||||
|
||||
def test( b, aDelay, aAngle ):
|
||||
''' '''
|
||||
def domove():
|
||||
print(b.angle)
|
||||
while b.moving:
|
||||
b.update(aDelay)
|
||||
sleep_us(aDelay)
|
||||
|
||||
b.angle = aAngle
|
||||
domove()
|
||||
b.angle -= 45
|
||||
domove()
|
||||
b.angle += 180
|
||||
domove()
|
||||
|
||||
def move(b, aDelay, aAngle):
|
||||
b.angle = aAngle
|
||||
print(b.angle)
|
||||
while b.moving:
|
||||
b.update(aDelay)
|
||||
sleep_us(aDelay)
|
|
@ -0,0 +1,91 @@
|
|||
#cat trainer and treat dispenser.
|
||||
|
||||
from machine import Pin, PWM
|
||||
from time import sleep_ms
|
||||
from uos import urandom
|
||||
|
||||
class cat(object):
|
||||
'''Control activation of triggers and LEDs, look for input and dispense a treat
|
||||
as a result. The LED indicates which switch is active. If that switch is
|
||||
triggered, a treat is dispensed and a new switch is activated.'''
|
||||
|
||||
_LEDPINS = (2, 0, 4, 5)
|
||||
_SWITCHPINS = (15, 13, 12, 10)
|
||||
_SERVOPIN = 14
|
||||
_RANDOMCOUNT = 256
|
||||
_UPVALUE = 10
|
||||
_DOWNVALUE = 60
|
||||
_UPDOWNPAUSE = 300
|
||||
_DELAYTIME = 500 #Delay for 5 seconds between switch activations.
|
||||
|
||||
def __init__( self ):
|
||||
super(cat, self).__init__()
|
||||
|
||||
rs = urandom(cat._RANDOMCOUNT)
|
||||
div = 255 / len(cat._LEDPINS)
|
||||
#Create array of random indexes for the LED/switches.
|
||||
self._randoms = [0 for r in rs] #int(r / div) for r in rs]
|
||||
self._randindex = 0
|
||||
|
||||
self._active = -1
|
||||
self._delay = 0
|
||||
|
||||
self._leds = [Pin(p, Pin.OUT) for p in cat._LEDPINS]
|
||||
self._switches = [Pin(p, Pin.IN) for p in cat._SWITCHPINS]
|
||||
|
||||
self._servo = PWM(Pin(cat._SERVOPIN), freq = 50)
|
||||
self._servo.duty(cat._DOWNVALUE)
|
||||
self._prev = 0
|
||||
|
||||
self.next() #Pick 1st active LED/switch.
|
||||
|
||||
def noactive( self ):
|
||||
''' Turn all LED/switches off. '''
|
||||
self._active = -1
|
||||
self.updateleds()
|
||||
|
||||
def updateleds( self ):
|
||||
''' Update LED to turn the correct one on. '''
|
||||
for i, l in enumerate(self._leds):
|
||||
l.value(1 if i == self._active else 0)
|
||||
|
||||
def next( self ):
|
||||
''' Pick a new switch/LED to make active. '''
|
||||
self._active = self._randoms[self._randindex]
|
||||
self._randindex += 1
|
||||
if self._randindex >= len(self._randoms):
|
||||
self._randindex = 0
|
||||
|
||||
self.updateleds()
|
||||
|
||||
def dispense( self ):
|
||||
''' Dispense a treat and pick a new active switch. '''
|
||||
self._servo.duty(cat._UPVALUE)
|
||||
sleep_ms(cat._UPDOWNPAUSE)
|
||||
self._servo.duty(cat._DOWNVALUE)
|
||||
self._delay = cat._DELAYTIME
|
||||
self.noactive()
|
||||
|
||||
def check( self ):
|
||||
''' Check to see if switch was hit and released. '''
|
||||
v = self._switches[self._active].value()
|
||||
if v != self._prev:
|
||||
if v == 0: #If the switch isn't touched, but it was before.
|
||||
print('dispense')
|
||||
self.dispense()
|
||||
self._prev = v
|
||||
|
||||
def run( self ):
|
||||
'''Main loop for cat treat dispenser.'''
|
||||
while 1:
|
||||
if self._delay:
|
||||
self._delay -= 100
|
||||
if self._delay <= 0:
|
||||
self.next()
|
||||
self._delay = 0
|
||||
else:
|
||||
self.check()
|
||||
|
||||
sleep_ms(100)
|
||||
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
#cat trainer and treat dispenser.
|
||||
|
||||
from machine import Pin
|
||||
from time import sleep_ms
|
||||
from uos import urandom
|
||||
|
||||
class cat(object):
|
||||
'''Control activation of triggers and LEDs, look for input and dispense a treat
|
||||
as a result. The LED indicates which switch is active. If that switch is
|
||||
triggered, a treat is dispensed using an archimedes screw device and a new switch is activated.'''
|
||||
|
||||
_LEDPINS = (2, 0, 4, 5)
|
||||
_SWITCHPINS = (15, 13, 12, 10)
|
||||
_SCREWPIN = 16
|
||||
_RANDOMCOUNT = 256
|
||||
_FRAMERATE = 100 #ms
|
||||
_ONVALUE = 100
|
||||
_OFFVALUE = 0
|
||||
_SCREWTIME = 5500
|
||||
_DELAYTIME = _FRAMERATE * 50 #Delay for 5 seconds between switch activations.
|
||||
|
||||
def __init__( self ):
|
||||
super(cat, self).__init__()
|
||||
print('Starting.')
|
||||
|
||||
rs = urandom(cat._RANDOMCOUNT)
|
||||
div = 255 / len(cat._LEDPINS)
|
||||
#Create array of random indexes for the LED/switches.
|
||||
self._randoms = [0 for r in rs] #int(r / div) for r in rs]
|
||||
self._randindex = 0
|
||||
|
||||
self._active = -1
|
||||
self._delay = 0
|
||||
|
||||
self._leds = [Pin(p, Pin.OUT) for p in cat._LEDPINS]
|
||||
self._switches = [Pin(p, Pin.IN) for p in cat._SWITCHPINS]
|
||||
|
||||
self._screwpin = Pin(cat._SCREWPIN, Pin.OUT)
|
||||
self.screwon = False
|
||||
|
||||
self._prev = 0
|
||||
|
||||
self.next() #Pick 1st active LED/switch.
|
||||
|
||||
@property
|
||||
def screwon( self ):
|
||||
return self._screw > 0
|
||||
|
||||
@screwon.setter
|
||||
def screwon( self, aTF ):
|
||||
''' Turn screw drive on/off. '''
|
||||
print('Screw On:', aTF)
|
||||
if aTF:
|
||||
self._screw = cat._SCREWTIME #Start screw on timer.
|
||||
self._screwpin.value(cat._ONVALUE)
|
||||
else:
|
||||
self._screwpin.value(cat._OFFVALUE)
|
||||
self._screw = 0 #reset the screw on timer to be done.
|
||||
|
||||
def noactive( self ):
|
||||
''' Turn all LED/switches off. '''
|
||||
self._active = -1
|
||||
self.updateleds()
|
||||
|
||||
def updateleds( self ):
|
||||
''' Update LED to turn the correct one on. '''
|
||||
for i, l in enumerate(self._leds):
|
||||
l.value(1 if i == self._active else 0)
|
||||
|
||||
def next( self ):
|
||||
''' Pick a new switch/LED to make active. '''
|
||||
self._active = self._randoms[self._randindex]
|
||||
self._randindex += 1
|
||||
if self._randindex >= len(self._randoms):
|
||||
self._randindex = 0
|
||||
|
||||
self.updateleds()
|
||||
|
||||
def dispense( self ):
|
||||
''' Dispense a treat and pick a new active switch. '''
|
||||
self.screwon = True
|
||||
self._delay = cat._DELAYTIME
|
||||
self.noactive()
|
||||
|
||||
def check( self ):
|
||||
''' Check to see if switch was hit and released. '''
|
||||
v = self._switches[self._active].value()
|
||||
if v != self._prev:
|
||||
if v == 0: #If the switch isn't touched, but it was before.
|
||||
self.dispense()
|
||||
self._prev = v
|
||||
|
||||
def updatescrew( self, dt ):
|
||||
''' update screw timer and shut off when up. '''
|
||||
if self.screwon:
|
||||
self._screw -= dt
|
||||
if self._screw <= 0:
|
||||
self.screwon = False
|
||||
|
||||
def updateinput( self, dt ):
|
||||
''' update led lighting. '''
|
||||
if self._delay:
|
||||
self._delay -= dt
|
||||
if self._delay <= 0:
|
||||
self.next()
|
||||
self._delay = 0
|
||||
else:
|
||||
self.check()
|
||||
|
||||
def run( self ):
|
||||
'''Main loop for cat treat dispenser.'''
|
||||
while 1:
|
||||
self.updatescrew(cat._FRAMERATE)
|
||||
self.updateinput(cat._FRAMERATE)
|
||||
sleep_ms(cat._FRAMERATE)
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
from machine import Pin
|
||||
from time import sleep_ms
|
||||
|
||||
class cattest(object):
|
||||
'''docstring for cattest'''
|
||||
_LEDPINS = (2, 0, 4, 5)
|
||||
_SWITCHONPIN = 1
|
||||
_SWITCHPINS = (15, 13, 12, 10)
|
||||
|
||||
|
||||
def __init__( self ):
|
||||
super(cattest, self).__init__()
|
||||
|
||||
self._leds = [Pin(p, Pin.OUT) for p in cattest._LEDPINS]
|
||||
self._switches = [Pin(p, Pin.IN) for p in cattest._SWITCHPINS]
|
||||
# self._switchon = Pin(cattest._SWITCHONPIN, Pin.OUT)
|
||||
|
||||
def updateleds( self ):
|
||||
''' '''
|
||||
for i, s in enumerate(self._switches):
|
||||
self._leds[i].value(s.value())
|
||||
|
||||
def read( self, ind ):
|
||||
return self._switches[ind].value()
|
||||
|
||||
def run( self ):
|
||||
''' '''
|
||||
while(1):
|
||||
self.updateleds()
|
||||
sleep_ms(100)
|
|
@ -0,0 +1,91 @@
|
|||
#Driver for CJMCU-IR temperature sensor. Uses mlx90614 but adds serial interface to it.
|
||||
|
||||
from machine import UART
|
||||
from utime import sleep_ms
|
||||
|
||||
#Format of data output from the device:
|
||||
#length: 9
|
||||
# Byte0 Header Flags 0x66
|
||||
# Byte1 Header Flags 0x66
|
||||
# Byte2 data output mode (0x01 continuous output; 0x02 query output, the default for continuous output mode)
|
||||
# Byte3 Measured data length (counted by Byte)
|
||||
# Byte4 Temperature 1 Upper 8 bits
|
||||
# Byte5 Temperature 1 Lower 8 bits
|
||||
# Byte6 Temperature 2 Upper 8 bits
|
||||
# Byte7 Temperature 2 Lower 8 bits
|
||||
# Byte8 data parity (all data accumulation, take the low 8-bit)
|
||||
#
|
||||
#Celcius Temperature calculation method:
|
||||
#
|
||||
#Temperature = Data High 8 bits << 8 | Lower 8 bits of data, the result is the actual temperature multiplied by 100.
|
||||
#
|
||||
#Command instructions:
|
||||
#Lenght: 4
|
||||
#Byte0 Header Flags 0x66
|
||||
#Byte1 Header Flags 0x66
|
||||
#Byte2 Sets the command:
|
||||
# 0x01 Continuous output mode
|
||||
# 0x02 Query output mode
|
||||
# 0x11 Set the baud rate to 9600
|
||||
# 0x12 Set the baud rate to 57600
|
||||
# 0x13 Set the baud rate to 115200
|
||||
#Byte3 End of frame flag 0x56
|
||||
|
||||
def c2f( aValue ):
|
||||
'''Celcius to Farenheit conversion.'''
|
||||
return (aValue * 9.0 / 5.0) + 32.0
|
||||
|
||||
class cjmcu(object) :
|
||||
"""docstring for cjmcu"""
|
||||
_CONTINUOUS = const(1)
|
||||
_POLL = const(2)
|
||||
|
||||
_RATEBASE = 0x11
|
||||
_BAUD9600 = const(0)
|
||||
_BAUD19200 = const(1)
|
||||
_BAUD38400 = const(2)
|
||||
|
||||
def __init__(self, aLoc):
|
||||
print('super')
|
||||
super(cjmcu, self).__init__()
|
||||
print('creating uart')
|
||||
sleep_ms(1000)
|
||||
self._uart = UART(aLoc, 19200)
|
||||
print('init')
|
||||
sleep_ms(1000)
|
||||
self._mode = _POLL
|
||||
self._output = bytearray(4)
|
||||
self._output[0] = 0x66
|
||||
self._output[1] = 0x66
|
||||
self._output[2] = self._mode
|
||||
self._output[3] = 0x56
|
||||
self._input = bytearray(9)
|
||||
|
||||
self.update()
|
||||
|
||||
def write( self ) :
|
||||
print('write', self._output)
|
||||
self._uart.write(self._output)
|
||||
|
||||
def read( self ) :
|
||||
print('read', len(self.input))
|
||||
self._uart.readinto(self._input)
|
||||
|
||||
def update( self ) :
|
||||
self.write()
|
||||
self.read()
|
||||
|
||||
def setbaud( self, aBaud ) :
|
||||
self._output[2] = _BAUDBASE + aBaud
|
||||
self.update()
|
||||
self._output[2] = self._mode
|
||||
self._uart.deinit()
|
||||
self._uart.init(9600 << aBaud)
|
||||
|
||||
def temps( self ) :
|
||||
v1 = (self._input[4] << 8) | self._input[5]
|
||||
v2 = (self._input[6] << 8) | self._input[7]
|
||||
return (v1 / 100.0, v2 / 100.0)
|
||||
|
||||
|
||||
|
|
@ -377,7 +377,7 @@ class accel(object) :
|
|||
|
||||
self.setclocksource(_CLOCK_PLL_XGYRO)
|
||||
self.setfullscalegyrorange(_GYRO_FS_250)
|
||||
self.setfulscaleaccelrange(_ACCEL_FS_2)
|
||||
self.setfullscaleaccelrange(_ACCEL_FS_2)
|
||||
self.setsleepenabled(False)
|
||||
|
||||
def getrate( self ) :
|
||||
|
@ -531,7 +531,7 @@ class accel(object) :
|
|||
return [(self._data6[i] << 8) | self._data6[i + 1] for i in range(0, len(self._data6), 2)]
|
||||
|
||||
def getrotation( self ) :
|
||||
self._readdata(_RA_GYRO_XOUT_H, self.data6)
|
||||
self._readdata(_RA_GYRO_XOUT_H, self._data6)
|
||||
return [(self._data6[i] << 8) | self._data6[i + 1] for i in range(0, len(self._data6), 2)]
|
||||
|
||||
def reset( self ) :
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.ida
|
||||
/bootbackup.py
|
||||
|
|
Ładowanie…
Reference in New Issue