From b2928fd83df482199c9e97d63c00efe8755ee07c Mon Sep 17 00:00:00 2001 From: Guy Carver Date: Sat, 15 May 2021 09:30:48 -0400 Subject: [PATCH] Adding some random stuff --- esp8266/byj.py | 127 ++++++++++++++++++++++++++++++++++++++++++++ esp8266/cat.py | 91 +++++++++++++++++++++++++++++++ esp8266/catscrew.py | 117 ++++++++++++++++++++++++++++++++++++++++ esp8266/cattest.py | 31 +++++++++++ esp8266/cjmcu.py | 91 +++++++++++++++++++++++++++++++ 5 files changed, 457 insertions(+) create mode 100644 esp8266/byj.py create mode 100644 esp8266/cat.py create mode 100644 esp8266/catscrew.py create mode 100644 esp8266/cattest.py create mode 100644 esp8266/cjmcu.py diff --git a/esp8266/byj.py b/esp8266/byj.py new file mode 100644 index 0000000..255a483 --- /dev/null +++ b/esp8266/byj.py @@ -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) diff --git a/esp8266/cat.py b/esp8266/cat.py new file mode 100644 index 0000000..653a6d1 --- /dev/null +++ b/esp8266/cat.py @@ -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) + + diff --git a/esp8266/catscrew.py b/esp8266/catscrew.py new file mode 100644 index 0000000..59b18d0 --- /dev/null +++ b/esp8266/catscrew.py @@ -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) + + diff --git a/esp8266/cattest.py b/esp8266/cattest.py new file mode 100644 index 0000000..67b986b --- /dev/null +++ b/esp8266/cattest.py @@ -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) \ No newline at end of file diff --git a/esp8266/cjmcu.py b/esp8266/cjmcu.py new file mode 100644 index 0000000..9c32a22 --- /dev/null +++ b/esp8266/cjmcu.py @@ -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) + + +