-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
567 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Pico W Setup | ||
|
||
When installing the Pico "W" (Wireless), you will need to download | ||
a different version of the MicroPython runtime. | ||
|
||
The list of runtime images is on the | ||
[https://micropython.org/download/RPI_PICO_W](https://micropython.org/download/RPI_PICO_W/) page. | ||
|
||
In this example, we are using [v1.24.1 (2024-11-29) .uf2](https://github.com/micropython/micropython/releases/tag/v1.24.1). | ||
|
||
Here is the image from Thonny that shows | ||
what version you are using. Note that you MUST select BOTSEL button | ||
before Thonny will download the new MicroPython runtime. | ||
|
||
![Pico W Thonny Setup for MicroPython 1.24.1](./06-thonny-pico-w-setup.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from machine import I2C, Pin | ||
import time | ||
|
||
# I2C setup | ||
i2c = I2C(0, sda=Pin(0), scl=Pin(1)) | ||
|
||
# Device addresses | ||
RTC_ADDR = 0x68 # Both DS1307 and DS3231 use 0x68 | ||
|
||
def identify_rtc(): | ||
""" | ||
Identify whether the RTC is a DS1307 or DS3231 | ||
Returns: String identifying the RTC type | ||
""" | ||
try: | ||
# Try to read the status register (0x0F) - only exists on DS3231 | ||
i2c.writeto(RTC_ADDR, b'\x0F') | ||
status = i2c.readfrom(RTC_ADDR, 1)[0] | ||
|
||
# Try to read control register (0x0E) - only exists on DS3231 | ||
i2c.writeto(RTC_ADDR, b'\x0E') | ||
control = i2c.readfrom(RTC_ADDR, 1)[0] | ||
|
||
# If we got here, it's almost certainly a DS3231 | ||
# Try reading temperature registers as final confirmation | ||
i2c.writeto(RTC_ADDR, b'\x11') | ||
temp_data = i2c.readfrom(RTC_ADDR, 2) | ||
|
||
return "DS3231 (Temperature-compensated RTC)" | ||
|
||
except Exception as e: | ||
# If we couldn't read those registers, it's probably a DS1307 | ||
# Let's verify by trying to read the control register (0x07) of DS1307 | ||
try: | ||
i2c.writeto(RTC_ADDR, b'\x07') | ||
control = i2c.readfrom(RTC_ADDR, 1)[0] | ||
return "DS1307 (Basic RTC)" | ||
except: | ||
return "Unknown RTC device" | ||
|
||
def main(): | ||
print("\nRTC Model Identifier") | ||
print("-" * 40) | ||
|
||
# First check if any device is present at RTC address | ||
devices = i2c.scan() | ||
if RTC_ADDR not in devices: | ||
print(f"No RTC found at address 0x{RTC_ADDR:02X}") | ||
return | ||
|
||
# Identify the RTC | ||
rtc_type = identify_rtc() | ||
print(f"Found: {rtc_type}") | ||
|
||
if "DS3231" in rtc_type: | ||
# Read temperature for DS3231 | ||
i2c.writeto(RTC_ADDR, b'\x11') | ||
temp_data = i2c.readfrom(RTC_ADDR, 2) | ||
temp_msb = temp_data[0] | ||
temp_lsb = (temp_data[1] >> 6) * 25 # 0.25°C precision | ||
temp_c = temp_msb + (temp_lsb / 100.0) | ||
temp_f = (temp_c * 9/5) + 32 | ||
print(f"Temperature: {temp_c:.2f}°C ({temp_f:.2f}°F)") | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces | ||
|
||
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, # display off | ||
# address setting | ||
SET_MEM_ADDR, | ||
0x00, # horizontal | ||
# resolution and layout | ||
SET_DISP_START_LINE, # start at line 0 | ||
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.width > 2 * self.height 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, # display on | ||
): # on | ||
self.write_cmd(cmd) | ||
self.fill(0) | ||
self.show() | ||
|
||
def poweroff(self): | ||
self.write_cmd(SET_DISP) | ||
|
||
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 rotate(self, rotate): | ||
self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3)) | ||
self.write_cmd(SET_SEG_REMAP | (rotate & 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) |
Oops, something went wrong.