Initial Release
commit
2a6cfbb1d9
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
|
@ -0,0 +1,3 @@
|
|||
# MicroPython Examples
|
||||
|
||||
Examples to accompany the "Pico Python SDK" book.
|
|
@ -0,0 +1,12 @@
|
|||
import machine
|
||||
import utime
|
||||
|
||||
sensor_temp = machine.ADC(4)
|
||||
conversion_factor = 3.3 / (65535)
|
||||
|
||||
while True:
|
||||
reading = sensor_temp.read_u16() * conversion_factor
|
||||
|
||||
temperature = 27 - (reading - 0.706)/0.001721
|
||||
print(temperature)
|
||||
utime.sleep(2)
|
|
@ -0,0 +1,9 @@
|
|||
from machine import Pin, Timer
|
||||
|
||||
led = Pin(25, Pin.OUT)
|
||||
tim = Timer()
|
||||
def tick(timer):
|
||||
global led
|
||||
led.toggle()
|
||||
|
||||
tim.init(freq=2.5, mode=Timer.PERIODIC, callback=tick)
|
|
@ -0,0 +1,35 @@
|
|||
= Using a SH1106-based OLED graphics display
|
||||
:xrefstyle: short
|
||||
|
||||
Display an image and text on I2C driven SH1106-based OLED graphics display
|
||||
such as the Pimoroni Breakout Garden 1.12" Mono OLED https://shop.pimoroni.com/products/1-12-oled-breakout?variant=29421050757203
|
||||
.
|
||||
|
||||
== Wiring information
|
||||
|
||||
See <<oled-wiring-diagram>> for wiring instructions.
|
||||
|
||||
[[oled-wiring-diagram]]
|
||||
[pdfwidth=75%]
|
||||
.Wiring the OLED to Pico using I2C
|
||||
image::pico-and-oled.png[]
|
||||
|
||||
== List of Files
|
||||
|
||||
A list of files with descriptions of their function;
|
||||
|
||||
i2c_1106oled_using_defaults.py:: The example code.
|
||||
i2c_1106oled_with_freq.py:: The example code, explicitly sets a frequency.
|
||||
sh1106.py:: SH1106 Driver Obtained from https://github.com/robert-hh/SH1106
|
||||
|
||||
== Bill of Materials
|
||||
|
||||
.A list of materials required for the example
|
||||
[[oled-bom-table]]
|
||||
[cols=3]
|
||||
|===
|
||||
| *Item* | *Quantity* | Details
|
||||
| Breadboard | 1 | generic part
|
||||
| Raspberry Pi Pico | 1 | http://raspberrypi.org/
|
||||
| Monochrome 128x128 I2C OLED Display | 1 | https://shop.pimoroni.com/products/1-12-oled-breakout?variant=29421050757203
|
||||
|===
|
|
@ -0,0 +1,34 @@
|
|||
# Display Image & text on I2C driven SH1106 OLED display
|
||||
from machine import I2C, ADC
|
||||
from sh1106 import SH1106_I2C
|
||||
import framebuf
|
||||
|
||||
|
||||
WIDTH = 128 # oled display width
|
||||
HEIGHT = 128 # oled display height
|
||||
|
||||
i2c = I2C(0) # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8), freq=400000
|
||||
print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address
|
||||
print("I2C Configuration: "+str(i2c)) # Display I2C config
|
||||
|
||||
|
||||
oled = SH1106_I2C(WIDTH, HEIGHT, i2c) # Init oled display
|
||||
|
||||
# Raspberry Pi logo as 32x32 bytearray
|
||||
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
|
||||
# Load the raspberry pi logo into the framebuffer (the image is 32x32)
|
||||
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
|
||||
|
||||
# Clear the oled display in case it has junk on it.
|
||||
oled.fill(0)
|
||||
|
||||
# Blit the image from the framebuffer to the oled display
|
||||
oled.blit(fb, 96, 0)
|
||||
|
||||
# Add some text
|
||||
oled.text("Raspberry Pi",5,5)
|
||||
oled.text("Pico",5,15)
|
||||
|
||||
# Finally update the oled display so the image & text is displayed
|
||||
oled.show()
|
|
@ -0,0 +1,33 @@
|
|||
# Display Image & text on I2C driven ssd1306 OLED display
|
||||
from machine import Pin, I2C
|
||||
from sh1106 import SH1106_I2C
|
||||
import framebuf
|
||||
|
||||
WIDTH = 128 # oled display width
|
||||
HEIGHT = 32 # oled display height
|
||||
|
||||
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000) # Init I2C using pins GP8 & GP9 (default I2C0 pins)
|
||||
print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address
|
||||
print("I2C Configuration: "+str(i2c)) # Display I2C config
|
||||
|
||||
|
||||
oled = SH1106_I2C(WIDTH, HEIGHT, i2c) # Init oled display
|
||||
|
||||
# Raspberry Pi logo as 32x32 bytearray
|
||||
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
|
||||
# Load the raspberry pi logo into the framebuffer (the image is 32x32)
|
||||
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
|
||||
|
||||
# Clear the oled display in case it has junk on it.
|
||||
oled.fill(0)
|
||||
|
||||
# Blit the image from the framebuffer to the oled display
|
||||
oled.blit(fb, 96, 0)
|
||||
|
||||
# Add some text
|
||||
oled.text("Raspberry Pi",5,5)
|
||||
oled.text("Pico",5,15)
|
||||
|
||||
# Finally update the oled display so the image & text is displayed
|
||||
oled.show()
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 200 KiB |
|
@ -0,0 +1,227 @@
|
|||
#
|
||||
# MicroPython SH1106 OLED driver, I2C and SPI interfaces
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2016 Radomir Dopieralski (@deshipu),
|
||||
# 2017 Robert Hammelrath (@robert-hh)
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
# Sample code sections
|
||||
# ------------ SPI ------------------
|
||||
# Pin Map SPI
|
||||
# - 3v - xxxxxx - Vcc
|
||||
# - G - xxxxxx - Gnd
|
||||
# - D7 - GPIO 13 - Din / MOSI fixed
|
||||
# - D5 - GPIO 14 - Clk / Sck fixed
|
||||
# - D8 - GPIO 4 - CS (optional, if the only connected device)
|
||||
# - D2 - GPIO 5 - D/C
|
||||
# - D1 - GPIO 2 - Res
|
||||
#
|
||||
# for CS, D/C and Res other ports may be chosen.
|
||||
#
|
||||
# from machine import Pin, SPI
|
||||
# import sh1106
|
||||
|
||||
# spi = SPI(1, baudrate=1000000)
|
||||
# display = sh1106.SH1106_SPI(128, 64, spi, Pin(5), Pin(2), Pin(4))
|
||||
# display.sleep(False)
|
||||
# display.fill(0)
|
||||
# display.text('Testing 1', 0, 0, 1)
|
||||
# display.show()
|
||||
#
|
||||
# --------------- I2C ------------------
|
||||
#
|
||||
# Pin Map I2C
|
||||
# - 3v - xxxxxx - Vcc
|
||||
# - G - xxxxxx - Gnd
|
||||
# - D2 - GPIO 5 - SCK / SCL
|
||||
# - D1 - GPIO 4 - DIN / SDA
|
||||
# - D0 - GPIO 16 - Res
|
||||
# - G - xxxxxx CS
|
||||
# - G - xxxxxx D/C
|
||||
#
|
||||
# Pin's for I2C can be set almost arbitrary
|
||||
#
|
||||
# from machine import Pin, I2C
|
||||
# import sh1106
|
||||
#
|
||||
# i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
|
||||
# display = sh1106.SH1106_I2C(128, 64, i2c, Pin(16), 0x3c)
|
||||
# display.sleep(False)
|
||||
# display.fill(0)
|
||||
# display.text('Testing 1', 0, 0, 1)
|
||||
# display.show()
|
||||
|
||||
from micropython import const
|
||||
import utime as time
|
||||
import framebuf
|
||||
|
||||
|
||||
# a few register definitions
|
||||
_SET_CONTRAST = const(0x81)
|
||||
_SET_NORM_INV = const(0xa6)
|
||||
_SET_DISP = const(0xae)
|
||||
_SET_SCAN_DIR = const(0xc0)
|
||||
_SET_SEG_REMAP = const(0xa0)
|
||||
_LOW_COLUMN_ADDRESS = const(0x00)
|
||||
_HIGH_COLUMN_ADDRESS = const(0x10)
|
||||
_SET_PAGE_ADDRESS = const(0xB0)
|
||||
|
||||
|
||||
class SH1106:
|
||||
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)
|
||||
fb = framebuf.FrameBuffer(self.buffer, self.width, self.height,
|
||||
framebuf.MVLSB)
|
||||
self.framebuf = fb
|
||||
# set shortcuts for the methods of framebuf
|
||||
self.fill = fb.fill
|
||||
self.fill_rect = fb.fill_rect
|
||||
self.hline = fb.hline
|
||||
self.vline = fb.vline
|
||||
self.line = fb.line
|
||||
self.rect = fb.rect
|
||||
self.pixel = fb.pixel
|
||||
self.scroll = fb.scroll
|
||||
self.text = fb.text
|
||||
self.blit = fb.blit
|
||||
|
||||
self.init_display()
|
||||
|
||||
def init_display(self):
|
||||
self.reset()
|
||||
self.fill(0)
|
||||
self.poweron()
|
||||
self.show()
|
||||
|
||||
def poweroff(self):
|
||||
self.write_cmd(_SET_DISP | 0x00)
|
||||
|
||||
def poweron(self):
|
||||
self.write_cmd(_SET_DISP | 0x01)
|
||||
|
||||
def rotate(self, flag, update=True):
|
||||
if flag:
|
||||
self.write_cmd(_SET_SEG_REMAP | 0x01) # mirror display vertically
|
||||
self.write_cmd(_SET_SCAN_DIR | 0x08) # mirror display hor.
|
||||
else:
|
||||
self.write_cmd(_SET_SEG_REMAP | 0x00)
|
||||
self.write_cmd(_SET_SCAN_DIR | 0x00)
|
||||
if update:
|
||||
self.show()
|
||||
|
||||
def sleep(self, value):
|
||||
self.write_cmd(_SET_DISP | (not value))
|
||||
|
||||
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):
|
||||
for page in range(self.height // 8):
|
||||
self.write_cmd(_SET_PAGE_ADDRESS | page)
|
||||
self.write_cmd(_LOW_COLUMN_ADDRESS | 2)
|
||||
self.write_cmd(_HIGH_COLUMN_ADDRESS | 0)
|
||||
self.write_data(self.buffer[
|
||||
self.width * page:self.width * page + self.width
|
||||
])
|
||||
|
||||
def reset(self, res):
|
||||
if res is not None:
|
||||
res(1)
|
||||
time.sleep_ms(1)
|
||||
res(0)
|
||||
time.sleep_ms(20)
|
||||
res(1)
|
||||
time.sleep_ms(20)
|
||||
|
||||
|
||||
class SH1106_I2C(SH1106):
|
||||
def __init__(self, width, height, i2c, res=None, addr=0x3c,
|
||||
external_vcc=False):
|
||||
self.i2c = i2c
|
||||
self.addr = addr
|
||||
self.res = res
|
||||
self.temp = bytearray(2)
|
||||
if res is not None:
|
||||
res.init(res.OUT, value=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.i2c.writeto(self.addr, b'\x40'+buf)
|
||||
|
||||
def reset(self):
|
||||
super().reset(self.res)
|
||||
|
||||
|
||||
class SH1106_SPI(SH1106):
|
||||
def __init__(self, width, height, spi, dc, res=None, cs=None,
|
||||
external_vcc=False):
|
||||
self.rate = 10 * 1000 * 1000
|
||||
dc.init(dc.OUT, value=0)
|
||||
if res is not None:
|
||||
res.init(res.OUT, value=0)
|
||||
if cs is not None:
|
||||
cs.init(cs.OUT, value=1)
|
||||
self.spi = spi
|
||||
self.dc = dc
|
||||
self.res = res
|
||||
self.cs = cs
|
||||
super().__init__(width, height, external_vcc)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
|
||||
if self.cs is not None:
|
||||
self.cs(1)
|
||||
self.dc(0)
|
||||
self.cs(0)
|
||||
self.spi.write(bytearray([cmd]))
|
||||
self.cs(1)
|
||||
else:
|
||||
self.dc(0)
|
||||
self.spi.write(bytearray([cmd]))
|
||||
|
||||
def write_data(self, buf):
|
||||
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
|
||||
if self.cs is not None:
|
||||
self.cs(1)
|
||||
self.dc(1)
|
||||
self.cs(0)
|
||||
self.spi.write(buf)
|
||||
self.cs(1)
|
||||
else:
|
||||
self.dc(1)
|
||||
self.spi.write(buf)
|
||||
|
||||
def reset(self):
|
||||
super().reset(self.res)
|
|
@ -0,0 +1,32 @@
|
|||
= Using a SSD1306-based OLED graphics display
|
||||
:xrefstyle: short
|
||||
|
||||
Display an image and text on I2C driven SSD1306-based OLED graphics display.
|
||||
|
||||
== Wiring information
|
||||
|
||||
See <<oled-wiring-diagram>> for wiring instructions.
|
||||
|
||||
[[oled-wiring-diagram]]
|
||||
[pdfwidth=75%]
|
||||
.Wiring the OLED to Pico using I2C
|
||||
image::pico-and-oled.png[]
|
||||
|
||||
== List of Files
|
||||
|
||||
A list of files with descriptions of their function;
|
||||
|
||||
i2c_1306oled_using_defaults.py:: The example code.
|
||||
i2c_1306oled_with_freq.py:: The example code, explicitly sets a frequency.
|
||||
|
||||
== Bill of Materials
|
||||
|
||||
.A list of materials required for the example
|
||||
[[oled-bom-table]]
|
||||
[cols=3]
|
||||
|===
|
||||
| *Item* | *Quantity* | Details
|
||||
| Breadboard | 1 | generic part
|
||||
| Raspberry Pi Pico | 1 | http://raspberrypi.org/
|
||||
| Monochrome 128x32 I2C OLED Display | 1 | https://www.adafruit.com/product/931
|
||||
|===
|
|
@ -0,0 +1,33 @@
|
|||
# Display Image & text on I2C driven ssd1306 OLED display
|
||||
from machine import Pin, I2C
|
||||
from ssd1306 import SSD1306_I2C
|
||||
import framebuf
|
||||
|
||||
WIDTH = 128 # oled display width
|
||||
HEIGHT = 32 # oled display height
|
||||
|
||||
i2c = I2C(0) # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8), freq=400000
|
||||
print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address
|
||||
print("I2C Configuration: "+str(i2c)) # Display I2C config
|
||||
|
||||
|
||||
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Init oled display
|
||||
|
||||
# Raspberry Pi logo as 32x32 bytearray
|
||||
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
|
||||
# Load the raspberry pi logo into the framebuffer (the image is 32x32)
|
||||
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
|
||||
|
||||
# Clear the oled display in case it has junk on it.
|
||||
oled.fill(0)
|
||||
|
||||
# Blit the image from the framebuffer to the oled display
|
||||
oled.blit(fb, 96, 0)
|
||||
|
||||
# Add some text
|
||||
oled.text("Raspberry Pi",5,5)
|
||||
oled.text("Pico",5,15)
|
||||
|
||||
# Finally update the oled display so the image & text is displayed
|
||||
oled.show()
|
|
@ -0,0 +1,33 @@
|
|||
# Display Image & text on I2C driven ssd1306 OLED display
|
||||
from machine import Pin, I2C
|
||||
from ssd1306 import SSD1306_I2C
|
||||
import framebuf
|
||||
|
||||
WIDTH = 128 # oled display width
|
||||
HEIGHT = 32 # oled display height
|
||||
|
||||
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000) # Init I2C using pins GP8 & GP9 (default I2C0 pins)
|
||||
print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address
|
||||
print("I2C Configuration: "+str(i2c)) # Display I2C config
|
||||
|
||||
|
||||
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Init oled display
|
||||
|
||||
# Raspberry Pi logo as 32x32 bytearray
|
||||
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
|
||||
# Load the raspberry pi logo into the framebuffer (the image is 32x32)
|
||||
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
|
||||
|
||||
# Clear the oled display in case it has junk on it.
|
||||
oled.fill(0)
|
||||
|
||||
# Blit the image from the framebuffer to the oled display
|
||||
oled.blit(fb, 96, 0)
|
||||
|
||||
# Add some text
|
||||
oled.text("Raspberry Pi",5,5)
|
||||
oled.text("Pico",5,15)
|
||||
|
||||
# Finally update the oled display so the image & text is displayed
|
||||
oled.show()
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 200 KiB |
|
@ -0,0 +1,11 @@
|
|||
from machine import Pin, I2C
|
||||
|
||||
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=100000)
|
||||
i2c.scan()
|
||||
i2c.writeto(76, b'123')
|
||||
i2c.readfrom(76, 4)
|
||||
|
||||
i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=100000)
|
||||
i2c.scan()
|
||||
i2c.writeto_mem(76, 6, b'456')
|
||||
i2c.readfrom_mem(76, 6, 4)
|
|
@ -0,0 +1,3 @@
|
|||
from machine import I2C
|
||||
|
||||
i2c = I2C(0) # defaults to SCL=Pin(9), SDA=Pin(8), freq=400000
|
|
@ -0,0 +1,5 @@
|
|||
from machine import Pin
|
||||
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
p2.irq(lambda pin: print("IRQ with flags:", pin.irq().flags()),
|
||||
Pin.IRQ_FALLING)
|
|
@ -0,0 +1,12 @@
|
|||
import time, _thread, machine
|
||||
|
||||
def task(n, delay):
|
||||
led = machine.Pin(25, machine.Pin.OUT)
|
||||
for i in range(n):
|
||||
led.high()
|
||||
time.sleep(delay)
|
||||
led.low()
|
||||
time.sleep(delay)
|
||||
print('done')
|
||||
|
||||
_thread.start_new_thread(task, (10, 0.5))
|
|
@ -0,0 +1,31 @@
|
|||
= Using PIO to drive a set of NeoPixel Ring (WS2812 LEDs)
|
||||
:xrefstyle: short
|
||||
|
||||
Combination of the PIO WS2812 demo with the Adafruit 'essential' NeoPixel example code to show off color fills, chases and of course a rainbow swirl on a 16-LED ring.
|
||||
|
||||
== Wiring information
|
||||
|
||||
See <<neopixel-wiring-diagram>> for wiring instructions.
|
||||
|
||||
[[neopixel-wiring-diagram]]
|
||||
[pdfwidth=75%]
|
||||
.Wiring the 16-LED NeoPixel Ring to Pico
|
||||
image::neopixel_ring.png[]
|
||||
|
||||
== List of Files
|
||||
|
||||
A list of files with descriptions of their function;
|
||||
|
||||
neopixel_ring.py:: The example code.
|
||||
|
||||
== Bill of Materials
|
||||
|
||||
.A list of materials required for the example
|
||||
[[ring-bom-table]]
|
||||
[cols=3]
|
||||
|===
|
||||
| *Item* | *Quantity* | Details
|
||||
| Breadboard | 1 | generic part
|
||||
| Raspberry Pi Pico | 1 | http://raspberrypi.org/
|
||||
| NeoPixel Ring | 1 | https://www.adafruit.com/product/1463
|
||||
|===
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 272 KiB |
|
@ -0,0 +1,104 @@
|
|||
# Example using PIO to drive a set of WS2812 LEDs.
|
||||
|
||||
import array, time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
# Configure the number of WS2812 LEDs.
|
||||
NUM_LEDS = 16
|
||||
PIN_NUM = 6
|
||||
brightness = 0.2
|
||||
|
||||
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
|
||||
def ws2812():
|
||||
T1 = 2
|
||||
T2 = 5
|
||||
T3 = 3
|
||||
wrap_target()
|
||||
label("bitloop")
|
||||
out(x, 1) .side(0) [T3 - 1]
|
||||
jmp(not_x, "do_zero") .side(1) [T1 - 1]
|
||||
jmp("bitloop") .side(1) [T2 - 1]
|
||||
label("do_zero")
|
||||
nop() .side(0) [T2 - 1]
|
||||
wrap()
|
||||
|
||||
|
||||
# Create the StateMachine with the ws2812 program, outputting on pin
|
||||
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
|
||||
|
||||
# Start the StateMachine, it will wait for data on its FIFO.
|
||||
sm.active(1)
|
||||
|
||||
# Display a pattern on the LEDs via an array of LED RGB values.
|
||||
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
|
||||
|
||||
##########################################################################
|
||||
def pixels_show():
|
||||
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
|
||||
for i,c in enumerate(ar):
|
||||
r = int(((c >> 8) & 0xFF) * brightness)
|
||||
g = int(((c >> 16) & 0xFF) * brightness)
|
||||
b = int((c & 0xFF) * brightness)
|
||||
dimmer_ar[i] = (g<<16) + (r<<8) + b
|
||||
sm.put(dimmer_ar, 8)
|
||||
time.sleep_ms(10)
|
||||
|
||||
def pixels_set(i, color):
|
||||
ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]
|
||||
|
||||
def pixels_fill(color):
|
||||
for i in range(len(ar)):
|
||||
pixels_set(i, color)
|
||||
|
||||
def color_chase(color, wait):
|
||||
for i in range(NUM_LEDS):
|
||||
pixels_set(i, color)
|
||||
time.sleep(wait)
|
||||
pixels_show()
|
||||
time.sleep(0.2)
|
||||
|
||||
def wheel(pos):
|
||||
# Input a value 0 to 255 to get a color value.
|
||||
# The colours are a transition r - g - b - back to r.
|
||||
if pos < 0 or pos > 255:
|
||||
return (0, 0, 0)
|
||||
if pos < 85:
|
||||
return (255 - pos * 3, pos * 3, 0)
|
||||
if pos < 170:
|
||||
pos -= 85
|
||||
return (0, 255 - pos * 3, pos * 3)
|
||||
pos -= 170
|
||||
return (pos * 3, 0, 255 - pos * 3)
|
||||
|
||||
|
||||
def rainbow_cycle(wait):
|
||||
for j in range(255):
|
||||
for i in range(NUM_LEDS):
|
||||
rc_index = (i * 256 // NUM_LEDS) + j
|
||||
pixels_set(i, wheel(rc_index & 255))
|
||||
pixels_show()
|
||||
time.sleep(wait)
|
||||
|
||||
BLACK = (0, 0, 0)
|
||||
RED = (255, 0, 0)
|
||||
YELLOW = (255, 150, 0)
|
||||
GREEN = (0, 255, 0)
|
||||
CYAN = (0, 255, 255)
|
||||
BLUE = (0, 0, 255)
|
||||
PURPLE = (180, 0, 255)
|
||||
WHITE = (255, 255, 255)
|
||||
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)
|
||||
|
||||
print("fills")
|
||||
for color in COLORS:
|
||||
pixels_fill(color)
|
||||
pixels_show()
|
||||
time.sleep(0.2)
|
||||
|
||||
print("chases")
|
||||
for color in COLORS:
|
||||
color_chase(color, 0.01)
|
||||
|
||||
print("rainbow")
|
||||
rainbow_cycle(0)
|
|
@ -0,0 +1,33 @@
|
|||
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
|
||||
|
||||
import time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
|
||||
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
|
||||
def blink_1hz():
|
||||
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
|
||||
irq(rel(0))
|
||||
set(pins, 1)
|
||||
set(x, 31) [5]
|
||||
label("delay_high")
|
||||
nop() [29]
|
||||
jmp(x_dec, "delay_high")
|
||||
|
||||
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
|
||||
set(pins, 0)
|
||||
set(x, 31) [6]
|
||||
label("delay_low")
|
||||
nop() [29]
|
||||
jmp(x_dec, "delay_low")
|
||||
|
||||
|
||||
# Create the StateMachine with the blink_1hz program, outputting on Pin(25).
|
||||
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
|
||||
|
||||
# Set the IRQ handler to print the millisecond timestamp.
|
||||
sm.irq(lambda p: print(time.ticks_ms()))
|
||||
|
||||
# Start the StateMachine.
|
||||
sm.active(1)
|
|
@ -0,0 +1,28 @@
|
|||
import time
|
||||
from rp2 import PIO, asm_pio
|
||||
from machine import Pin
|
||||
|
||||
# Define the blink program. It has one GPIO to bind to on the set instruction, which is an output pin.
|
||||
# Use lots of delays to make the blinking visible by eye.
|
||||
@asm_pio(set_init=rp2.PIO.OUT_LOW)
|
||||
def blink():
|
||||
wrap_target()
|
||||
set(pins, 1) [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
set(pins, 0) [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
wrap()
|
||||
|
||||
# Instantiate a state machine with the blink program, at 1000Hz, with set bound to Pin(25) (LED on the rp2 board)
|
||||
sm = rp2.StateMachine(0, blink, freq=1000, set_base=Pin(25))
|
||||
|
||||
# Run the state machine for 3 seconds. The LED should blink.
|
||||
sm.active(1)
|
||||
time.sleep(3)
|
||||
sm.active(0)
|
|
@ -0,0 +1,27 @@
|
|||
# Example using PIO to turn on an LED via an explicit exec.
|
||||
#
|
||||
# Demonstrates:
|
||||
# - using set_init and set_base
|
||||
# - using StateMachine.exec
|
||||
|
||||
import time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
# Define an empty program that uses a single set pin.
|
||||
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
|
||||
def prog():
|
||||
pass
|
||||
|
||||
|
||||
# Construct the StateMachine, binding Pin(25) to the set pin.
|
||||
sm = rp2.StateMachine(0, prog, set_base=Pin(25))
|
||||
|
||||
# Turn on the set pin via an exec instruction.
|
||||
sm.exec("set(pins, 1)")
|
||||
|
||||
# Sleep for 500ms.
|
||||
time.sleep(0.5)
|
||||
|
||||
# Turn off the set pin via an exec instruction.
|
||||
sm.exec("set(pins, 0)")
|
|
@ -0,0 +1,25 @@
|
|||
import time
|
||||
import rp2
|
||||
|
||||
@rp2.asm_pio()
|
||||
def irq_test():
|
||||
wrap_target()
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
irq(0)
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
nop() [31]
|
||||
irq(1)
|
||||
wrap()
|
||||
|
||||
|
||||
rp2.PIO(0).irq(lambda pio: print(pio.irq().flags()))
|
||||
|
||||
sm = rp2.StateMachine(0, irq_test, freq=1000)
|
||||
sm.active(1)
|
||||
time.sleep(1)
|
||||
sm.active(0)
|
|
@ -0,0 +1,46 @@
|
|||
# Example using PIO to wait for a pin change and raise an IRQ.
|
||||
#
|
||||
# Demonstrates:
|
||||
# - PIO wrapping
|
||||
# - PIO wait instruction, waiting on an input pin
|
||||
# - PIO irq instruction, in blocking mode with relative IRQ number
|
||||
# - setting the in_base pin for a StateMachine
|
||||
# - setting an irq handler for a StateMachine
|
||||
# - instantiating 2x StateMachine's with the same program and different pins
|
||||
|
||||
import time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
|
||||
@rp2.asm_pio()
|
||||
def wait_pin_low():
|
||||
wrap_target()
|
||||
|
||||
wait(0, pin, 0)
|
||||
irq(block, rel(0))
|
||||
wait(1, pin, 0)
|
||||
|
||||
wrap()
|
||||
|
||||
|
||||
def handler(sm):
|
||||
# Print a (wrapping) timestamp, and the state machine object.
|
||||
print(time.ticks_ms(), sm)
|
||||
|
||||
|
||||
# Instantiate StateMachine(0) with wait_pin_low program on Pin(16).
|
||||
pin16 = Pin(16, Pin.IN, Pin.PULL_UP)
|
||||
sm0 = rp2.StateMachine(0, wait_pin_low, in_base=pin16)
|
||||
sm0.irq(handler)
|
||||
|
||||
# Instantiate StateMachine(1) with wait_pin_low program on Pin(17).
|
||||
pin17 = Pin(17, Pin.IN, Pin.PULL_UP)
|
||||
sm1 = rp2.StateMachine(1, wait_pin_low, in_base=pin17)
|
||||
sm1.irq(handler)
|
||||
|
||||
# Start the StateMachine's running.
|
||||
sm0.active(1)
|
||||
sm1.active(1)
|
||||
|
||||
# Now, when Pin(16) or Pin(17) is pulled low a message will be printed to the REPL.
|
|
@ -0,0 +1,43 @@
|
|||
# Example of using PIO for PWM, and fading the brightness of an LED
|
||||
|
||||
from machine import Pin
|
||||
from rp2 import PIO, StateMachine, asm_pio
|
||||
from time import sleep
|
||||
|
||||
|
||||
@asm_pio(sideset_init=PIO.OUT_LOW)
|
||||
def pwm_prog():
|
||||
pull(noblock) .side(0)
|
||||
mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock
|
||||
mov(y, isr) # ISR must be preloaded with PWM count max
|
||||
label("pwmloop")
|
||||
jmp(x_not_y, "skip")
|
||||
nop() .side(1)
|
||||
label("skip")
|
||||
jmp(y_dec, "pwmloop")
|
||||
|
||||
|
||||
class PIOPWM:
|
||||
def __init__(self, sm_id, pin, max_count, count_freq):
|
||||
self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin))
|
||||
# Use exec() to load max count into ISR
|
||||
self._sm.put(max_count)
|
||||
self._sm.exec("pull()")
|
||||
self._sm.exec("mov(isr, osr)")
|
||||
self._sm.active(1)
|
||||
self._max_count = max_count
|
||||
|
||||
def set(self, value):
|
||||
# Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse
|
||||
value = max(value, -1)
|
||||
value = min(value, self._max_count)
|
||||
self._sm.put(value)
|
||||
|
||||
|
||||
# Pin 25 is LED on Pico boards
|
||||
pwm = PIOPWM(0, 25, max_count=(1 << 16) - 1, count_freq=10_000_000)
|
||||
|
||||
while True:
|
||||
for i in range(256):
|
||||
pwm.set(i ** 2)
|
||||
sleep(0.01)
|
|
@ -0,0 +1,48 @@
|
|||
from machine import Pin
|
||||
|
||||
@rp2.asm_pio(out_shiftdir=0, autopull=True, pull_thresh=8, autopush=True, push_thresh=8, sideset_init=(rp2.PIO.OUT_LOW, rp2.PIO.OUT_HIGH), out_init=rp2.PIO.OUT_LOW)
|
||||
def spi_cpha0():
|
||||
# Note X must be preinitialised by setup code before first byte, we reload after sending each byte
|
||||
# Would normally do this via exec() but in this case it's in the instruction memory and is only run once
|
||||
set(x, 6)
|
||||
# Actual program body follows
|
||||
wrap_target()
|
||||
pull(ifempty) .side(0x2) [1]
|
||||
label("bitloop")
|
||||
out(pins, 1) .side(0x0) [1]
|
||||
in_(pins, 1) .side(0x1)
|
||||
jmp(x_dec, "bitloop") .side(0x1)
|
||||
|
||||
out(pins, 1) .side(0x0)
|
||||
set(x, 6) .side(0x0) # Note this could be replaced with mov x, y for programmable frame size
|
||||
in_(pins, 1) .side(0x1)
|
||||
jmp(not_osre, "bitloop") .side(0x1) # Fallthru if TXF empties
|
||||
|
||||
nop() .side(0x0) [1] # CSn back porch
|
||||
wrap()
|
||||
|
||||
|
||||
class PIOSPI:
|
||||
|
||||
def __init__(self, sm_id, pin_mosi, pin_miso, pin_sck, cpha=False, cpol=False, freq=1000000):
|
||||
assert(not(cpol or cpha))
|
||||
self._sm = rp2.StateMachine(sm_id, spi_cpha0, freq=4*freq, sideset_base=Pin(pin_sck), out_base=Pin(pin_mosi), in_base=Pin(pin_sck))
|
||||
self._sm.active(1)
|
||||
|
||||
# Note this code will die spectacularly cause we're not draining the RX FIFO
|
||||
def write_blocking(wdata):
|
||||
for b in wdata:
|
||||
self._sm.put(b << 24)
|
||||
|
||||
def read_blocking(n):
|
||||
data = []
|
||||
for i in range(n):
|
||||
data.append(self._sm.get() & 0xff)
|
||||
return data
|
||||
|
||||
def write_read_blocking(wdata):
|
||||
rdata = []
|
||||
for b in wdata:
|
||||
self._sm.put(b << 24)
|
||||
rdata.append(self._sm.get() & 0xff)
|
||||
return rdata
|
|
@ -0,0 +1,42 @@
|
|||
# Example using PIO to create a UART TX interface
|
||||
|
||||
from machine import Pin
|
||||
from rp2 import PIO, StateMachine, asm_pio
|
||||
|
||||
UART_BAUD = 115200
|
||||
PIN_BASE = 10
|
||||
NUM_UARTS = 8
|
||||
|
||||
|
||||
@asm_pio(sideset_init=PIO.OUT_HIGH, out_init=PIO.OUT_HIGH, out_shiftdir=PIO.SHIFT_RIGHT)
|
||||
def uart_tx():
|
||||
# Block with TX deasserted until data available
|
||||
pull()
|
||||
# Initialise bit counter, assert start bit for 8 cycles
|
||||
set(x, 7) .side(0) [7]
|
||||
# Shift out 8 data bits, 8 execution cycles per bit
|
||||
label("bitloop")
|
||||
out(pins, 1) [6]
|
||||
jmp(x_dec, "bitloop")
|
||||
# Assert stop bit for 8 cycles total (incl 1 for pull())
|
||||
nop() .side(1) [6]
|
||||
|
||||
|
||||
# Now we add 8 UART TXs, on pins 10 to 17. Use the same baud rate for all of them.
|
||||
uarts = []
|
||||
for i in range(NUM_UARTS):
|
||||
sm = StateMachine(
|
||||
i, uart_tx, freq=8 * UART_BAUD, sideset_base=Pin(PIN_BASE + i), out_base=Pin(PIN_BASE + i)
|
||||
)
|
||||
sm.active(1)
|
||||
uarts.append(sm)
|
||||
|
||||
# We can print characters from each UART by pushing them to the TX FIFO
|
||||
def pio_uart_print(sm, s):
|
||||
for c in s:
|
||||
sm.put(ord(c))
|
||||
|
||||
|
||||
# Print a different message from each UART
|
||||
for i, u in enumerate(uarts):
|
||||
pio_uart_print(u, "Hello from UART {}!\n".format(i))
|
|
@ -0,0 +1,52 @@
|
|||
# Example using PIO to drive a set of WS2812 LEDs.
|
||||
|
||||
import array, time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
# Configure the number of WS2812 LEDs.
|
||||
NUM_LEDS = 8
|
||||
|
||||
|
||||
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
|
||||
def ws2812():
|
||||
T1 = 2
|
||||
T2 = 5
|
||||
T3 = 3
|
||||
wrap_target()
|
||||
label("bitloop")
|
||||
out(x, 1) .side(0) [T3 - 1]
|
||||
jmp(not_x, "do_zero") .side(1) [T1 - 1]
|
||||
jmp("bitloop") .side(1) [T2 - 1]
|
||||
label("do_zero")
|
||||
nop() .side(0) [T2 - 1]
|
||||
wrap()
|
||||
|
||||
|
||||
# Create the StateMachine with the ws2812 program, outputting on Pin(22).
|
||||
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(22))
|
||||
|
||||
# Start the StateMachine, it will wait for data on its FIFO.
|
||||
sm.active(1)
|
||||
|
||||
# Display a pattern on the LEDs via an array of LED RGB values.
|
||||
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
|
||||
|
||||
# Cycle colours.
|
||||
for i in range(4 * NUM_LEDS):
|
||||
for j in range(NUM_LEDS):
|
||||
r = j * 100 // (NUM_LEDS - 1)
|
||||
b = 100 - j * 100 // (NUM_LEDS - 1)
|
||||
if j != i % NUM_LEDS:
|
||||
r >>= 3
|
||||
b >>= 3
|
||||
ar[j] = r << 16 | b
|
||||
sm.put(ar, 8)
|
||||
time.sleep_ms(50)
|
||||
|
||||
# Fade out.
|
||||
for i in range(24):
|
||||
for j in range(NUM_LEDS):
|
||||
ar[j] >>= 1
|
||||
sm.put(ar, 8)
|
||||
time.sleep_ms(50)
|
|
@ -0,0 +1,25 @@
|
|||
# Example using PWM to fade an LED.
|
||||
|
||||
import time
|
||||
from machine import Pin, PWM
|
||||
|
||||
|
||||
# Construct PWM object, with LED on Pin(25).
|
||||
pwm = PWM(Pin(25))
|
||||
|
||||
# Set the PWM frequency.
|
||||
pwm.freq(1000)
|
||||
|
||||
# Fade the LED in and out a few times.
|
||||
duty = 0
|
||||
direction = 1
|
||||
for _ in range(8 * 256):
|
||||
duty += direction
|
||||
if duty > 255:
|
||||
duty = 255
|
||||
direction = -1
|
||||
elif duty < 0:
|
||||
duty = 0
|
||||
direction = 1
|
||||
pwm.duty_u16(duty * duty)
|
||||
time.sleep(0.001)
|
|
@ -0,0 +1,11 @@
|
|||
from machine import SPI
|
||||
|
||||
spi = SPI(0)
|
||||
spi = SPI(0, 100_000)
|
||||
spi = SPI(0, 100_000, polarity=1, phase=1)
|
||||
|
||||
spi.write('test')
|
||||
spi.read(5)
|
||||
|
||||
buf = bytearray(3)
|
||||
spi.write_readinto('out', buf)
|
Ładowanie…
Reference in New Issue