c737cde947
Anywhere a module is mentioned, use its "non-u" name for consistency. The "import module" vs "import umodule" is something of a FAQ, and this commit intends to help clear that up. As a first approximation MicroPython is Python, and so imports should work the same as Python and use the same name, to a first approximation. The u-version of a module is a detail that can be learned later on, when the user wants to understand more and have finer control over importing. Existing Python code should just work, as much as it is possible to do that within the constraints of embedded systems, and the MicroPython documentation should match the idiomatic way to write Python code. With universal weak links for modules (via MICROPY_MODULE_WEAK_LINKS) users can consistently use "import foo" across all ports (with the exception of the minimal ports). And the ability to override/extend via "foo.py" continues to work well. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
301 lines
9.2 KiB
ReStructuredText
301 lines
9.2 KiB
ReStructuredText
.. _rp2_quickref:
|
|
|
|
Quick reference for the RP2
|
|
===========================
|
|
|
|
.. image:: img/pico_pinout.png
|
|
:alt: Raspberry Pi Pico
|
|
:width: 640px
|
|
|
|
The Raspberry Pi Pico Development Board (image attribution: Raspberry Pi Foundation).
|
|
|
|
Below is a quick reference for Raspberry Pi RP2xxx boards. If it is your first time
|
|
working with this board it may be useful to get an overview of the microcontroller:
|
|
|
|
.. toctree::
|
|
:maxdepth: 1
|
|
|
|
general.rst
|
|
tutorial/intro.rst
|
|
|
|
Installing MicroPython
|
|
----------------------
|
|
|
|
See the corresponding section of tutorial: :ref:`rp2_intro`. It also includes
|
|
a troubleshooting subsection.
|
|
|
|
General board control
|
|
---------------------
|
|
|
|
The MicroPython REPL is accessed via the USB serial port. Tab-completion is useful to
|
|
find out what methods an object has. Paste mode (ctrl-E) is useful to paste a
|
|
large slab of Python code into the REPL.
|
|
|
|
The :mod:`machine` module::
|
|
|
|
import machine
|
|
|
|
machine.freq() # get the current frequency of the CPU
|
|
machine.freq(240000000) # set the CPU frequency to 240 MHz
|
|
|
|
The :mod:`rp2` module::
|
|
|
|
import rp2
|
|
|
|
Delay and timing
|
|
----------------
|
|
|
|
Use the :mod:`time <time>` module::
|
|
|
|
import time
|
|
|
|
time.sleep(1) # sleep for 1 second
|
|
time.sleep_ms(500) # sleep for 500 milliseconds
|
|
time.sleep_us(10) # sleep for 10 microseconds
|
|
start = time.ticks_ms() # get millisecond counter
|
|
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
|
|
|
Timers
|
|
------
|
|
|
|
RP2040's system timer peripheral provides a global microsecond timebase and
|
|
generates interrupts for it. The software timer is available currently,
|
|
and there are unlimited number of them (memory permitting). There is no need
|
|
to specify the timer id (id=-1 is supported at the moment) as it will default
|
|
to this.
|
|
|
|
Use the :mod:`machine.Timer` class::
|
|
|
|
from machine import Timer
|
|
|
|
tim = Timer(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
|
|
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2))
|
|
|
|
|
|
.. _rp2_Pins_and_GPIO:
|
|
|
|
Pins and GPIO
|
|
-------------
|
|
|
|
Use the :ref:`machine.Pin <machine.Pin>` class::
|
|
|
|
from machine import Pin
|
|
|
|
p0 = Pin(0, Pin.OUT) # create output pin on GPIO0
|
|
p0.on() # set pin to "on" (high) level
|
|
p0.off() # set pin to "off" (low) level
|
|
p0.value(1) # set pin to on/high
|
|
|
|
p2 = Pin(2, Pin.IN) # create input pin on GPIO2
|
|
print(p2.value()) # get value, 0 or 1
|
|
|
|
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
|
|
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
|
|
|
|
UART (serial bus)
|
|
-----------------
|
|
|
|
There are two UARTs, UART0 and UART1. UART0 can be mapped to GPIO 0/1, 12/13
|
|
and 16/17, and UART1 to GPIO 4/5 and 8/9.
|
|
|
|
|
|
See :ref:`machine.UART <machine.UART>`. ::
|
|
|
|
from machine import UART, Pin
|
|
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
|
|
uart1.write('hello') # write 5 bytes
|
|
uart1.read(5) # read up to 5 bytes
|
|
|
|
.. note::
|
|
|
|
REPL over UART is disabled by default. You can see the :ref:`rp2_intro` for
|
|
details on how to enable REPL over UART.
|
|
|
|
|
|
PWM (pulse width modulation)
|
|
----------------------------
|
|
|
|
There are 8 independent channels each of which have 2 outputs making it 16
|
|
PWM channels in total which can be clocked from 7Hz to 125Mhz.
|
|
|
|
Use the ``machine.PWM`` class::
|
|
|
|
from machine import Pin, PWM
|
|
|
|
pwm0 = PWM(Pin(0)) # create PWM object from a pin
|
|
pwm0.freq() # get current frequency
|
|
pwm0.freq(1000) # set frequency
|
|
pwm0.duty_u16() # get current duty cycle, range 0-65535
|
|
pwm0.duty_u16(200) # set duty cycle, range 0-65535
|
|
pwm0.deinit() # turn off PWM on the pin
|
|
|
|
ADC (analog to digital conversion)
|
|
----------------------------------
|
|
|
|
RP2040 has five ADC channels in total, four of which are 12-bit SAR based
|
|
ADCs: GP26, GP27, GP28 and GP29. The input signal for ADC0, ADC1, ADC2 and
|
|
ADC3 can be connected with GP26, GP27, GP28, GP29 respectively (On Pico board,
|
|
GP29 is connected to VSYS). The standard ADC range is 0-3.3V. The fifth
|
|
channel is connected to the in-built temperature sensor and can be used for
|
|
measuring the temperature.
|
|
|
|
Use the :ref:`machine.ADC <machine.ADC>` class::
|
|
|
|
from machine import ADC, Pin
|
|
adc = ADC(Pin(26)) # create ADC object on ADC pin
|
|
adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v
|
|
|
|
Software SPI bus
|
|
----------------
|
|
|
|
Software SPI (using bit-banging) works on all pins, and is accessed via the
|
|
:ref:`machine.SoftSPI <machine.SoftSPI>` class::
|
|
|
|
from machine import Pin, SoftSPI
|
|
|
|
# construct a SoftSPI bus on the given pins
|
|
# polarity is the idle state of SCK
|
|
# phase=0 means sample on the first edge of SCK, phase=1 means the second
|
|
spi = SoftSPI(baudrate=100_000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
|
|
|
spi.init(baudrate=200000) # set the baudrate
|
|
|
|
spi.read(10) # read 10 bytes on MISO
|
|
spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI
|
|
|
|
buf = bytearray(50) # create a buffer
|
|
spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case)
|
|
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI
|
|
|
|
spi.write(b'12345') # write 5 bytes on MOSI
|
|
|
|
buf = bytearray(4) # create a buffer
|
|
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
|
|
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
|
|
|
|
.. Warning::
|
|
Currently *all* of ``sck``, ``mosi`` and ``miso`` *must* be specified when
|
|
initialising Software SPI.
|
|
|
|
Hardware SPI bus
|
|
----------------
|
|
|
|
The RP2040 has 2 hardware SPI buses which is accessed via the
|
|
:ref:`machine.SPI <machine.SPI>` class and has the same methods as software
|
|
SPI above::
|
|
|
|
from machine import Pin, SPI
|
|
|
|
spi = SPI(1, 10_000_000) # Default assignment: sck=Pin(10), mosi=Pin(11), miso=Pin(8)
|
|
spi = SPI(1, 10_000_000, sck=Pin(14), mosi=Pin(15), miso=Pin(12))
|
|
spi = SPI(0, baudrate=80_000_000, polarity=0, phase=0, bits=8, sck=Pin(6), mosi=Pin(7), miso=Pin(4))
|
|
|
|
Software I2C bus
|
|
----------------
|
|
|
|
Software I2C (using bit-banging) works on all output-capable pins, and is
|
|
accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
|
|
|
|
from machine import Pin, SoftI2C
|
|
|
|
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100_000)
|
|
|
|
i2c.scan() # scan for devices
|
|
|
|
i2c.readfrom(0x3a, 4) # read 4 bytes from device with address 0x3a
|
|
i2c.writeto(0x3a, '12') # write '12' to device with address 0x3a
|
|
|
|
buf = bytearray(10) # create a buffer with 10 bytes
|
|
i2c.writeto(0x3a, buf) # write the given buffer to the peripheral
|
|
|
|
Hardware I2C bus
|
|
----------------
|
|
|
|
The driver is accessed via the :ref:`machine.I2C <machine.I2C>` class and
|
|
has the same methods as software I2C above::
|
|
|
|
from machine import Pin, I2C
|
|
|
|
i2c = I2C(0) # default assignment: scl=Pin(9), sda=Pin(8)
|
|
i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=400_000)
|
|
|
|
Real time clock (RTC)
|
|
---------------------
|
|
|
|
See :ref:`machine.RTC <machine.RTC>` ::
|
|
|
|
from machine import RTC
|
|
|
|
rtc = RTC()
|
|
rtc.datetime((2017, 8, 23, 2, 12, 48, 0, 0)) # set a specific date and
|
|
# time, eg. 2017/8/23 1:12:48
|
|
rtc.datetime() # get date and time
|
|
|
|
WDT (Watchdog timer)
|
|
--------------------
|
|
|
|
The RP2040 has a watchdog which is a countdown timer that can restart
|
|
parts of the chip if it reaches zero.
|
|
|
|
See :ref:`machine.WDT <machine.WDT>`. ::
|
|
|
|
from machine import WDT
|
|
|
|
# enable the WDT with a timeout of 5s (1s is the minimum)
|
|
wdt = WDT(timeout=5000)
|
|
wdt.feed()
|
|
|
|
|
|
OneWire driver
|
|
--------------
|
|
|
|
The OneWire driver is implemented in software and works on all pins::
|
|
|
|
from machine import Pin
|
|
import onewire
|
|
|
|
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
|
|
ow.scan() # return a list of devices on the bus
|
|
ow.reset() # reset the bus
|
|
ow.readbyte() # read a byte
|
|
ow.writebyte(0x12) # write a byte on the bus
|
|
ow.write('123') # write bytes on the bus
|
|
ow.select_rom(b'12345678') # select a specific device by its ROM code
|
|
|
|
There is a specific driver for DS18S20 and DS18B20 devices::
|
|
|
|
import time, ds18x20
|
|
ds = ds18x20.DS18X20(ow)
|
|
roms = ds.scan()
|
|
ds.convert_temp()
|
|
time.sleep_ms(750)
|
|
for rom in roms:
|
|
print(ds.read_temp(rom))
|
|
|
|
Be sure to put a 4.7k pull-up resistor on the data line. Note that
|
|
the ``convert_temp()`` method must be called each time you want to
|
|
sample the temperature.
|
|
|
|
NeoPixel and APA106 driver
|
|
--------------------------
|
|
|
|
Use the ``neopixel`` and ``apa106`` modules::
|
|
|
|
from machine import Pin
|
|
from neopixel import NeoPixel
|
|
|
|
pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels
|
|
np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels
|
|
np[0] = (255, 255, 255) # set the first pixel to white
|
|
np.write() # write data to all pixels
|
|
r, g, b = np[0] # get first pixel colour
|
|
|
|
|
|
The APA106 driver extends NeoPixel, but internally uses a different colour order::
|
|
|
|
from apa106 import APA106
|
|
ap = APA106(pin, 8)
|
|
r, g, b = ap[0]
|
|
|
|
APA102 (DotStar) uses a different driver as it has an additional clock pin.
|