From c4f60a9cf8f23f8a1e9680ce3e0336e51a9a7602 Mon Sep 17 00:00:00 2001 From: Benjamin Tayehanpour Date: Sat, 26 Sep 2026 09:46:51 +0000 Subject: [PATCH] decoder --- decoder.py | 136 ++++++++++++++++++++ display.py | 18 +++ kladd/{decoder_samle => decoder_sample.txt} | 0 kladd/{pins => pins.txt} | 0 4 files changed, 154 insertions(+) create mode 100755 decoder.py create mode 100644 display.py rename kladd/{decoder_samle => decoder_sample.txt} (100%) rename kladd/{pins => pins.txt} (100%) diff --git a/decoder.py b/decoder.py new file mode 100755 index 0000000..6cbf11f --- /dev/null +++ b/decoder.py @@ -0,0 +1,136 @@ +import asyncio + +import asyncpio + +class decoder: + + """Class to decode mechanical rotary encoder pulses.""" + + def __init__(self, pi, gpioA, gpioB, callback): + + """ + Instantiate the class with the pi and gpios connected to + rotary encoder contacts A and B. The common contact + should be connected to ground. The callback is + called when the rotary encoder is turned. It takes + one parameter which is +1 for clockwise and -1 for + counterclockwise. + + EXAMPLE + + import time + import asyncpio + + import rotary_encoder + + pos = 0 + + def callback(way): + + global pos + + pos += way + + print("pos={}".format(pos)) + + pi = asyncpio.pi() + await pi.connect() + + decoder = rotary_encoder.decoder(pi, 7, 8, callback) + await decoder.start() + + await asyncio.sleep(300) + + await decoder.cancel() + + await pi.stop() + + """ + + self.pi = pi + self.gpioA = gpioA + self.gpioB = gpioB + self.callback = callback + + self.levA = 0 + self.levB = 0 + + self.lastGpio = None + + async def start(self): + await self.pi.set_mode(self.gpioA, asyncpio.INPUT) + await self.pi.set_mode(self.gpioB, asyncpio.INPUT) + + await self.pi.set_pull_up_down(self.gpioA, asyncpio.PUD_UP) + await self.pi.set_pull_up_down(self.gpioB, asyncpio.PUD_UP) + + self.cbA = await self.pi.callback(self.gpioA, asyncpio.EITHER_EDGE, self._pulse) + self.cbB = await self.pi.callback(self.gpioB, asyncpio.EITHER_EDGE, self._pulse) + + def _pulse(self, gpio, level, tick): + + """ + Decode the rotary encoder pulse. + + +---------+ +---------+ 0 + | | | | + A | | | | + | | | | + +---------+ +---------+ +----- 1 + + +---------+ +---------+ 0 + | | | | + B | | | | + | | | | + ----+ +---------+ +---------+ 1 + """ + + if gpio == self.gpioA: + self.levA = level + else: + self.levB = level; + + if gpio != self.lastGpio: # debounce + self.lastGpio = gpio + + if gpio == self.gpioA and level == 1: + if self.levB == 1: + self.callback(1) + elif gpio == self.gpioB and level == 1: + if self.levA == 1: + self.callback(-1) + + async def cancel(self): + + """ + Cancel the rotary encoder decoder. + """ + + await self.cbA.cancel() + await self.cbB.cancel() + +# async def main(): +# pos = 0 +# +# def callback(way): +# +# nonlocal pos +# +# pos += way +# +# print("pos={}".format(pos)) +# +# pi = asyncpio.pi() +# await pi.connect() +# +# decoder = decoder(pi, 7, 8, callback) +# await decoder.start() +# +# await asyncio.sleep(300) +# +# await decoder.cancel() +# +# await pi.stop() + +#if __name__ == "__main__": +# asyncio.run(main()) diff --git a/display.py b/display.py new file mode 100644 index 0000000..f01ffb3 --- /dev/null +++ b/display.py @@ -0,0 +1,18 @@ +from LCD import LCD + +class display: + def __init__(self, width=16, height=4, i2c_addr=0x27): + self.width = width + self.height = height + self.device = LCD(2, i2c_addr, True) + self.contents = [""] * self.height + + def redraw(self): + for row, line in enumerate(self.contents): + self.device.message(row + 1, line) + + def read(self): + pass + + def write(self): + pass \ No newline at end of file diff --git a/kladd/decoder_samle b/kladd/decoder_sample.txt similarity index 100% rename from kladd/decoder_samle rename to kladd/decoder_sample.txt diff --git a/kladd/pins b/kladd/pins.txt similarity index 100% rename from kladd/pins rename to kladd/pins.txt