Here are some updates
							parent
							
								
									2160dcacfd
								
							
						
					
					
						commit
						1e54d652e0
					
				@ -1,2 +1,3 @@
 | 
				
			|||||||
.idea/
 | 
					.idea/
 | 
				
			||||||
/env
 | 
					/env
 | 
				
			||||||
 | 
					/binaries
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					# The Kitchen Sink
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project uses most of the code from other projects. It pretty much does most things.
 | 
				
			||||||
@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					from dht import DHT11
 | 
				
			||||||
 | 
					from machine import Pin, SPI, ADC
 | 
				
			||||||
 | 
					from ssd1306 import SSD1306_SPI
 | 
				
			||||||
 | 
					from time import sleep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Buttons and Knobs Pins
 | 
				
			||||||
 | 
					BUTTON_PIN = Pin(34, Pin.IN)
 | 
				
			||||||
 | 
					POT_PIN = ADC(Pin(35))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# DHT Sensor
 | 
				
			||||||
 | 
					DHT_PIN = DHT11(Pin(26))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SPI PINS
 | 
				
			||||||
 | 
					MISO_PIN = Pin(19)
 | 
				
			||||||
 | 
					MOSI_PIN = Pin(23)
 | 
				
			||||||
 | 
					SCK_PIN = Pin(18)
 | 
				
			||||||
 | 
					DC_PIN = Pin(4, Pin.OUT)
 | 
				
			||||||
 | 
					CS_PIN = Pin(5, Pin.OUT)
 | 
				
			||||||
 | 
					RST_PIN = Pin(2, Pin.OUT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# VSPI Hardware channel. 80 MHz signal rate
 | 
				
			||||||
 | 
					vspi = SPI(2, baudrate=2600000, polarity=0, phase=0, bits=8, firstbit=0, sck=SCK_PIN, mosi=MOSI_PIN, miso=MISO_PIN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					oled = SSD1306_SPI(128, 64, vspi, DC_PIN, RST_PIN, CS_PIN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayWriter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, spi):
 | 
				
			||||||
 | 
					        self.spi = spi
 | 
				
			||||||
 | 
					        self.height = spi.height
 | 
				
			||||||
 | 
					        self.width = spi.width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def msg(self, msg: str, l_offset=0, top_offset=0) -> None:
 | 
				
			||||||
 | 
					        """Writes a message to an OLED display.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Will wrap text as needed.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        self.spi.fill(0)
 | 
				
			||||||
 | 
					        formatted_msg = self._split_msg(msg, l_offset, top_offset)
 | 
				
			||||||
 | 
					        for s, left, top in formatted_msg:
 | 
				
			||||||
 | 
					            self.spi.text(s, left, top)
 | 
				
			||||||
 | 
					        self.spi.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Todo make this a generator
 | 
				
			||||||
 | 
					    def _split_msg(self, msg, l_offset, top_offset) -> list:
 | 
				
			||||||
 | 
					        """Splits a message at screen width to be used for text wrapping."""
 | 
				
			||||||
 | 
					        _top_offset = top_offset
 | 
				
			||||||
 | 
					        result = []
 | 
				
			||||||
 | 
					        for e in msg.split('\n'):
 | 
				
			||||||
 | 
					            result.append((e, l_offset, _top_offset))
 | 
				
			||||||
 | 
					            _top_offset += 10
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def dht_report(dht_pin):
 | 
				
			||||||
 | 
					    dht_pin.measure()
 | 
				
			||||||
 | 
					    _temp = dht_pin.temperature()
 | 
				
			||||||
 | 
					    _hum = dht_pin.humidity()
 | 
				
			||||||
 | 
					    return _temp, _hum
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def celsius_to_fahrenheit(celsius: int):
 | 
				
			||||||
 | 
					    return (celsius * (9 / 5)) + 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					display = DisplayWriter(oled)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while True:
 | 
				
			||||||
 | 
					    button_val = BUTTON_PIN.value()
 | 
				
			||||||
 | 
					    light_sensor = round(POT_PIN.read() / 4096 * 100)
 | 
				
			||||||
 | 
					    temp, hum = dht_report(DHT_PIN)
 | 
				
			||||||
 | 
					    report = "Temp: {}C/{}F\nHum: {}%\nButton: {}\nLight: {}%".format(temp, celsius_to_fahrenheit(temp), hum,
 | 
				
			||||||
 | 
					                                                                      button_val, light_sensor)
 | 
				
			||||||
 | 
					    # print(report)
 | 
				
			||||||
 | 
					    oled.invert(button_val)
 | 
				
			||||||
 | 
					    display.msg(report)
 | 
				
			||||||
 | 
					    sleep(0.1)
 | 
				
			||||||
@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
 | 
				
			||||||
 | 
					# https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from micropython import const
 | 
				
			||||||
 | 
					import framebuf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# register definitions
 | 
				
			||||||
 | 
					SET_CONTRAST = const(0x81)
 | 
				
			||||||
 | 
					SET_ENTIRE_ON = const(0xa4)
 | 
				
			||||||
 | 
					SET_NORM_INV = const(0xa6)
 | 
				
			||||||
 | 
					SET_DISP = const(0xae)
 | 
				
			||||||
 | 
					SET_MEM_ADDR = const(0x20)
 | 
				
			||||||
 | 
					SET_COL_ADDR = const(0x21)
 | 
				
			||||||
 | 
					SET_PAGE_ADDR = const(0x22)
 | 
				
			||||||
 | 
					SET_DISP_START_LINE = const(0x40)
 | 
				
			||||||
 | 
					SET_SEG_REMAP = const(0xa0)
 | 
				
			||||||
 | 
					SET_MUX_RATIO = const(0xa8)
 | 
				
			||||||
 | 
					SET_COM_OUT_DIR = const(0xc0)
 | 
				
			||||||
 | 
					SET_DISP_OFFSET = const(0xd3)
 | 
				
			||||||
 | 
					SET_COM_PIN_CFG = const(0xda)
 | 
				
			||||||
 | 
					SET_DISP_CLK_DIV = const(0xd5)
 | 
				
			||||||
 | 
					SET_PRECHARGE = const(0xd9)
 | 
				
			||||||
 | 
					SET_VCOM_DESEL = const(0xdb)
 | 
				
			||||||
 | 
					SET_CHARGE_PUMP = const(0x8d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Subclassing FrameBuffer provides support for graphics primitives
 | 
				
			||||||
 | 
					# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
 | 
				
			||||||
 | 
					class SSD1306(framebuf.FrameBuffer):
 | 
				
			||||||
 | 
					    def __init__(self, width, height, external_vcc):
 | 
				
			||||||
 | 
					        self.width = width
 | 
				
			||||||
 | 
					        self.height = height
 | 
				
			||||||
 | 
					        self.external_vcc = external_vcc
 | 
				
			||||||
 | 
					        self.pages = self.height // 8
 | 
				
			||||||
 | 
					        self.buffer = bytearray(self.pages * self.width)
 | 
				
			||||||
 | 
					        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
 | 
				
			||||||
 | 
					        self.init_display()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def init_display(self):
 | 
				
			||||||
 | 
					        for cmd in (
 | 
				
			||||||
 | 
					                SET_DISP | 0x00,  # off
 | 
				
			||||||
 | 
					                # address setting
 | 
				
			||||||
 | 
					                SET_MEM_ADDR, 0x00,  # horizontal
 | 
				
			||||||
 | 
					                # resolution and layout
 | 
				
			||||||
 | 
					                SET_DISP_START_LINE | 0x00,
 | 
				
			||||||
 | 
					                SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
 | 
				
			||||||
 | 
					                SET_MUX_RATIO, self.height - 1,
 | 
				
			||||||
 | 
					                SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
 | 
				
			||||||
 | 
					                SET_DISP_OFFSET, 0x00,
 | 
				
			||||||
 | 
					                SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
 | 
				
			||||||
 | 
					                # timing and driving scheme
 | 
				
			||||||
 | 
					                SET_DISP_CLK_DIV, 0x80,
 | 
				
			||||||
 | 
					                SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
 | 
				
			||||||
 | 
					                SET_VCOM_DESEL, 0x30,  # 0.83*Vcc
 | 
				
			||||||
 | 
					                # display
 | 
				
			||||||
 | 
					                SET_CONTRAST, 0xff,  # maximum
 | 
				
			||||||
 | 
					                SET_ENTIRE_ON,  # output follows RAM contents
 | 
				
			||||||
 | 
					                SET_NORM_INV,  # not inverted
 | 
				
			||||||
 | 
					                # charge pump
 | 
				
			||||||
 | 
					                SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
 | 
				
			||||||
 | 
					                SET_DISP | 0x01):  # on
 | 
				
			||||||
 | 
					            self.write_cmd(cmd)
 | 
				
			||||||
 | 
					        self.fill(0)
 | 
				
			||||||
 | 
					        self.show()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def poweroff(self):
 | 
				
			||||||
 | 
					        self.write_cmd(SET_DISP | 0x00)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def poweron(self):
 | 
				
			||||||
 | 
					        self.write_cmd(SET_DISP | 0x01)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def contrast(self, contrast):
 | 
				
			||||||
 | 
					        self.write_cmd(SET_CONTRAST)
 | 
				
			||||||
 | 
					        self.write_cmd(contrast)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def invert(self, invert):
 | 
				
			||||||
 | 
					        self.write_cmd(SET_NORM_INV | (invert & 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def show(self):
 | 
				
			||||||
 | 
					        x0 = 0
 | 
				
			||||||
 | 
					        x1 = self.width - 1
 | 
				
			||||||
 | 
					        if self.width == 64:
 | 
				
			||||||
 | 
					            # displays with width of 64 pixels are shifted by 32
 | 
				
			||||||
 | 
					            x0 += 32
 | 
				
			||||||
 | 
					            x1 += 32
 | 
				
			||||||
 | 
					        self.write_cmd(SET_COL_ADDR)
 | 
				
			||||||
 | 
					        self.write_cmd(x0)
 | 
				
			||||||
 | 
					        self.write_cmd(x1)
 | 
				
			||||||
 | 
					        self.write_cmd(SET_PAGE_ADDR)
 | 
				
			||||||
 | 
					        self.write_cmd(0)
 | 
				
			||||||
 | 
					        self.write_cmd(self.pages - 1)
 | 
				
			||||||
 | 
					        self.write_data(self.buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SSD1306_I2C(SSD1306):
 | 
				
			||||||
 | 
					    def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):
 | 
				
			||||||
 | 
					        self.i2c = i2c
 | 
				
			||||||
 | 
					        self.addr = addr
 | 
				
			||||||
 | 
					        self.temp = bytearray(2)
 | 
				
			||||||
 | 
					        self.write_list = [b'\x40', None]  # Co=0, D/C#=1
 | 
				
			||||||
 | 
					        super().__init__(width, height, external_vcc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def write_cmd(self, cmd):
 | 
				
			||||||
 | 
					        self.temp[0] = 0x80  # Co=1, D/C#=0
 | 
				
			||||||
 | 
					        self.temp[1] = cmd
 | 
				
			||||||
 | 
					        self.i2c.writeto(self.addr, self.temp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def write_data(self, buf):
 | 
				
			||||||
 | 
					        self.write_list[1] = buf
 | 
				
			||||||
 | 
					        self.i2c.writevto(self.addr, self.write_list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SSD1306_SPI(SSD1306):
 | 
				
			||||||
 | 
					    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
 | 
				
			||||||
 | 
					        self.rate = 10 * 1024 * 1024
 | 
				
			||||||
 | 
					        dc.init(dc.OUT, value=0)
 | 
				
			||||||
 | 
					        res.init(res.OUT, value=0)
 | 
				
			||||||
 | 
					        cs.init(cs.OUT, value=1)
 | 
				
			||||||
 | 
					        self.spi = spi
 | 
				
			||||||
 | 
					        self.dc = dc
 | 
				
			||||||
 | 
					        self.res = res
 | 
				
			||||||
 | 
					        self.cs = cs
 | 
				
			||||||
 | 
					        import time
 | 
				
			||||||
 | 
					        self.res(1)
 | 
				
			||||||
 | 
					        time.sleep_ms(1)
 | 
				
			||||||
 | 
					        self.res(0)
 | 
				
			||||||
 | 
					        time.sleep_ms(10)
 | 
				
			||||||
 | 
					        self.res(1)
 | 
				
			||||||
 | 
					        super().__init__(width, height, external_vcc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def write_cmd(self, cmd):
 | 
				
			||||||
 | 
					        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
 | 
				
			||||||
 | 
					        self.cs(1)
 | 
				
			||||||
 | 
					        self.dc(0)
 | 
				
			||||||
 | 
					        self.cs(0)
 | 
				
			||||||
 | 
					        self.spi.write(bytearray([cmd]))
 | 
				
			||||||
 | 
					        self.cs(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def write_data(self, buf):
 | 
				
			||||||
 | 
					        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
 | 
				
			||||||
 | 
					        self.cs(1)
 | 
				
			||||||
 | 
					        self.dc(1)
 | 
				
			||||||
 | 
					        self.cs(0)
 | 
				
			||||||
 | 
					        self.spi.write(buf)
 | 
				
			||||||
 | 
					        self.cs(1)
 | 
				
			||||||
@ -1,3 +1,5 @@
 | 
				
			|||||||
# MQTT Light Sensor
 | 
					# MQTT Light Sensor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This project uses a simple photo resistor to capture data and push the result to an MQTT broker.
 | 
					This project uses a simple photo resistor to capture data and push the result to an MQTT broker.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It was one of my first attempts at build a Micropython project.
 | 
				
			||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					# Threading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The ESP32 has two cores, but Micropython will only run in single core mode. We can however use threading.
 | 
				
			||||||
@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import _thread
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def testThread():
 | 
				
			||||||
 | 
					    while True:
 | 
				
			||||||
 | 
					        print("Hello threading")
 | 
				
			||||||
 | 
					        time.sleep(15) # Time is so high so that we can actually get a repl.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_thread.start_new_thread(testThread, ())
 | 
				
			||||||
@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					import _thread
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					Loading…
					
					
				
		Reference in New Issue