Programming reference
See also
official MycroPython documentation
Boxes like this throughout the page provide direct links to specific relevant pages in the official MicroPython documentation.
Digital IOs
Digital Inputs
inputs.Pin
.inputs.Pin
.Each digital input has a green LED that lights up when voltage is applied to the input (meaning the input state is then logic high).
The state of the input can be read simply by calling the method value()
from the corresponding Pin
object:
inputs.Pin.input1.value() # returns the input logic state, either 0 or 1
official MycroPython documentation
pyb.Pin
class
Quadrature encoder Inputs
encoder |
digital inputs |
---|---|
|
9 and 10 |
|
11 and 12 |
|
13 and 14 |
|
15 and 16 |
inputs.Encoder
.mode()
with arguments:
|
counts both on input A and B flanks, default mode |
|
only counts on input A flanks |
|
only counts on input B flanks |
|
disables encoder mode and returns to basic digital input mode |
mode()
invoked without arguments returns the current mode.For instance:
inputs.Encoder.ENC1.mode('AB') # enables encoder using mode AB, default mode
The encoder count value can be read using the method value()
:
inputs.Encoder.ENC1.value()
Note
'A'
and 'B'
still require both A and B valid input quadrature signals.official MycroPython documentation
pyb.Timer
class
Digital outputs
on()
and off()
.outputs.output1.on() # output_1 is switched on
pyb.delay(1000)
outputs.output1.off() # output_1 is switched off
is_in_fault()
returns True
if the protection has tripped.OC_threshold()
returns the current threshold in Amps for the overcurrent protection.mode('PWM')
is used to enable PWM mode and pulse_width_percent()
sets the percentage of ON time:outputs.output1.mode('PWM') # output1 is configured to PWM mode
outputs.output1.pulse_width_percent(20) # output1 set to 20% duty cycle
pyb.delay(1000)
outputs.output1.off() # output_1 is switched off
on()
and off()
still work also in PWM mode, and set the duty cycle to 100% and 0% respectively.pwm_freq()
changes the PWM frequency:outputs.output1.pwm_freq(500) # PWM frequency set to 500 Hz (default is 1000 Hz)
pwm_freq
:outputs.output1.mode('PWM', pwm_freq=2000) # PWM mode with 2000 Hz PWM frequency
mode('GPIO')
.load_connected()
returns True
if a low-impedance load is connected to the output.Vin()
returns the actual supply voltage measured from the power output.omega:ONE has H-Bridges instead of discrete power outputs, see the next paragraph.
high()
and low()
, respectively.outputs.output1.high() # output_1 is switched on
pyb.delay(1000)
outputs.output1.low() # output_1 is switched off
Attention
official MycroPython documentation
pyb.Pin
classH-Bridges
alpha:ONE does not provide H-Bridge outputs.
is_in_fault()
returns True
if any of the H-Bridges outputs have tripped the protection.on()
and off()
methods.'GPIO'
or in 'PWM'
mode, using the method mode()
.mode()
invoked without arguments returns the current operating mode.Pin
.outputs.HB1.mode('GPIO')
outputs.HB1.on() # outputs are enabled, but both are low (connected to GND)
outputs.HB1.Pin.A1.high() # output A1 high -> move forward
pyb.delay(1000)
outputs.HB1.Pin.A1.low() # stop
pyb.delay(1000)
outputs.HB1.Pin.A2.high() # output A2 high -> move backwards
pyb.delay(1000)
outputs.HB1.Pin.A2.low() # stop
outputs.HB1.mode('PWM')
outputs.HB1.on()
outputs.HB1.Pin.A1.pulse_width_percent(30) # move forward with 30% speed
pyb.delay(1000)
outputs.HB1.Pin.A1.pulse_width_percent(0) # stop
pwm_freq()
:pwm_freq()
invoked without arguments returns the current value.outputs.HB1.pwm_freq(500) # sets the pwm frequency to 500 Hz
pwm_freq
:outputs.HB1.mode('PWM', pwm_freq=1200) # sets the pwm frequency to 1200 Hz
decay()
:decay()
invoked without arguments returns the current mode.
|
In the off-time the current quickly decays to zero.
A spinning motor will coast in this phase.
|
|
In the off-time the current recirculates longer through the load.
As a consequence of its back-emf, a spinning motor will experience a braking torque and slow down quicker.
For solenoids, slow decay is usually preferred for a more constant current throughout the PWM cycle.
|
|
Fast decay for a fixed amount of time, subsequently slow decay mode for the remaining period of time.
Mainly used with stepper motors, particularly for microstepping.
|
omega:TWO does not provide H-Bridge outputs.
See also
For more detailed information on the current decay modes, read Texas Instruments’ Application Report Current Recirculation and Decay Modes. as well as the H-Bridge IC, DRV8841 datasheet.
LEDs
MicroPython LEDs
pyb
, where each color is controlled by a different LED object
|
blue |
|
green |
|
red |
pyb
.
|
blue |
pyb
.
|
blue |
The LEDs can be turned on and off simply using the on()
and off()
methods:
pyb.LED(1).on() # blue LED is switched on
pyb.delay(1000)
pyb.LED(1).off() # blue LED is switched off
For better code readability, you can also use a more self-explanatory variable:
LED_blue = pyb.LED(1)
LED_blue.on() # blue LED is switched on
pyb.delay(1000)
LED_blue.off() # blue LED is switched off
Finally, the toggle()
method also exists:
LED_blue.toggle() # blue LED is toggled
Note
official MycroPython documentation
pyb.LED
classRGB Status LEDs
LEDs
, automatically instantiated at boot.set_color(LED_nr, color, brightness)
keyword |
valid values |
---|---|
|
1 to 3 |
|
‘red’, ‘green’, ‘blue’, ‘yellow’, ‘orange’, ‘turquoise’, ‘aqua’, ‘pink’, ‘white’, ‘off’ |
|
0 to 31 |
LEDs.set_color(LED_nr=1,color='red') # with default brightness = 1
LEDs.set_color(LED_nr=2,color='green', brightness=5)
LEDs.set_color(3, 'blue') # shorter, using positional arguments
colors
:LEDs.colors.keys() # returns all colors
colors
dictionary can also be modified to include special, user-defined colors, if needed.set_rgb(LED_nr, red, green, blue, brightness)
keyword |
valid values |
---|---|
|
1 to 3 |
|
0 to 255 |
|
0 to 255 |
|
0 to 255 |
|
0 to 31 |
LEDs.set_rgb(LED_nr=1, red=167, green=23, blue=255, brightness=3)
To turn it off you can set color = 'off'
:
LEDs.set_color(LED_nr=1, color='off')
LEDs.set_color(2, 'off')
all_off()
is also provided, to turn all LEDs off at once.Timing and interrupts
Delay and timing
Insert a delay in the execution of a program, using the module pyb
pyb.delay(100) # wait for 100 milliseconds
pyb.udelay(10) # wait for 10 microsenconds
Measure the duration of a program in milliseconds
start_ms_count = pyb.millis() # store the starting time
pyb.delay(100) # the program or code block you want to measure
delta_t = pyb.elapsed_millis(start_ms_count)
print("elapsed time:", delta_t, "ms")
Measure the duration of a program in microseconds
start_us_count = pyb.micros() # store the starting time
pyb.delay(100) # the program or code block you want to measure
delta_t = pyb.elapsed_micros(start_us_count)
print("elapsed time:", delta_t, "us")
alternatively you can also use the time
module
import time
start_ms_count = time.ticks_ms() # store the start time in milliseconds
pyb.delay(100) # the program or code block you want to measure
delta_t = time.ticks_diff(time.ticks_ms(), start_ms_count) # compute time difference
print("elapsed time:", delta_t, "ms")
official MycroPython documentation
External interrupts
pyb.ExtInt(pin, mode, pull, callback)
,mode
can have following values:
|
The interrupt will be triggered only by rising edges |
|
The interrupt will be triggered only by falling edges |
|
The interrupt will be triggered both by rising and falling edges |
pull
is defined like with any GPIO input pin.led = pyb.LED(1)
# first define the callback function
def cb_func():
led.toggle()
# this will call the callback function cb_func() each time the pin object input_1 goes high, toggling the LED
ext_input_1 = pyb.ExtInt(input_1, pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_NONE, cb_func)
Important
Special care has to be given when writing callback functions (also called interrupt handlers) since they can be invoked at any time during the execution of the code and could therefore have unwanted consequences. For more information on this topic, see the detailed information in the official MicroPython documentation: Writing interrupt handlers.
Attention
official MycroPython documentation
Timers
Timers are hardware peripherals that can be used for a variety of tasks, from frequency and pulse counting to generating PWM signals. See the official Micropython documentation for all the supported features.
# first define the callback function
def cb_func(t):
pyb.LED(1).toggle()
# then create the timer and assign the callback function
tim = pyb.Timer(1, freq=1, callback=cb_func) # Timer1 set to a frequency of 1 Hz
Alternatively, the callback function can also be defined or changed after creating the timer, here demonstrated using a lambda function
tim = pyb.Timer(1, freq=1) # Timer1 set to a frequency of 1 Hz
tim.callback(lambda t: pyb.LED(1).toggle())
The callback function can be disabled by setting it to None
tim.callback(None)
Using the machine
module, a timer can also be configured to trigger a callback function just once after a delay specified in milliseconds:
import machine
def cb_function(t):
print('test')
tim = machine.Timer()
tim.init(mode=machine.Timer.ONE_SHOT, period=2000, callback=cb_function)
official MycroPython documentation
RTC
RTC
class provides access to the microcontroller’s Real Time Clock, which keeps track of time and date also when the board is not supplied with power, thanks to the CR2032 backup battery. The object rtc
is automatically instantiated on boot.datetime()
is used both to set and to read the current datetime and uses a tuple with format(year, month, day, weekday, hours, minutes, seconds, microseconds)
:rtc.datetime((2013, 4, 29, 1, 0, 0, 0, 0)) # set a fairly specific date and time
pyb.delay(1000) # 1 s delay so you see a difference in the current time
rtc.datetime() # returns a tuple corresponding to the current datetime
If you need a datetime string, such as for a timestamp, you can use the method datetime_str()
:
rtc.datetime_str()
datetime_print()
to print it out._formatstring
and/or the method datetime_str()
can be overridden.time
module provides access to different time formats, such as the Epoch (in seconds since Jan 1, 2000)import time
print(time.mktime(time.localtime())) # seconds since Jan 1, 2000
official MycroPython documentation
pyb.RTC
classCommunication interfaces
Ethernet
eth
is automatically instantiated on boot.eth
is automatically instantiated on boot.The network interface then needs to be activated and configured, e.g. using DHCP:
eth.active(True)
eth.ifconfig('dhcp')
You can also configure a static IP by passing a tuple (ip_address, subnet_mask, gateway, dns_server)
eth.active(True)
eth.ifconfig(('192.168.1.88','255.255.255.0','192.168.1.1','192.168.1.1'))
This snippet prints out information on the state of the ethernet interface, so you can verify it is connected:
print('eth.status =', eth.status())
print('eth.active =', eth.active())
print('eth.isconnected =', eth.isconnected())
print('eth.ifconfig =', eth.ifconfig())
Look-up the IP address of a host using socket
(it will automatically use the network interface available):
import usocket as socket
ip_addr = socket.getaddrinfo('www.systematica.ch',80)[0][-1][0]
print('www.systematica.ch has address', ip_addr)
uping
utility bundled with the firmware.from uping import ping
ping('www.systematica.ch', count=4, interval=1000) # ping www.systematica.ch four times with an interval of 1000 ms
Use a socket
to receive data from a server:
import usocket as socket
addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
addr = addr_info[0][-1]
s = socket.socket()
s.connect(addr)
while True:
data = s.recv(500)
print(str(data, 'utf8'), end='')
You can interrupt the program execution with Ctrl + C
as usual
CAN bus
can
CAN Bus test in loopback mode (to be able to test without actual bus nodes connected)
can.init(mode=can.LOOPBACK, baudrate=250_000)
can.setfilter(0, can.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125, 126
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
CAN Bus test in normal mode (at least one more node has to be present on the bus so, that the messages are acknowledged, otherwise the message will keep retransmitting indefinitely)
can.init(mode=can.NORMAL, baudrate=250_000)
can.setfilter(0, can.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125, 126
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
can
, supporting baudrates up to 1 Mbit/s.jumper |
function |
setting |
result |
---|---|---|---|
SJ1 |
bus terminator |
open |
bus unterminated |
closed |
bus terminated with 120 Ohm resistor |
||
SJ5 |
slew-rate limit |
open |
max 250 kbit/s |
lower pads closed |
max 500 kbit/s |
||
upper pads closed |
max 1 Mbit/s |
CAN Bus test in loopback mode (to be able to test without actual bus nodes connected)
can.init(mode=can.LOOPBACK, baudrate=250_000)
can.setfilter(0, can.RANGE, 0, (123, 126)) # set a filter to receive messages with id=123, 124, 125, 126
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
CAN Bus test in normal mode (at least one more node has to be present on the bus so, that the messages are acknowledged, otherwise the message will keep retransmitting indefinitely)
can.init(mode=can.NORMAL, baudrate=250_000)
can.setfilter(0, can.RANGE, 0, (123, 126)) # set a filter to receive messages with id=123, 124, 125, 126
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
can
CAN Bus test in loopback mode (to be able to test without actual bus nodes connected)
can.init(mode=can.LOOPBACK, baudrate=250_000)
can.setfilter(0, can.RANGE, 0, (123, 126)) # set a filter to receive messages with id=123, 124, 125, 126
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
CAN Bus test in normal mode (at least one more node has to be present on the bus so, that the messages are acknowledged, otherwise the message will keep retransmitting indefinitely)
can.init(mode=can.NORMAL, baudrate=250_000)
can.setfilter(0, can.RANGE, 0, (123, 126)) # set a filter to receive messages with id=123, 124, 125, 126
can.send('message!', 123) # send a message with id 123
can.recv(0) # receive message on FIFO 0
official MycroPython documentation
pyb.CAN
classRS422/485
rs485_1
and rs485_2
.slew_rate('limited')
(default).rs485_1.mode('4-Wire') # default mode
rs485_1.init(baudrate=9600)
rs485_1.write('Test RS485 full-duplex 9.6 kbaud')
write()
, writechar()
and sendbreak()
automatically toggle the driver enable pin on and off when transmitting.rs485_1.mode('2-Wire')
rs485_1.init(baudrate=9600)
rs485_1.write('Test RS485 half-duplex 9.6 kbaud')
echo('on')
:rs485_1.echo('on')
rs485_1.mode('2-Wire echo')
|mode()
returns the current mode:
rs485_1.mode()
For baud rates above 250 kbit/s the driver must be configured in fast mode using slew_rate('max')
:
rs485_1.init(baudrate=500000)
rs485_1.slew_rate('max')
rs485_1.write('Test RS485 500 kbaud')
RS485
.jumper |
function |
setting |
result |
---|---|---|---|
SJ4 |
nRE |
upper pads closed (default) |
nRE connected to DE |
lower pads closed |
nRE connected to GND (receiver always on) |
||
SJ6 |
AB terminator |
open |
rx line unterminated |
closed (default) |
rx line terminated with 120 Ohm resistor |
||
SJ7 |
YZ terminator |
open |
tx line unterminated |
closed (default) |
tx line terminated with 120 Ohm resistor |
||
SJ8 |
half-duplex |
open (default) |
4-wire full-duplex mode |
closed |
2-wire half-duplex mode (-> use AB) |
||
SJ9 |
slew-rate limit |
open (default) |
max 250 kbit/s |
lower pads closed |
max 500 kbit/s |
||
upper pads closed |
max 16 Mbit/s |
rs485.init(baudrate=9600)
rs485.write('TEST RS485 full-duplex')
rs485.init(baudrate=9600)
rs485.write('TEST RS485 half-duplex')
official MycroPython documentation
pyb.UART
classRS232/485
rs232_485
and can be used as follows:# set up interface in RS232 mode
rs232_485.init(baudrate=9600)
rs232_485.mode('RS232')
rs232_485.slew_rate('slow') # enables low-EMI mode for <= 250 kBit/s (dafault)
# send a test message
rs232_485.write('Test RS232')
slew_rate('max')
.termination()
does not apply to RS232 mode.# set up interface in RS485 half-duplex mode
rs232_485.init(baudrate=9600)
rs232_485.mode('RS485')
rs232_485.termination('on') # enable 120 Ohm termination
# send a test message
rs232_485.write('Test RS485 half-duplex')
termination('on')
if the bus is otherwise unterminated.slew_rate()
does not apply to RS485 mode.omega:ONE does not provide an RS232/485 interface.
omega:TWO does not provide an RS232/485 interface.
official MycroPython documentation
pyb.UART
classMultifunction pins
gpios.Pin
, named gpio1
to gpio21
.AUX_3V3()
as follows:gpios.AUX_3V3('on') # turns on the 3V3 regulator
gpios.Pin.EN_3V3
regulator enable pin can also be manipulated directly.pyb.Pin.cpu.A4
.pyb.Pin.cpu.A4
.Attention
GPIO output
gpios.Pin.gpio1.init(pyb.Pin.OUT)
# turn on the output for 1s
gpios.Pin.gpio1.high()
pyb.delay(1000)
gpios.Pin.gpio1.low()
# initialize the output by instantiating the Pin object
pin_out = pyb.Pin(pyb.Pin.cpu.A4, pyb.Pin.OUT)
# turn on the output for 1s
pin_out.high()
pyb.delay(1000)
pin_out.low()
# initialize the output by instantiating the Pin object
pin_out = pyb.Pin(pyb.Pin.cpu.A4, pyb.Pin.OUT)
# turn on the output for 1s
pin_out.high()
pyb.delay(1000)
pin_out.low()
official MycroPython documentation
pyb.Pin
classGPIO input
|
enables a pull up of about 40 kOhm to 3.3 V |
|
enables a pull down of about 40 kOhm to ground |
|
leaves it floating. Use this only if the circuit you connect already has a pull resistor installed. |
gpios.Pin.gpio1.init(pyb.Pin.IN, pyb.Pin.PULL_UP)
gpios.Pin.gpio1.value()
pin_in = pyb.Pin(GPIO_2, pyb.Pin.IN, pyb.Pin.PULL_UP)
pin_in.value() # returns value, either 0 or 1
pin_in = pyb.Pin(GPIO_2, pyb.Pin.IN, pyb.Pin.PULL_UP)
pin_in.value() # returns value, either 0 or 1
official MycroPython documentation
pyb.Pin
classPWM
# instantiate the timer with a frequency of 1 kHz
tim = pyb.Timer(2, freq=1000) # the frequency will be the PWM frequency
# then create the pwm channel on the pin
ch = tim.channel(1, pyb.Timer.PWM, gpios.Pin.gpio9)
# you can then set or change the pulse width in percent
ch.pulse_width_percent(50)
# instantiate the timer with a frequency of 1 kHz
tim = pyb.Timer(13, freq=1000) # the frequency will be the PWM frequency
# then create the pwm channel on the pin
ch = tim.channel(1, pyb.Timer.PWM, pyb.Pin.cpu.A6)
# you can then set or change the pulse width in percent
ch.pulse_width_percent(50)
# instantiate the timer with a frequency of 1 kHz
tim = pyb.Timer(13, freq=1000) # the frequency will be the PWM frequency
# then create the pwm channel on the pin
ch = tim.channel(1, pyb.Timer.PWM, pyb.Pin.cpu.A6)
# you can then set or change the pulse width in percent
ch.pulse_width_percent(50)
ADC
adc = pyb.ADC(gpios.Pin.gpio8) # GPIO8 or cpu pin A4
adc.read() # read value, 0 to 4095 corresponding to a voltage of 0 to 3.3V
adc = pyb.ADC(pyb.Pin.cpu.C0) # cpu pin C0
adc.read() # read value, 0 to 4095 corresponding to a voltage of 0 to 3.3V
adc = pyb.ADC(pyb.Pin.cpu.C0) # cpu pin C0
adc.read() # read value, 0 to 4095 corresponding to a voltage of 0 to 3.3V
DAC
bits=12
buffering=True
, unless your load has a very high impedance (MOhm range).dac = pyb.DAC(gpios.Pin.gpio8, buffering=True) # GPIO8 or cpu pin A4
dac.write(123) # output between 0 and 255
dac = pyb.DAC(pyb.Pin.cpu.A4, buffering=True) # cpu pin A4
dac.write(123) # output between 0 and 255
dac = pyb.DAC(pyb.Pin.cpu.A4, buffering=True) # cpu pin A4
dac.write(123) # output between 0 and 255
UART
TX |
transmit data |
RX |
receive data |
pyb.UART()
uart = pyb.UART(4, 9600)
uart.write('UART test')
uart.read() # read what has been received in the UART buffer
uart = pyb.UART(1, 9600)
uart.write('UART test')
uart.read() # read what has been received in the UART buffer
uart = pyb.UART(1, 9600)
uart.write('UART test')
uart.read() # read what has been received in the UART buffer
official MycroPython documentation
pyb.UART
classSPI bus
SCK |
clock signal |
MISO |
Master-in, Slave-out data |
MOSI |
Master-out, Slave-in data |
CS |
Chip Select, must be pulled low to enable communication with a slave device |
pyb.SPI()
# configure SPI4 as a master/controller
spi = pyb.SPI(4, mode=pyb.SPI.MASTER, baudrate=1000000, polarity=1, phase=0)
cs = pyb.Pin(pyb.Pin.cpu.E4, pyb.Pin.OUT, value=1)
cs.low() # enable chip select
spi.send(b'\x01\x02\x03\x04') # send bytes on the bus
spi.recv(5) # receive 5 bytes on the bus
spi.send_recv(b'\x01\x02\x03\x04') # send message and simultaneously receive 4 bytes
cs.high() # disable chip select
# configure SPI2 as a master/controller
spi = pyb.SPI(2, mode=pyb.SPI.MASTER, baudrate=1000000, polarity=1, phase=0)
cs = pyb.Pin(pyb.Pin.cpu.E10, pyb.Pin.OUT, value=1)
cs.low() # enable chip select
spi.send(b'\x01\x02\x03\x04') # send bytes on the bus
spi.recv(5) # receive 5 bytes on the bus
spi.send_recv(b'\x01\x02\x03\x04') # send message and simultaneously receive 4 bytes
cs.high() # disable chip select
# configure SPI2 as a master/controller
spi = pyb.SPI(2, mode=pyb.SPI.MASTER, baudrate=1000000, polarity=1, phase=0)
cs = pyb.Pin(pyb.Pin.cpu.E10, pyb.Pin.OUT, value=1)
cs.low() # enable chip select
spi.send(b'\x01\x02\x03\x04') # send bytes on the bus
spi.recv(5) # receive 5 bytes on the bus
spi.send_recv(b'\x01\x02\x03\x04') # send message and simultaneously receive 4 bytes
cs.high() # disable chip select
machine.SoftSPI()
:from machine import SoftSPI
# create Software SPI bus as a master/controller (pinout for omega)
spi = SoftSPI(baudrate=500000, polarity=1, phase=0, bits=8, firstbit=SoftSPI.MSB, sck=gpios.Pin.gpio19, mosi=gpios.Pin.gpio18, miso=gpios.Pin.gpio17)
cs = pyb.Pin(gpios.Pin.gpio20, pyb.Pin.OUT, value=1)
cs.low() # enable chip select
spi.write(b'\x01\x02\x03\x04') # send bytes on the bus
spi.read(4) # receive 4 bytes on the bus
cs.high() # disable chip select
from machine import SoftSPI
# create Software SPI bus as a master/controller (pinout for omega)
spi = SoftSPI(baudrate=500000, polarity=1, phase=0, bits=8, firstbit=SoftSPI.MSB, sck=pyb.Pin.cpu.E9, mosi=pyb.Pin.cpu.E8, miso=pyb.Pin.cpu.E7)
cs = pyb.Pin(pyb.Pin.cpu.E10, pyb.Pin.OUT, value=1)
cs.low() # enable chip select
spi.write(b'\x01\x02\x03\x04') # send bytes on the bus
spi.read(4) # receive 4 bytes on the bus
cs.high() # disable chip select
from machine import SoftSPI
# create Software SPI bus as a master/controller (pinout for omega)
spi = SoftSPI(baudrate=500000, polarity=1, phase=0, bits=8, firstbit=SoftSPI.MSB, sck=pyb.Pin.cpu.E9, mosi=pyb.Pin.cpu.E8, miso=pyb.Pin.cpu.E7)
cs = pyb.Pin(pyb.Pin.cpu.E10, pyb.Pin.OUT, value=1)
cs.low() # enable chip select
spi.write(b'\x01\x02\x03\x04') # send bytes on the bus
spi.read(4) # receive 4 bytes on the bus
cs.high() # disable chip select
I2C bus
SCL |
clock signal |
SDA |
transmit and receive data |
pyb.I2C()
# create hardware I2C1 object
i2c = pyb.I2C(2, pyb.I2C.CONTROLLER, baudrate=400000)
addresses = i2c.scan() # returns list of slave addresses
i2c.send('123', addr=0x42) # send 3 bytes to slave with address 0x42
data = i2c.recv(2, addr=0x42) # read 2 bytes from bus
i2c.mem_write(b'\x01\x02', addr=0x42, memaddr=0x10) # write 2 bytes to slave 0x42, memory address 0x10
data = i2c.mem_read(2, addr=0x42, memaddr=0x10) # read 2 bytes from slave 0x42, starting from memory address 0x10
# create hardware I2C1 object
i2c = pyb.I2C(1, pyb.I2C.CONTROLLER, baudrate=400000)
addresses = i2c.scan() # returns list of slave addresses
i2c.send('123', addr=0x42) # send 3 bytes to slave with address 0x42
data = i2c.recv(2, addr=0x42) # read 2 bytes from bus
i2c.mem_write(b'\x01\x02', addr=0x42, memaddr=0x10) # write 2 bytes to slave 0x42, memory address 0x10
data = i2c.mem_read(2, addr=0x42, memaddr=0x10) # read 2 bytes from slave 0x42, starting from memory address 0x10
# create hardware I2C1 object
i2c = pyb.I2C(1, pyb.I2C.CONTROLLER, baudrate=400000)
addresses = i2c.scan() # returns list of slave addresses
i2c.send('123', addr=0x42) # send 3 bytes to slave with address 0x42
data = i2c.recv(2, addr=0x42) # read 2 bytes from bus
i2c.mem_write(b'\x01\x02', addr=0x42, memaddr=0x10) # write 2 bytes to slave 0x42, memory address 0x10
data = i2c.mem_read(2, addr=0x42, memaddr=0x10) # read 2 bytes from slave 0x42, starting from memory address 0x10
machine.SoftI2C()
:from machine import SoftI2C
# create Software I2C bus as a controller
i2c = SoftI2C(scl=gpios.Pin.gpio20, sda=gpios.Pin.gpio19, freq=400000)
i2c.writeto(0x42, 'hello') # write 5 bytes to slave with address 0x42
i2c.readfrom(0x42, 5) # read 5 bytes from slave
from machine import SoftI2C
# create Software I2C bus as a controller
i2c = SoftI2C(scl=pyb.Pin.cpu.E7, sda=pyb.Pin.cpu.E8, freq=400000) # create software I2C object
i2c.writeto(0x42, 'hello') # write 5 bytes to slave with address 0x42
i2c.readfrom(0x42, 5) # read 5 bytes from slave
from machine import SoftI2C
# create Software I2C bus as a controller
i2c = SoftI2C(scl=pyb.Pin.cpu.E7, sda=pyb.Pin.cpu.E8, freq=400000) # create software I2C object
i2c.writeto(0x42, 'hello') # write 5 bytes to slave with address 0x42
i2c.readfrom(0x42, 5) # read 5 bytes from slave
Storage
flash memory
/flash
and can be used to store small files in addition to boot.py
and main.py
.basic file system operations
/flash
directory content using:import os
print(os.listdir('/flash'))
To create a file and/or write data to it use the open()
function with mode='w'
:
FILENAME = '/flash/test.txt' # any file extension can be used
# create file
file = open(FILENAME, mode='w')
file.write('First line\n') # write the first line to the file
file.close() # always close the file when it is not used anymore
To append data to a file use mode='a'
:
# append data to file
with open(FILENAME, mode='a') as file: # 'w' would over write the data in the file
file.write('Second line\n') # '\n' is the escape sequence for the new line character
To print the content of a file use mode='r'
to open it with read-only access, so you don’t accedentally modify it:
# read data from file
with open(FILENAME, mode='r') as f: # using 'with' the file will be automatically closed afterwards
for line in f.readlines():
print(line)
with open() as f:
makes sure the file is automatically closed after the operation.To delete a file use os.remove()
import os
os.remove('/flash/test.txt')
To create and remove directories you can use os.mkdir(path)
and os.rmdir(path)
, see the documentation below.
For examples on how to test for the presence or absence of files, see the code in the advanced examples
official MycroPython documentation
microSD Card
Important
To use the microSD card, insert it into the slot and mount it using:
import os
os.mount(pyb.SDCard(), '/sd')
# list the SD card content
print(os.listdir('/sd'))
Attention
/flash
, automatically mount the SD card and boot using the files under /sd
./flash
!/flash
./flash
, create a folder or an empty file named SKIPSD
under /flash
:import os
os.mkdir('/flash/SKIPSD')
print(os.listdir('/flash')) # list the current directory content to verify the SKIPSD folder has been created
official MycroPython documentation
Accessing storage over USB
boot.py
:pyb.usb_mode( 'VCP+MSC', msc=(pyb.Flash(),) ) # default setting
Meaning that both the Virtual Com Port for the REPL as well as the Mass Storage Device are enabled on the USB port.
Attention
pyb.usb_mode( 'VCP+MSC', msc=(pyb.Flash(), pyb.SDCard()) )
boot.py
.official MycroPython documentation
pyb.usb_mode()
function
General board control
power-saving sleep mode
For power saving purposes in battery applications you can put the CPU in a low-power state. An external interrupt or an interrupt from the RTC is then needed to wake it up.
pyb.stop() # stop CPU, waiting for external or RTC interrupt
See rtc.wakeup()
to configure a real-time-clock wakeup event, respectively pyb.ExtInt
for external interrupts.
official MycroPython documentation
CPU frequency
You can read the CPU operating frequency, as well as the frequency of the different peripheral buses:
pyb.freq() # get CPU and bus frequencies
pyb.freq(120000000) # set CPU freq to 120MHz
official MycroPython documentation
pyb.freq()
method
miscellaneous functions
You can duplicate the REPL on an UART using pyb.repl_uart()
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
info()
prints lots of information about the board
pyb.info() # print out lots of information about the board
official MycroPython documentation
unique ID
Each microcontroller has a globally-unique ID you can read out to identify a specific board:
pyb.unique_id() # returns a 96 bit microcontroller unique identifier
official MycroPython documentation
pyb.unique_id
method
Advanced examples
external interrupt datalogger
FOLDER = '/sd/' # where the log file will be saved
FILENAME = 'datalog_INT.csv' # log filename, any other file extension such as .log or .txt can be used
INTERRUPT_PIN = input_1 # the input pin triggering the interrupt
DEBOUNCING_THRESHOLD = 20 # debouncing window in ms (determines minimum valid repetition rate)
import os, micropython
micropython.alloc_emergency_exception_buf(100)
last_event = pyb.millis()
# mount sd card if it isn't already
if 'sd' not in os.listdir('/'):
os.mount(pyb.SDCard(), '/sd')
# create a new file to log to if it doesn't already exist
if FILENAME not in os.listdir(FOLDER):
with open(FOLDER+FILENAME, 'w') as f:
f.write('Timestamp;\n') # write column header
# define the callback function
def schedule_log(line):
micropython.schedule(log_event,line)
#define the logger function
def log_event(line):
global last_event
if pyb.elapsed_millis(last_event) > DEBOUNCING_THRESHOLD:
last_event = pyb.millis()
with open(FOLDER+FILENAME, 'a') as f: # 'a' appends data to the file
f.write(rtc.datetime_str()) # appends the timestamp
# attach the external interrupt to input_1
extint_pin = pyb.ExtInt(INTERRUPT_PIN, pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_NONE, schedule_log)
# define function to print the log file content
def print_log():
with open(FOLDER+FILENAME, 'r') as f:
for line in f.readlines():
print(line, end='')
timed ADC datalogger
FOLDER = '/sd/' # where the log file will be saved
FILENAME = 'datalog_ADC.csv' # log filename, any other file extension such as .log or .txt can be used
ADC_PIN = 'A4' # the ADC pin to measure
LOGGING_FREQUENCY = 10 # logging frequency in Hz
import os, micropython
micropython.alloc_emergency_exception_buf(100)
# create the ADC object on the specified pin
adc = pyb.ADC(eval('pyb.Pin.cpu.' + ADC_PIN))
# mount sd card if it isn't already
if 'sd' not in os.listdir('/'):
os.mount(pyb.SDCard(), '/sd')
# create a new file to log to if it doesn't already exist
if FILENAME not in os.listdir(FOLDER):
with open(FOLDER+FILENAME, 'w') as f:
f.write('Timestamp;ADC_value;\n') # write column header
# define the callback function
def schedule_log(tim):
micropython.schedule(log_ADC,tim)
#define the logger function
def log_ADC(tim):
value = str(adc.read())
with open(FOLDER+FILENAME, 'a') as f: # 'a' appends data to the file
f.write(rtc.datetime_str() + ';' + value + ';\n') #
# create timer with interrupt
timer_log = pyb.Timer(1, freq=LOGGING_FREQUENCY, callback=schedule_log)
# define function to print the log file content
def print_log():
with open(FOLDER+FILENAME, 'r') as f:
for line in f.readlines():
print(line, end='')
printing log files
You can print the log file content by calling the function print_log()
defined in both datalogger examples.