├── .gitignore ├── LICENSE.txt ├── README.md ├── adc └── temperature.py ├── blink └── blink.py ├── bluetooth ├── ble_advertising.py ├── picow_ble_temp_reader.py └── picow_ble_temp_sensor.py ├── i2c ├── 1106oled │ ├── README.adoc │ ├── i2c_1106oled_using_defaults.py │ ├── i2c_1106oled_with_freq.py │ ├── pico-and-oled.fzz │ ├── pico-and-oled.png │ └── sh1106.py ├── 1306oled │ ├── README.adoc │ ├── i2c_1306oled_using_defaults.py │ ├── i2c_1306oled_with_freq.py │ ├── pico-and-oled.fzz │ └── pico-and-oled.png ├── i2c.py └── i2c_without_freq.py ├── irq └── irq.py ├── multicore └── multicore.py ├── pio ├── neopixel_ring │ ├── README.adoc │ ├── neopixel_ring.fzz │ ├── neopixel_ring.png │ └── neopixel_ring.py ├── pio_1hz.py ├── pio_blink.py ├── pio_exec.py ├── pio_irq.py ├── pio_pinchange.py ├── pio_pwm.py ├── pio_spi.py ├── pio_uart_tx.py └── pio_ws2812.py ├── pwm └── pwm_fade.py ├── spi └── spi.py ├── uart └── loopback │ ├── README.adoc │ ├── pico_uart_example.png │ └── uart.py └── wireless └── webserver.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 4 | following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 7 | disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided with the distribution. 11 | 12 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroPython Examples 2 | 3 | Examples to accompany the "[Raspberry Pi Pico Python SDK](https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-python-sdk.pdf)" book published by Raspberry Pi Ltd, which forms part of the [technical documentation](https://www.raspberrypi.com/documentation/microcontrollers/) in support of Raspberry Pi Pico and the MicroPython port to RP2040. 4 | 5 | **Note:** There are also additional examples for the RP2040 port of MicroPython [here](https://github.com/micropython/micropython/tree/master/examples/rp2) in the upstream [MicroPython repo](https://github.com/micropython/micropython). 6 | 7 | ## Contributions 8 | 9 | While we welcome pull requests to contribute further example code, please do not link to personal sites or to your social media. Contributions which are fully documented with an AsciiDoc description and a Fritzing wiring diagram, e.g. see the [NeoPixel Ring](https://github.com/raspberrypi/pico-micropython-examples/tree/master/pio/neopixel_ring) example, stand more chance of inclusion. 10 | 11 | Our example code is under the BSD-3-Clause License: any contributions must be under the same license. 12 | -------------------------------------------------------------------------------- /adc/temperature.py: -------------------------------------------------------------------------------- 1 | import machine 2 | import utime 3 | 4 | sensor_temp = machine.ADC(4) 5 | conversion_factor = 3.3 / (65535) 6 | 7 | while True: 8 | reading = sensor_temp.read_u16() * conversion_factor 9 | 10 | # The temperature sensor measures the Vbe voltage of a biased bipolar diode, connected to the fifth ADC channel 11 | # Typically, Vbe = 0.706V at 27 degrees C, with a slope of -1.721mV (0.001721) per degree. 12 | temperature = 27 - (reading - 0.706)/0.001721 13 | print(temperature) 14 | utime.sleep(2) 15 | -------------------------------------------------------------------------------- /blink/blink.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, Timer 2 | 3 | led = Pin("LED", Pin.OUT) 4 | tim = Timer() 5 | def tick(timer): 6 | global led 7 | led.toggle() 8 | 9 | tim.init(freq=2.5, mode=Timer.PERIODIC, callback=tick) 10 | -------------------------------------------------------------------------------- /bluetooth/ble_advertising.py: -------------------------------------------------------------------------------- 1 | # Helpers for generating BLE advertising payloads. 2 | 3 | from micropython import const 4 | import struct 5 | import bluetooth 6 | 7 | # Advertising payloads are repeated packets of the following form: 8 | # 1 byte data length (N + 1) 9 | # 1 byte type (see constants below) 10 | # N bytes type-specific data 11 | 12 | _ADV_TYPE_FLAGS = const(0x01) 13 | _ADV_TYPE_NAME = const(0x09) 14 | _ADV_TYPE_UUID16_COMPLETE = const(0x3) 15 | _ADV_TYPE_UUID32_COMPLETE = const(0x5) 16 | _ADV_TYPE_UUID128_COMPLETE = const(0x7) 17 | _ADV_TYPE_UUID16_MORE = const(0x2) 18 | _ADV_TYPE_UUID32_MORE = const(0x4) 19 | _ADV_TYPE_UUID128_MORE = const(0x6) 20 | _ADV_TYPE_APPEARANCE = const(0x19) 21 | 22 | 23 | # Generate a payload to be passed to gap_advertise(adv_data=...). 24 | def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): 25 | payload = bytearray() 26 | 27 | def _append(adv_type, value): 28 | nonlocal payload 29 | payload += struct.pack("BB", len(value) + 1, adv_type) + value 30 | 31 | _append( 32 | _ADV_TYPE_FLAGS, 33 | struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)), 34 | ) 35 | 36 | if name: 37 | _append(_ADV_TYPE_NAME, name) 38 | 39 | if services: 40 | for uuid in services: 41 | b = bytes(uuid) 42 | if len(b) == 2: 43 | _append(_ADV_TYPE_UUID16_COMPLETE, b) 44 | elif len(b) == 4: 45 | _append(_ADV_TYPE_UUID32_COMPLETE, b) 46 | elif len(b) == 16: 47 | _append(_ADV_TYPE_UUID128_COMPLETE, b) 48 | 49 | # See org.bluetooth.characteristic.gap.appearance.xml 50 | if appearance: 51 | _append(_ADV_TYPE_APPEARANCE, struct.pack(" 0): 224 | for i in range(flash_count): 225 | self._led.on() 226 | time.sleep_ms(100) 227 | self._led.off() 228 | time.sleep_ms(100) 229 | delay_ms -= 200 230 | time.sleep_ms(1000) 231 | delay_ms -= 1000 232 | 233 | def print_temp(result): 234 | print("read temp: %.2f degc" % result) 235 | 236 | def demo(ble, central): 237 | not_found = False 238 | 239 | def on_scan(addr_type, addr, name): 240 | if addr_type is not None: 241 | print("Found sensor: %s" % name) 242 | central.connect() 243 | else: 244 | nonlocal not_found 245 | not_found = True 246 | print("No sensor found.") 247 | 248 | central.scan(callback=on_scan) 249 | 250 | # Wait for connection... 251 | while not central.is_connected(): 252 | time.sleep_ms(100) 253 | if not_found: 254 | return 255 | 256 | print("Connected") 257 | 258 | # Explicitly issue reads 259 | while central.is_connected(): 260 | central.read(callback=print_temp) 261 | sleep_ms_flash_led(central, 2, 2000) 262 | 263 | print("Disconnected") 264 | 265 | if __name__ == "__main__": 266 | ble = bluetooth.BLE() 267 | central = BLETemperatureCentral(ble) 268 | while(True): 269 | demo(ble, central) 270 | sleep_ms_flash_led(central, 1, 10000) 271 | -------------------------------------------------------------------------------- /bluetooth/picow_ble_temp_sensor.py: -------------------------------------------------------------------------------- 1 | # This example demonstrates a simple temperature sensor peripheral. 2 | # 3 | # The sensor's local value is updated, and it will notify 4 | # any connected central every 10 seconds. 5 | 6 | import bluetooth 7 | import random 8 | import struct 9 | import time 10 | import machine 11 | import ubinascii 12 | from ble_advertising import advertising_payload 13 | from micropython import const 14 | from machine import Pin 15 | 16 | _IRQ_CENTRAL_CONNECT = const(1) 17 | _IRQ_CENTRAL_DISCONNECT = const(2) 18 | _IRQ_GATTS_INDICATE_DONE = const(20) 19 | 20 | _FLAG_READ = const(0x0002) 21 | _FLAG_NOTIFY = const(0x0010) 22 | _FLAG_INDICATE = const(0x0020) 23 | 24 | # org.bluetooth.service.environmental_sensing 25 | _ENV_SENSE_UUID = bluetooth.UUID(0x181A) 26 | # org.bluetooth.characteristic.temperature 27 | _TEMP_CHAR = ( 28 | bluetooth.UUID(0x2A6E), 29 | _FLAG_READ | _FLAG_NOTIFY | _FLAG_INDICATE, 30 | ) 31 | _ENV_SENSE_SERVICE = ( 32 | _ENV_SENSE_UUID, 33 | (_TEMP_CHAR,), 34 | ) 35 | 36 | # org.bluetooth.characteristic.gap.appearance.xml 37 | _ADV_APPEARANCE_GENERIC_THERMOMETER = const(768) 38 | 39 | class BLETemperature: 40 | def __init__(self, ble, name=""): 41 | self._sensor_temp = machine.ADC(4) 42 | self._ble = ble 43 | self._ble.active(True) 44 | self._ble.irq(self._irq) 45 | ((self._handle,),) = self._ble.gatts_register_services((_ENV_SENSE_SERVICE,)) 46 | self._connections = set() 47 | if len(name) == 0: 48 | name = 'Pico %s' % ubinascii.hexlify(self._ble.config('mac')[1],':').decode().upper() 49 | print('Sensor name %s' % name) 50 | self._payload = advertising_payload( 51 | name=name, services=[_ENV_SENSE_UUID] 52 | ) 53 | self._advertise() 54 | 55 | def _irq(self, event, data): 56 | # Track connections so we can send notifications. 57 | if event == _IRQ_CENTRAL_CONNECT: 58 | conn_handle, _, _ = data 59 | self._connections.add(conn_handle) 60 | elif event == _IRQ_CENTRAL_DISCONNECT: 61 | conn_handle, _, _ = data 62 | self._connections.remove(conn_handle) 63 | # Start advertising again to allow a new connection. 64 | self._advertise() 65 | elif event == _IRQ_GATTS_INDICATE_DONE: 66 | conn_handle, value_handle, status = data 67 | 68 | def update_temperature(self, notify=False, indicate=False): 69 | # Write the local value, ready for a central to read. 70 | temp_deg_c = self._get_temp() 71 | print("write temp %.2f degc" % temp_deg_c); 72 | self._ble.gatts_write(self._handle, struct.pack("> for wiring instructions. 11 | 12 | [[oled-wiring-diagram]] 13 | [pdfwidth=75%] 14 | .Wiring the OLED to Pico using I2C 15 | image::pico-and-oled.png[] 16 | 17 | == List of Files 18 | 19 | A list of files with descriptions of their function; 20 | 21 | i2c_1106oled_using_defaults.py:: The example code. 22 | i2c_1106oled_with_freq.py:: The example code, explicitly sets a frequency. 23 | sh1106.py:: SH1106 Driver Obtained from https://github.com/robert-hh/SH1106 24 | 25 | == Bill of Materials 26 | 27 | .A list of materials required for the example 28 | [[oled-bom-table]] 29 | [cols=3] 30 | |=== 31 | | *Item* | *Quantity* | Details 32 | | Breadboard | 1 | generic part 33 | | Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ 34 | | Monochrome 128x128 I2C OLED Display | 1 | https://shop.pimoroni.com/products/1-12-oled-breakout?variant=29421050757203 35 | |=== 36 | -------------------------------------------------------------------------------- /i2c/1106oled/i2c_1106oled_using_defaults.py: -------------------------------------------------------------------------------- 1 | # Display Image & text on I2C driven SH1106 OLED display 2 | from machine import I2C, ADC 3 | from sh1106 import SH1106_I2C 4 | import framebuf 5 | 6 | WIDTH = 128 # oled display width 7 | HEIGHT = 128 # oled display height 8 | 9 | i2c = I2C(0) # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8), freq=400000 10 | print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address 11 | print("I2C Configuration: "+str(i2c)) # Display I2C config 12 | 13 | 14 | oled = SH1106_I2C(WIDTH, HEIGHT, i2c) # Init oled display 15 | 16 | # Raspberry Pi logo as 32x32 bytearray 17 | 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") 18 | 19 | # Load the raspberry pi logo into the framebuffer (the image is 32x32) 20 | fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB) 21 | 22 | # Clear the oled display in case it has junk on it. 23 | oled.fill(0) 24 | 25 | # Blit the image from the framebuffer to the oled display 26 | oled.blit(fb, 96, 0) 27 | 28 | # Add some text 29 | oled.text("Raspberry Pi",5,5) 30 | oled.text("Pico",5,15) 31 | 32 | # Finally update the oled display so the image & text is displayed 33 | oled.show() 34 | -------------------------------------------------------------------------------- /i2c/1106oled/i2c_1106oled_with_freq.py: -------------------------------------------------------------------------------- 1 | # Display Image & text on I2C driven ssd1306 OLED display 2 | from machine import Pin, I2C 3 | from sh1106 import SH1106_I2C 4 | import framebuf 5 | 6 | WIDTH = 128 # oled display width 7 | HEIGHT = 32 # oled display height 8 | 9 | i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000) # Init I2C using pins GP8 & GP9 (default I2C0 pins) 10 | print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address 11 | print("I2C Configuration: "+str(i2c)) # Display I2C config 12 | 13 | 14 | oled = SH1106_I2C(WIDTH, HEIGHT, i2c) # Init oled display 15 | 16 | # Raspberry Pi logo as 32x32 bytearray 17 | 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") 18 | 19 | # Load the raspberry pi logo into the framebuffer (the image is 32x32) 20 | fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB) 21 | 22 | # Clear the oled display in case it has junk on it. 23 | oled.fill(0) 24 | 25 | # Blit the image from the framebuffer to the oled display 26 | oled.blit(fb, 96, 0) 27 | 28 | # Add some text 29 | oled.text("Raspberry Pi",5,5) 30 | oled.text("Pico",5,15) 31 | 32 | # Finally update the oled display so the image & text is displayed 33 | oled.show() 34 | -------------------------------------------------------------------------------- /i2c/1106oled/pico-and-oled.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/i2c/1106oled/pico-and-oled.fzz -------------------------------------------------------------------------------- /i2c/1106oled/pico-and-oled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/i2c/1106oled/pico-and-oled.png -------------------------------------------------------------------------------- /i2c/1106oled/sh1106.py: -------------------------------------------------------------------------------- 1 | # 2 | # MicroPython SH1106 OLED driver, I2C and SPI interfaces 3 | # 4 | # The MIT License (MIT) 5 | # 6 | # Copyright (c) 2016 Radomir Dopieralski (@deshipu), 7 | # 2017 Robert Hammelrath (@robert-hh) 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy 10 | # of this software and associated documentation files (the "Software"), to deal 11 | # in the Software without restriction, including without limitation the rights 12 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | # copies of the Software, and to permit persons to whom the Software is 14 | # furnished to do so, subject to the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in 17 | # all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | # THE SOFTWARE. 26 | # 27 | # Sample code sections 28 | # ------------ SPI ------------------ 29 | # Pin Map SPI 30 | # - 3V3 - Vcc 31 | # - GND - Gnd 32 | # - GPIO 11 - DIN / MOSI fixed 33 | # - GPIO 10 - CLK / Sck fixed 34 | # - GPIO 4 - CS (optional, if the only connected device, connect to GND) 35 | # - GPIO 5 - D/C 36 | # - GPIO 2 - Res 37 | # 38 | # for CS, D/C and Res other ports may be chosen. 39 | # 40 | # from machine import Pin, SPI 41 | # import sh1106 42 | 43 | # spi = SPI(1, baudrate=1000000) 44 | # display = sh1106.SH1106_SPI(128, 64, spi, Pin(5), Pin(2), Pin(4)) 45 | # display.sleep(False) 46 | # display.fill(0) 47 | # display.text('Testing 1', 0, 0, 1) 48 | # display.show() 49 | # 50 | # --------------- I2C ------------------ 51 | # 52 | # Pin Map I2C 53 | # - 3V3 - Vcc 54 | # - GND - Gnd 55 | # - GPIO 5 - CLK / SCL 56 | # - GPIO 4 - DIN / SDA 57 | # - GPIO 2 - Res 58 | # - GND - CS 59 | # - GND - D/C 60 | # 61 | # 62 | # from machine import Pin, I2C 63 | # import sh1106 64 | # 65 | # i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000) 66 | # display = sh1106.SH1106_I2C(128, 64, i2c, Pin(2), 0x3c) 67 | # display.sleep(False) 68 | # display.fill(0) 69 | # display.text('Testing 1', 0, 0, 1) 70 | # display.show() 71 | 72 | from micropython import const 73 | import utime as time 74 | import framebuf 75 | 76 | 77 | # a few register definitions 78 | _SET_CONTRAST = const(0x81) 79 | _SET_NORM_INV = const(0xa6) 80 | _SET_DISP = const(0xae) 81 | _SET_SCAN_DIR = const(0xc0) 82 | _SET_SEG_REMAP = const(0xa0) 83 | _LOW_COLUMN_ADDRESS = const(0x00) 84 | _HIGH_COLUMN_ADDRESS = const(0x10) 85 | _SET_PAGE_ADDRESS = const(0xB0) 86 | 87 | 88 | class SH1106: 89 | def __init__(self, width, height, external_vcc): 90 | self.width = width 91 | self.height = height 92 | self.external_vcc = external_vcc 93 | self.pages = self.height // 8 94 | self.buffer = bytearray(self.pages * self.width) 95 | fb = framebuf.FrameBuffer(self.buffer, self.width, self.height, 96 | framebuf.MVLSB) 97 | self.framebuf = fb 98 | # set shortcuts for the methods of framebuf 99 | self.fill = fb.fill 100 | self.fill_rect = fb.fill_rect 101 | self.hline = fb.hline 102 | self.vline = fb.vline 103 | self.line = fb.line 104 | self.rect = fb.rect 105 | self.pixel = fb.pixel 106 | self.scroll = fb.scroll 107 | self.text = fb.text 108 | self.blit = fb.blit 109 | 110 | self.init_display() 111 | 112 | def init_display(self): 113 | self.reset() 114 | self.fill(0) 115 | self.poweron() 116 | self.show() 117 | 118 | def poweroff(self): 119 | self.write_cmd(_SET_DISP | 0x00) 120 | 121 | def poweron(self): 122 | self.write_cmd(_SET_DISP | 0x01) 123 | 124 | def rotate(self, flag, update=True): 125 | if flag: 126 | self.write_cmd(_SET_SEG_REMAP | 0x01) # mirror display vertically 127 | self.write_cmd(_SET_SCAN_DIR | 0x08) # mirror display hor. 128 | else: 129 | self.write_cmd(_SET_SEG_REMAP | 0x00) 130 | self.write_cmd(_SET_SCAN_DIR | 0x00) 131 | if update: 132 | self.show() 133 | 134 | def sleep(self, value): 135 | self.write_cmd(_SET_DISP | (not value)) 136 | 137 | def contrast(self, contrast): 138 | self.write_cmd(_SET_CONTRAST) 139 | self.write_cmd(contrast) 140 | 141 | def invert(self, invert): 142 | self.write_cmd(_SET_NORM_INV | (invert & 1)) 143 | 144 | def show(self): 145 | for page in range(self.height // 8): 146 | self.write_cmd(_SET_PAGE_ADDRESS | page) 147 | self.write_cmd(_LOW_COLUMN_ADDRESS | 2) 148 | self.write_cmd(_HIGH_COLUMN_ADDRESS | 0) 149 | self.write_data(self.buffer[ 150 | self.width * page:self.width * page + self.width 151 | ]) 152 | 153 | def reset(self, res): 154 | if res is not None: 155 | res(1) 156 | time.sleep_ms(1) 157 | res(0) 158 | time.sleep_ms(20) 159 | res(1) 160 | time.sleep_ms(20) 161 | 162 | 163 | class SH1106_I2C(SH1106): 164 | def __init__(self, width, height, i2c, res=None, addr=0x3c, 165 | external_vcc=False): 166 | self.i2c = i2c 167 | self.addr = addr 168 | self.res = res 169 | self.temp = bytearray(2) 170 | if res is not None: 171 | res.init(res.OUT, value=1) 172 | super().__init__(width, height, external_vcc) 173 | 174 | def write_cmd(self, cmd): 175 | self.temp[0] = 0x80 # Co=1, D/C#=0 176 | self.temp[1] = cmd 177 | self.i2c.writeto(self.addr, self.temp) 178 | 179 | def write_data(self, buf): 180 | self.i2c.writeto(self.addr, b'\x40'+buf) 181 | 182 | def reset(self): 183 | super().reset(self.res) 184 | 185 | 186 | class SH1106_SPI(SH1106): 187 | def __init__(self, width, height, spi, dc, res=None, cs=None, 188 | external_vcc=False): 189 | self.rate = 10 * 1000 * 1000 190 | dc.init(dc.OUT, value=0) 191 | if res is not None: 192 | res.init(res.OUT, value=0) 193 | if cs is not None: 194 | cs.init(cs.OUT, value=1) 195 | self.spi = spi 196 | self.dc = dc 197 | self.res = res 198 | self.cs = cs 199 | super().__init__(width, height, external_vcc) 200 | 201 | def write_cmd(self, cmd): 202 | self.spi.init(baudrate=self.rate, polarity=0, phase=0) 203 | if self.cs is not None: 204 | self.cs(1) 205 | self.dc(0) 206 | self.cs(0) 207 | self.spi.write(bytearray([cmd])) 208 | self.cs(1) 209 | else: 210 | self.dc(0) 211 | self.spi.write(bytearray([cmd])) 212 | 213 | def write_data(self, buf): 214 | self.spi.init(baudrate=self.rate, polarity=0, phase=0) 215 | if self.cs is not None: 216 | self.cs(1) 217 | self.dc(1) 218 | self.cs(0) 219 | self.spi.write(buf) 220 | self.cs(1) 221 | else: 222 | self.dc(1) 223 | self.spi.write(buf) 224 | 225 | def reset(self): 226 | super().reset(self.res) -------------------------------------------------------------------------------- /i2c/1306oled/README.adoc: -------------------------------------------------------------------------------- 1 | = Using a SSD1306-based OLED graphics display 2 | :xrefstyle: short 3 | 4 | Display an image and text on I2C driven SSD1306-based OLED graphics display. 5 | 6 | == Wiring information 7 | 8 | See <> for wiring instructions. 9 | 10 | [[oled-wiring-diagram]] 11 | [pdfwidth=75%] 12 | .Wiring the OLED to Pico using I2C 13 | image::pico-and-oled.png[] 14 | 15 | == List of Files 16 | 17 | A list of files with descriptions of their function; 18 | 19 | i2c_1306oled_using_defaults.py:: The example code. 20 | i2c_1306oled_with_freq.py:: The example code, explicitly sets a frequency. 21 | 22 | == Bill of Materials 23 | 24 | .A list of materials required for the example 25 | [[oled-bom-table]] 26 | [cols=3] 27 | |=== 28 | | *Item* | *Quantity* | Details 29 | | Breadboard | 1 | generic part 30 | | Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ 31 | | Monochrome 128x32 I2C OLED Display | 1 | https://www.adafruit.com/product/931 32 | |=== 33 | -------------------------------------------------------------------------------- /i2c/1306oled/i2c_1306oled_using_defaults.py: -------------------------------------------------------------------------------- 1 | # Display Image & text on I2C driven ssd1306 OLED display 2 | from machine import Pin, I2C 3 | from ssd1306 import SSD1306_I2C 4 | import framebuf 5 | 6 | WIDTH = 128 # oled display width 7 | HEIGHT = 32 # oled display height 8 | 9 | i2c = I2C(0) # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8), freq=400000 10 | print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address 11 | print("I2C Configuration: "+str(i2c)) # Display I2C config 12 | 13 | 14 | oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Init oled display 15 | 16 | # Raspberry Pi logo as 32x32 bytearray 17 | 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") 18 | 19 | # Load the raspberry pi logo into the framebuffer (the image is 32x32) 20 | fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB) 21 | 22 | # Clear the oled display in case it has junk on it. 23 | oled.fill(0) 24 | 25 | # Blit the image from the framebuffer to the oled display 26 | oled.blit(fb, 96, 0) 27 | 28 | # Add some text 29 | oled.text("Raspberry Pi",5,5) 30 | oled.text("Pico",5,15) 31 | 32 | # Finally update the oled display so the image & text is displayed 33 | oled.show() 34 | -------------------------------------------------------------------------------- /i2c/1306oled/i2c_1306oled_with_freq.py: -------------------------------------------------------------------------------- 1 | # Display Image & text on I2C driven ssd1306 OLED display 2 | from machine import Pin, I2C 3 | from ssd1306 import SSD1306_I2C 4 | import framebuf 5 | 6 | WIDTH = 128 # oled display width 7 | HEIGHT = 32 # oled display height 8 | 9 | i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000) # Init I2C using pins GP8 & GP9 (default I2C0 pins) 10 | print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address 11 | print("I2C Configuration: "+str(i2c)) # Display I2C config 12 | 13 | 14 | oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Init oled display 15 | 16 | # Raspberry Pi logo as 32x32 bytearray 17 | 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") 18 | 19 | # Load the raspberry pi logo into the framebuffer (the image is 32x32) 20 | fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB) 21 | 22 | # Clear the oled display in case it has junk on it. 23 | oled.fill(0) 24 | 25 | # Blit the image from the framebuffer to the oled display 26 | oled.blit(fb, 96, 0) 27 | 28 | # Add some text 29 | oled.text("Raspberry Pi",5,5) 30 | oled.text("Pico",5,15) 31 | 32 | # Finally update the oled display so the image & text is displayed 33 | oled.show() 34 | -------------------------------------------------------------------------------- /i2c/1306oled/pico-and-oled.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/i2c/1306oled/pico-and-oled.fzz -------------------------------------------------------------------------------- /i2c/1306oled/pico-and-oled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/i2c/1306oled/pico-and-oled.png -------------------------------------------------------------------------------- /i2c/i2c.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, I2C 2 | 3 | i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=100000) 4 | i2c.scan() 5 | i2c.writeto(76, b'123') 6 | i2c.readfrom(76, 4) 7 | 8 | i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq=100000) 9 | i2c.scan() 10 | i2c.writeto_mem(76, 6, b'456') 11 | i2c.readfrom_mem(76, 6, 4) 12 | -------------------------------------------------------------------------------- /i2c/i2c_without_freq.py: -------------------------------------------------------------------------------- 1 | from machine import I2C 2 | 3 | i2c = I2C(0) # defaults to SCL=Pin(9), SDA=Pin(8), freq=400000 4 | -------------------------------------------------------------------------------- /irq/irq.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | 3 | p2 = Pin(2, Pin.IN, Pin.PULL_UP) 4 | p2.irq(lambda pin: print("IRQ with flags:", pin.irq().flags()), Pin.IRQ_FALLING) 5 | -------------------------------------------------------------------------------- /multicore/multicore.py: -------------------------------------------------------------------------------- 1 | import time, _thread, machine 2 | 3 | def task(n, delay): 4 | led = machine.Pin("LED", machine.Pin.OUT) 5 | for i in range(n): 6 | led.high() 7 | time.sleep(delay) 8 | led.low() 9 | time.sleep(delay) 10 | print('done') 11 | 12 | _thread.start_new_thread(task, (10, 0.5)) 13 | -------------------------------------------------------------------------------- /pio/neopixel_ring/README.adoc: -------------------------------------------------------------------------------- 1 | = Using PIO to drive a set of NeoPixel Ring (WS2812 LEDs) 2 | :xrefstyle: short 3 | 4 | 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. 5 | 6 | == Wiring information 7 | 8 | See <> for wiring instructions. 9 | 10 | [[neopixel-wiring-diagram]] 11 | [pdfwidth=75%] 12 | .Wiring the 16-LED NeoPixel Ring to Pico 13 | image::neopixel_ring.png[] 14 | 15 | == List of Files 16 | 17 | A list of files with descriptions of their function; 18 | 19 | neopixel_ring.py:: The example code. 20 | 21 | == Bill of Materials 22 | 23 | .A list of materials required for the example 24 | [[ring-bom-table]] 25 | [cols=3] 26 | |=== 27 | | *Item* | *Quantity* | Details 28 | | Breadboard | 1 | generic part 29 | | Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ 30 | | NeoPixel Ring | 1 | https://www.adafruit.com/product/1463 31 | |=== 32 | -------------------------------------------------------------------------------- /pio/neopixel_ring/neopixel_ring.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/pio/neopixel_ring/neopixel_ring.fzz -------------------------------------------------------------------------------- /pio/neopixel_ring/neopixel_ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/pio/neopixel_ring/neopixel_ring.png -------------------------------------------------------------------------------- /pio/neopixel_ring/neopixel_ring.py: -------------------------------------------------------------------------------- 1 | # Example using PIO to drive a set of WS2812 LEDs. 2 | 3 | import array, time 4 | from machine import Pin 5 | import rp2 6 | 7 | # Configure the number of WS2812 LEDs. 8 | NUM_LEDS = 16 9 | PIN_NUM = 6 10 | brightness = 0.2 11 | 12 | @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) 13 | def ws2812(): 14 | T1 = 2 15 | T2 = 5 16 | T3 = 3 17 | wrap_target() 18 | label("bitloop") 19 | out(x, 1) .side(0) [T3 - 1] 20 | jmp(not_x, "do_zero") .side(1) [T1 - 1] 21 | jmp("bitloop") .side(1) [T2 - 1] 22 | label("do_zero") 23 | nop() .side(0) [T2 - 1] 24 | wrap() 25 | 26 | 27 | # Create the StateMachine with the ws2812 program, outputting on pin 28 | sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM)) 29 | 30 | # Start the StateMachine, it will wait for data on its FIFO. 31 | sm.active(1) 32 | 33 | # Display a pattern on the LEDs via an array of LED RGB values. 34 | ar = array.array("I", [0 for _ in range(NUM_LEDS)]) 35 | 36 | ########################################################################## 37 | def pixels_show(): 38 | dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)]) 39 | for i,c in enumerate(ar): 40 | r = int(((c >> 8) & 0xFF) * brightness) 41 | g = int(((c >> 16) & 0xFF) * brightness) 42 | b = int((c & 0xFF) * brightness) 43 | dimmer_ar[i] = (g<<16) + (r<<8) + b 44 | sm.put(dimmer_ar, 8) 45 | time.sleep_ms(10) 46 | 47 | def pixels_set(i, color): 48 | ar[i] = (color[1]<<16) + (color[0]<<8) + color[2] 49 | 50 | def pixels_fill(color): 51 | for i in range(len(ar)): 52 | pixels_set(i, color) 53 | 54 | def color_chase(color, wait): 55 | for i in range(NUM_LEDS): 56 | pixels_set(i, color) 57 | time.sleep(wait) 58 | pixels_show() 59 | time.sleep(0.2) 60 | 61 | def wheel(pos): 62 | # Input a value 0 to 255 to get a color value. 63 | # The colours are a transition r - g - b - back to r. 64 | if pos < 0 or pos > 255: 65 | return (0, 0, 0) 66 | if pos < 85: 67 | return (255 - pos * 3, pos * 3, 0) 68 | if pos < 170: 69 | pos -= 85 70 | return (0, 255 - pos * 3, pos * 3) 71 | pos -= 170 72 | return (pos * 3, 0, 255 - pos * 3) 73 | 74 | def rainbow_cycle(wait): 75 | for j in range(255): 76 | for i in range(NUM_LEDS): 77 | rc_index = (i * 256 // NUM_LEDS) + j 78 | pixels_set(i, wheel(rc_index & 255)) 79 | pixels_show() 80 | time.sleep(wait) 81 | 82 | BLACK = (0, 0, 0) 83 | RED = (255, 0, 0) 84 | YELLOW = (255, 150, 0) 85 | GREEN = (0, 255, 0) 86 | CYAN = (0, 255, 255) 87 | BLUE = (0, 0, 255) 88 | PURPLE = (180, 0, 255) 89 | WHITE = (255, 255, 255) 90 | COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE) 91 | 92 | print("fills") 93 | for color in COLORS: 94 | pixels_fill(color) 95 | pixels_show() 96 | time.sleep(0.2) 97 | 98 | print("chases") 99 | for color in COLORS: 100 | color_chase(color, 0.01) 101 | 102 | print("rainbow") 103 | rainbow_cycle(0) 104 | -------------------------------------------------------------------------------- /pio/pio_1hz.py: -------------------------------------------------------------------------------- 1 | # Example using PIO to blink an LED and raise an IRQ at 1Hz. 2 | 3 | import time 4 | from machine import Pin 5 | import rp2 6 | 7 | 8 | @rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) 9 | def blink_1hz(): 10 | # Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000 11 | irq(rel(0)) 12 | set(pins, 1) 13 | set(x, 31) [5] 14 | label("delay_high") 15 | nop() [29] 16 | jmp(x_dec, "delay_high") 17 | 18 | # Cycles: 1 + 7 + 32 * (30 + 1) = 1000 19 | set(pins, 0) 20 | set(x, 31) [6] 21 | label("delay_low") 22 | nop() [29] 23 | jmp(x_dec, "delay_low") 24 | 25 | 26 | # Create the StateMachine with the blink_1hz program, outputting on Pin(25). 27 | sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25)) 28 | 29 | # Set the IRQ handler to print the millisecond timestamp. 30 | sm.irq(lambda p: print(time.ticks_ms())) 31 | 32 | # Start the StateMachine. 33 | sm.active(1) 34 | -------------------------------------------------------------------------------- /pio/pio_blink.py: -------------------------------------------------------------------------------- 1 | import time 2 | import rp2 3 | from machine import Pin 4 | 5 | # Define the blink program. It has one GPIO to bind to on the set instruction, which is an output pin. 6 | # Use lots of delays to make the blinking visible by eye. 7 | @rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) 8 | def blink(): 9 | wrap_target() 10 | set(pins, 1) [31] 11 | nop() [31] 12 | nop() [31] 13 | nop() [31] 14 | nop() [31] 15 | set(pins, 0) [31] 16 | nop() [31] 17 | nop() [31] 18 | nop() [31] 19 | nop() [31] 20 | wrap() 21 | 22 | # Instantiate a state machine with the blink program, at 2000Hz, with set bound to Pin(25) (LED on the Pico board) 23 | sm = rp2.StateMachine(0, blink, freq=2000, set_base=Pin(25)) 24 | 25 | # Run the state machine for 3 seconds. The LED should blink. 26 | sm.active(1) 27 | time.sleep(3) 28 | sm.active(0) 29 | -------------------------------------------------------------------------------- /pio/pio_exec.py: -------------------------------------------------------------------------------- 1 | # Example using PIO to turn on an LED via an explicit exec. 2 | # 3 | # Demonstrates: 4 | # - using set_init and set_base 5 | # - using StateMachine.exec 6 | 7 | import time 8 | from machine import Pin 9 | import rp2 10 | 11 | # Define an empty program that uses a single set pin. 12 | @rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) 13 | def prog(): 14 | pass 15 | 16 | 17 | # Construct the StateMachine, binding Pin 25 to the set pin. 18 | sm = rp2.StateMachine(0, prog, set_base=Pin(25)) 19 | 20 | # Turn on the set pin via an exec instruction. 21 | sm.exec("set(pins, 1)") 22 | 23 | # Sleep for 500ms. 24 | time.sleep(0.5) 25 | 26 | # Turn off the set pin via an exec instruction. 27 | sm.exec("set(pins, 0)") 28 | -------------------------------------------------------------------------------- /pio/pio_irq.py: -------------------------------------------------------------------------------- 1 | import time 2 | import rp2 3 | 4 | @rp2.asm_pio() 5 | def irq_test(): 6 | wrap_target() 7 | nop() [31] 8 | nop() [31] 9 | nop() [31] 10 | nop() [31] 11 | irq(0) 12 | nop() [31] 13 | nop() [31] 14 | nop() [31] 15 | nop() [31] 16 | irq(1) 17 | wrap() 18 | 19 | 20 | rp2.PIO(0).irq(lambda pio: print(pio.irq().flags())) 21 | 22 | sm = rp2.StateMachine(0, irq_test, freq=2000) 23 | sm.active(1) 24 | time.sleep(1) 25 | sm.active(0) 26 | -------------------------------------------------------------------------------- /pio/pio_pinchange.py: -------------------------------------------------------------------------------- 1 | # Example using PIO to wait for a pin change and raise an IRQ. 2 | # 3 | # Demonstrates: 4 | # - PIO wrapping 5 | # - PIO wait instruction, waiting on an input pin 6 | # - PIO irq instruction, in blocking mode with relative IRQ number 7 | # - setting the in_base pin for a StateMachine 8 | # - setting an irq handler for a StateMachine 9 | # - instantiating 2x StateMachine's with the same program and different pins 10 | 11 | import time 12 | from machine import Pin 13 | import rp2 14 | 15 | 16 | @rp2.asm_pio() 17 | def wait_pin_low(): 18 | wrap_target() 19 | 20 | wait(0, pin, 0) 21 | irq(block, rel(0)) 22 | wait(1, pin, 0) 23 | 24 | wrap() 25 | 26 | 27 | def handler(sm): 28 | # Print a (wrapping) timestamp, and the state machine object. 29 | print(time.ticks_ms(), sm) 30 | 31 | 32 | # Instantiate StateMachine(0) with wait_pin_low program on Pin(16). 33 | pin16 = Pin(16, Pin.IN, Pin.PULL_UP) 34 | sm0 = rp2.StateMachine(0, wait_pin_low, in_base=pin16) 35 | sm0.irq(handler) 36 | 37 | # Instantiate StateMachine(1) with wait_pin_low program on Pin(17). 38 | pin17 = Pin(17, Pin.IN, Pin.PULL_UP) 39 | sm1 = rp2.StateMachine(1, wait_pin_low, in_base=pin17) 40 | sm1.irq(handler) 41 | 42 | # Start the StateMachine's running. 43 | sm0.active(1) 44 | sm1.active(1) 45 | 46 | # Now, when Pin(16) or Pin(17) is pulled low a message will be printed to the REPL. 47 | -------------------------------------------------------------------------------- /pio/pio_pwm.py: -------------------------------------------------------------------------------- 1 | # Example of using PIO for PWM, and fading the brightness of an LED 2 | 3 | from machine import Pin 4 | from rp2 import PIO, StateMachine, asm_pio 5 | from time import sleep 6 | 7 | 8 | @asm_pio(sideset_init=PIO.OUT_LOW) 9 | def pwm_prog(): 10 | pull(noblock) .side(0) 11 | mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock 12 | mov(y, isr) # ISR must be preloaded with PWM count max 13 | label("pwmloop") 14 | jmp(x_not_y, "skip") 15 | nop() .side(1) 16 | label("skip") 17 | jmp(y_dec, "pwmloop") 18 | 19 | 20 | class PIOPWM: 21 | def __init__(self, sm_id, pin, max_count, count_freq): 22 | self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) 23 | # Use exec() to load max count into ISR 24 | self._sm.put(max_count) 25 | self._sm.exec("pull()") 26 | self._sm.exec("mov(isr, osr)") 27 | self._sm.active(1) 28 | self._max_count = max_count 29 | 30 | def set(self, value): 31 | # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse 32 | value = max(value, -1) 33 | value = min(value, self._max_count) 34 | self._sm.put(value) 35 | 36 | 37 | # Pin 25 on Pico boards 38 | pwm = PIOPWM(0, 25, max_count=(1 << 16) - 1, count_freq=10_000_000) 39 | 40 | while True: 41 | for i in range(256): 42 | pwm.set(i ** 2) 43 | sleep(0.01) 44 | -------------------------------------------------------------------------------- /pio/pio_spi.py: -------------------------------------------------------------------------------- 1 | import rp2 2 | from machine import Pin 3 | 4 | @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) 5 | def spi_cpha0(): 6 | # Note X must be preinitialised by setup code before first byte, we reload after sending each byte 7 | # Would normally do this via exec() but in this case it's in the instruction memory and is only run once 8 | set(x, 6) 9 | # Actual program body follows 10 | wrap_target() 11 | pull(ifempty) .side(0x2) [1] 12 | label("bitloop") 13 | out(pins, 1) .side(0x0) [1] 14 | in_(pins, 1) .side(0x1) 15 | jmp(x_dec, "bitloop") .side(0x1) 16 | 17 | out(pins, 1) .side(0x0) 18 | set(x, 6) .side(0x0) # Note this could be replaced with mov x, y for programmable frame size 19 | in_(pins, 1) .side(0x1) 20 | jmp(not_osre, "bitloop") .side(0x1) # Fallthru if TXF empties 21 | 22 | nop() .side(0x0) [1] # CSn back porch 23 | wrap() 24 | 25 | 26 | class PIOSPI: 27 | 28 | def __init__(self, sm_id, pin_mosi, pin_miso, pin_sck, cpha=False, cpol=False, freq=1000000): 29 | assert(not(cpol or cpha)) 30 | 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)) 31 | self._sm.active(1) 32 | 33 | # Note this code will die spectacularly cause we're not draining the RX FIFO 34 | def write_blocking(wdata): 35 | for b in wdata: 36 | self._sm.put(b << 24) 37 | 38 | def read_blocking(n): 39 | data = [] 40 | for i in range(n): 41 | data.append(self._sm.get() & 0xff) 42 | return data 43 | 44 | def write_read_blocking(wdata): 45 | rdata = [] 46 | for b in wdata: 47 | self._sm.put(b << 24) 48 | rdata.append(self._sm.get() & 0xff) 49 | return rdata 50 | -------------------------------------------------------------------------------- /pio/pio_uart_tx.py: -------------------------------------------------------------------------------- 1 | # Example using PIO to create a UART TX interface 2 | 3 | from machine import Pin 4 | from rp2 import PIO, StateMachine, asm_pio 5 | 6 | UART_BAUD = 115200 7 | PIN_BASE = 10 8 | NUM_UARTS = 8 9 | 10 | 11 | @asm_pio(sideset_init=PIO.OUT_HIGH, out_init=PIO.OUT_HIGH, out_shiftdir=PIO.SHIFT_RIGHT) 12 | def uart_tx(): 13 | # Block with TX deasserted until data available 14 | pull() 15 | # Initialise bit counter, assert start bit for 8 cycles 16 | set(x, 7) .side(0) [7] 17 | # Shift out 8 data bits, 8 execution cycles per bit 18 | label("bitloop") 19 | out(pins, 1) [6] 20 | jmp(x_dec, "bitloop") 21 | # Assert stop bit for 8 cycles total (incl 1 for pull()) 22 | nop() .side(1) [6] 23 | 24 | 25 | # Now we add 8 UART TXs, on pins 10 to 17. Use the same baud rate for all of them. 26 | uarts = [] 27 | for i in range(NUM_UARTS): 28 | sm = StateMachine( 29 | i, uart_tx, freq=8 * UART_BAUD, sideset_base=Pin(PIN_BASE + i), out_base=Pin(PIN_BASE + i) 30 | ) 31 | sm.active(1) 32 | uarts.append(sm) 33 | 34 | # We can print characters from each UART by pushing them to the TX FIFO 35 | def pio_uart_print(sm, s): 36 | for c in s: 37 | sm.put(ord(c)) 38 | 39 | 40 | # Print a different message from each UART 41 | for i, u in enumerate(uarts): 42 | pio_uart_print(u, "Hello from UART {}!\n".format(i)) 43 | -------------------------------------------------------------------------------- /pio/pio_ws2812.py: -------------------------------------------------------------------------------- 1 | # Example using PIO to drive a set of WS2812 LEDs. 2 | 3 | import array, time 4 | from machine import Pin 5 | import rp2 6 | 7 | # Configure the number of WS2812 LEDs. 8 | NUM_LEDS = 8 9 | 10 | 11 | @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) 12 | def ws2812(): 13 | T1 = 2 14 | T2 = 5 15 | T3 = 3 16 | wrap_target() 17 | label("bitloop") 18 | out(x, 1) .side(0) [T3 - 1] 19 | jmp(not_x, "do_zero") .side(1) [T1 - 1] 20 | jmp("bitloop") .side(1) [T2 - 1] 21 | label("do_zero") 22 | nop() .side(0) [T2 - 1] 23 | wrap() 24 | 25 | 26 | # Create the StateMachine with the ws2812 program, outputting on Pin(22). 27 | sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(22)) 28 | 29 | # Start the StateMachine, it will wait for data on its FIFO. 30 | sm.active(1) 31 | 32 | # Display a pattern on the LEDs via an array of LED RGB values. 33 | ar = array.array("I", [0 for _ in range(NUM_LEDS)]) 34 | 35 | # Cycle colours. 36 | for i in range(4 * NUM_LEDS): 37 | for j in range(NUM_LEDS): 38 | r = j * 100 // (NUM_LEDS - 1) 39 | b = 100 - j * 100 // (NUM_LEDS - 1) 40 | if j != i % NUM_LEDS: 41 | r >>= 3 42 | b >>= 3 43 | ar[j] = r << 16 | b 44 | sm.put(ar, 8) 45 | time.sleep_ms(50) 46 | 47 | # Fade out. 48 | for i in range(24): 49 | for j in range(NUM_LEDS): 50 | ar[j] >>= 1 51 | sm.put(ar, 8) 52 | time.sleep_ms(50) 53 | -------------------------------------------------------------------------------- /pwm/pwm_fade.py: -------------------------------------------------------------------------------- 1 | # Example using PWM to fade an LED. 2 | 3 | import time 4 | from machine import Pin, PWM 5 | 6 | 7 | # Construct PWM object, with LED on Pin(25). 8 | pwm = PWM(Pin(25)) 9 | 10 | # Set the PWM frequency. 11 | pwm.freq(1000) 12 | 13 | # Fade the LED in and out a few times. 14 | duty = 0 15 | direction = 1 16 | for _ in range(8 * 256): 17 | duty += direction 18 | if duty > 255: 19 | duty = 255 20 | direction = -1 21 | elif duty < 0: 22 | duty = 0 23 | direction = 1 24 | pwm.duty_u16(duty * duty) 25 | time.sleep(0.001) 26 | -------------------------------------------------------------------------------- /spi/spi.py: -------------------------------------------------------------------------------- 1 | from machine import SPI 2 | 3 | spi = SPI(0) 4 | spi = SPI(0, 100_000) 5 | spi = SPI(0, 100_000, polarity=1, phase=1) 6 | 7 | spi.write('test') 8 | spi.read(5) 9 | 10 | buf = bytearray(3) 11 | spi.write_readinto('out', buf) 12 | -------------------------------------------------------------------------------- /uart/loopback/README.adoc: -------------------------------------------------------------------------------- 1 | = Using UART on the Raspberry Pi Pico 2 | :xrefstyle: short 3 | 4 | Send data from the UART1 port to the UART0 port. Other things to try; 5 | 6 | [source,python] 7 | ---- 8 | uart0 = UART(0) 9 | ---- 10 | 11 | which will open a UART connection at the default baudrate of 115200, and 12 | 13 | [source,python] 14 | ---- 15 | uart0.readline() 16 | ---- 17 | 18 | which will read until the CR (\r) and NL (\n) characters, then return the line. 19 | 20 | == Wiring information 21 | 22 | See <> for wiring instructions. 23 | 24 | [[uart-wiring-diagram]] 25 | [pdfwidth=75%] 26 | .Wiring two of the Pico's ports together. Be sure to wire UART0 TX to UART1 RX and UART0 RX to UART1 TX. 27 | image::pico_uart_example.png[] 28 | 29 | == List of Files 30 | 31 | A list of files with descriptions of their function; 32 | 33 | uart.py:: The example code. 34 | 35 | == Bill of Materials 36 | 37 | .A list of materials required for the example 38 | [[uart-bom-table]] 39 | [cols=3] 40 | |=== 41 | | *Item* | *Quantity* | Details 42 | | Breadboard | 1 | generic part 43 | | Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ 44 | |=== 45 | -------------------------------------------------------------------------------- /uart/loopback/pico_uart_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raspberrypi/pico-micropython-examples/1dc8d73a08f0e791c7694855cb61a5bfe8537756/uart/loopback/pico_uart_example.png -------------------------------------------------------------------------------- /uart/loopback/uart.py: -------------------------------------------------------------------------------- 1 | from machine import UART, Pin 2 | import time 3 | 4 | uart1 = UART(1, baudrate=9600, tx=Pin(8), rx=Pin(9)) 5 | 6 | uart0 = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) 7 | 8 | txData = b'hello world\n\r' 9 | uart1.write(txData) 10 | time.sleep(0.1) 11 | rxData = bytes() 12 | while uart0.any() > 0: 13 | rxData += uart0.read(1) 14 | 15 | print(rxData.decode('utf-8')) -------------------------------------------------------------------------------- /wireless/webserver.py: -------------------------------------------------------------------------------- 1 | import network 2 | import socket 3 | import time 4 | 5 | from machine import Pin 6 | 7 | led = Pin(15, Pin.OUT) 8 | 9 | ssid = 'YOUR NETWORK NAME' 10 | password = 'YOUR NETWORK PASSWORD' 11 | 12 | wlan = network.WLAN(network.STA_IF) 13 | wlan.active(True) 14 | wlan.connect(ssid, password) 15 | 16 | html = """ 17 | 18 | Pico W 19 |

Pico W

20 |

%s

21 | 22 | 23 | """ 24 | 25 | max_wait = 10 26 | while max_wait > 0: 27 | if wlan.status() < 0 or wlan.status() >= 3: 28 | break 29 | max_wait -= 1 30 | print('waiting for connection...') 31 | time.sleep(1) 32 | 33 | if wlan.status() != 3: 34 | raise RuntimeError('network connection failed') 35 | else: 36 | print('connected') 37 | status = wlan.ifconfig() 38 | print( 'ip = ' + status[0] ) 39 | 40 | addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] 41 | 42 | s = socket.socket() 43 | s.bind(addr) 44 | s.listen(1) 45 | 46 | print('listening on', addr) 47 | 48 | # Listen for connections 49 | while True: 50 | try: 51 | cl, addr = s.accept() 52 | print('client connected from', addr) 53 | request = cl.recv(1024) 54 | print(request) 55 | 56 | request = str(request) 57 | led_on = request.find('/light/on') 58 | led_off = request.find('/light/off') 59 | print( 'led on = ' + str(led_on)) 60 | print( 'led off = ' + str(led_off)) 61 | 62 | if led_on == 6: 63 | print("led on") 64 | led.value(1) 65 | stateis = "LED is ON" 66 | 67 | if led_off == 6: 68 | print("led off") 69 | led.value(0) 70 | stateis = "LED is OFF" 71 | 72 | response = html % stateis 73 | 74 | cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') 75 | cl.send(response) 76 | cl.close() 77 | 78 | except OSError as e: 79 | cl.close() 80 | print('connection closed') --------------------------------------------------------------------------------