MicroPython Pyboard

Today is sunny. _… Let’s write something about MicroPython PyBoard. In my test, I’m using a PyBv1.1, which embeddes a STM32F405RG microcontroller.

Overview

1. Contents In PyBoard

After connecting PyBv1.1 via USB cable, you will possibly see a folder prompt on the screen as follows:

Current Contents In PYBv1.1

PYBv1.1 Properties

2. Test Out picocom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
➜  ~ picocom /dev/ttyACM0
picocom v3.1

port is : /dev/ttyACM0
flowcontrol : none
baudrate is : 9600
parity is : none
databits are : 8
stopbits are : 1
escape is : C-a
local echo is : no
noinit is : no
noreset is : no
hangup is : no
nolock is : no
send_cmd is : sz -vv
receive_cmd is : rz -vv -E
imap is :
omap is :
emap is : crcrlf,delbs,
logfile is : none
initstring : none
exit_after is : not set
exit is : no


FATAL: cannot open /dev/ttyACM0: Permission denied

It looks we need to change the permission of /dev/ttyACM0.

1
2
3
➜  ~ ll /dev/ttyACM0 
crw-rw---- 1 root dialout 166, 0 Jul 9 13:54 /dev/ttyACM0
➜ ~ sudo chmod 777 /dev/ttyACM0

Reconnect…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
➜  ~ picocom /dev/ttyACM0
picocom v3.1

port is : /dev/ttyACM0
flowcontrol : none
baudrate is : 9600
parity is : none
databits are : 8
stopbits are : 1
escape is : C-a
local echo is : no
noinit is : no
noreset is : no
hangup is : no
nolock is : no
send_cmd is : sz -vv
receive_cmd is : rz -vv -E
imap is :
omap is :
emap is : crcrlf,delbs,
logfile is : none
initstring : none
exit_after is : not set
exit is : no

Type [C-a] [C-h] to see available commands
Terminal ready
MicroPython v1.9.4 on 2018-05-11; PYBv1.1 with STM32F405RG
Type "help()" for more information.
>>>

Press Ctrl+A then Ctrl+x, picocom will terminate its execution.

1
2
3
>>> 
Terminating...
Thanks for using picocom

3. Test Out screen

1
➜  ~ screen /dev/ttyACM0

Then you will see a micropython working console as:

1
2
3
1+1
2
>>>

It looks there is NO prompt after login via screen. That’s why I did 1+1 as a test whenever logging in by screen.

Now, let’s press Ctrl+A then Ctrl+d to quit screen.

1
2
3
➜  ~ screen /dev/ttyACM0
[detached from 5561.pts-5.lvision-GT72-6QE]
➜ ~

4. VERY Important

The code typed in the working console from either picocom or screen is corresponding to main.py in PYBFLASH.

Test

1. LED and Switch

The code is directly copied from MicroPython’s homepage.

1
2
3
4
5
6
7
8
9
10
11
12
13
import pyb

sw = pyb.Switch()
led = pyb.LED(4)
x = 0

while True:
if sw():
x = min(255, x+1)
else:
x = max(0,x-1)
led.intensity(x)
pyb.delay(30)

Press the USR switch and take a look what’s going on? _ Interesting, isn’t it?

2. Log of Accelerometer’s Readings

Let’s try out MicroPython’s Example Code : Accelerometer Log with trivial modification.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# log the accelerometer values to a .csv-file on the SD-card

import pyb

accel = pyb.Accel() # create object of accelerometer
blue = pyb.LED(4) # create object of blue LED

log = open('.log.csv', 'w') # open file to write data - /sd/ is the SD-card, /flash/ the internal memory
blue.on() # turn on blue LED

for i in range(100): # do 100 times (if the board is connected via USB, you can't write longer because the PC tries to open the filesystem which messes up your file.)
t = pyb.millis() # get time since reset
x, y, z = accel.filtered_xyz() # get acceleration data
log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file

log.close() # close file
blue.off() # turn off LED

Just press the RST switch, the above piece of code will automatically run once, and the onboard accelerator’s reading will be logged in file log.csv. In my test, 100 readings are logged as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
156,-10,-14,13
157,-20,-28,26
158,-30,-42,39
159,-40,-56,52
161,-40,-56,52
162,-40,-56,52
163,-40,-56,52
164,-40,-56,52
165,-40,-56,52
166,-40,-56,52
167,-40,-56,52
169,-39,-56,53
170,-38,-56,54
171,-37,-56,55
172,-36,-56,56
173,-36,-56,56
174,-36,-56,56
176,-36,-56,56
177,-36,-56,56
178,-36,-56,56
179,-36,-56,56
180,-36,-56,56
181,-36,-56,56
183,-36,-56,56
184,-36,-55,57
185,-36,-54,58
186,-36,-53,59
187,-36,-52,60
188,-36,-52,60
189,-36,-52,60
191,-36,-52,60
192,-36,-52,60
193,-36,-52,60
194,-36,-52,60
195,-36,-52,60
322,-30,-58,58
324,-24,-64,56
325,-18,-70,54
326,-12,-76,52
327,-12,-76,52
328,-12,-76,52
329,-12,-76,52
331,-12,-76,52
332,-12,-76,52
333,-12,-76,52
334,-14,-73,55
335,-16,-70,58
336,-18,-67,61
338,-20,-64,64
339,-20,-64,64
340,-20,-64,64
341,-20,-64,64
342,-20,-64,64
343,-20,-64,64
345,-20,-64,64
346,-20,-64,64
347,-20,-64,64
348,-20,-64,64
349,-18,-67,63
350,-16,-70,62
352,-14,-73,61
353,-12,-76,60
354,-12,-76,60
355,-12,-76,60
356,-12,-76,60
357,-12,-76,60
359,-12,-76,60
360,-12,-76,60
361,-12,-76,60
488,-19,-68,58
489,-26,-60,56
490,-33,-52,54
491,-40,-44,52
492,-40,-44,52
493,-40,-44,52
495,-40,-44,52
496,-40,-44,52
497,-40,-44,52
498,-41,-45,55
499,-42,-46,58
500,-43,-47,61
502,-44,-48,64
503,-44,-48,64
504,-44,-48,64
505,-44,-48,64
506,-44,-48,64
507,-44,-48,64
509,-44,-48,64
510,-44,-48,64
511,-44,-48,64
512,-44,-48,64
513,-43,-47,65
516,-30,-52,59
517,-17,-57,53
518,-2,-64,47
519,12,-72,40
520,14,-74,40
521,16,-76,40
523,16,-76,40
524,16,-76,40

Flash Micropython Onto Pyboard

1. Checkout Micropython Source Code

Let’s FIRST download the NEWEST micropython release. In my case, the MOST up-to-date release is 1.11. (Do NOT use the git version from https://github.com/micropython/micropython.git ).

2. Build Micropython For PYBV11

We’ll strictly follow ports/stm32/README.md to build Micropython.

1
2
3
4
5
6
7
8
9
➜  micropython-1.11 make -C mpy-cross
make: Entering directory '....../micropython-1.11/mpy-cross'
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
GEN build/genhdr/mpversion.h
CC main.c
LINK mpy-cross
text data bss dec hex filename
322105 24864 864 347833 54eb9 mpy-cross
make: Leaving directory '....../micropython-1.11/mpy-cross'

Then we enter subfolder ports/stm32. for further building.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
➜  micropython-1.11 cd ports/stm32 
➜ stm32 make BOARD=PYBV11 deploy
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
mkdir -p build-PYBV11/genhdr
GEN build-PYBV11/genhdr/pins.h
GEN stmconst build-PYBV11/modstm_qstr.h
GEN build-PYBV11/genhdr/mpversion.h
GEN build-PYBV11/genhdr/moduledefs.h
GEN build-PYBV11/genhdr/pybcdc.inf
GEN build-PYBV11/genhdr/pybcdc_inf.h
GEN build-PYBV11/genhdr/pllfreqtable.h
GEN build-PYBV11/genhdr/qstr.i.last
GEN build-PYBV11/genhdr/qstr.split
GEN build-PYBV11/genhdr/qstrdefs.collected.h
QSTR updated
GEN build-PYBV11/genhdr/qstrdefs.generated.h
mkdir -p build-PYBV11/boards/
mkdir -p build-PYBV11/build-PYBV11/
mkdir -p build-PYBV11/drivers/bus/
mkdir -p build-PYBV11/drivers/dht/
mkdir -p build-PYBV11/drivers/memory/
mkdir -p build-PYBV11/extmod/
mkdir -p build-PYBV11/lib/embed/
mkdir -p build-PYBV11/lib/libc/
mkdir -p build-PYBV11/lib/libm/
mkdir -p build-PYBV11/lib/mp-readline/
mkdir -p build-PYBV11/lib/netutils/
mkdir -p build-PYBV11/lib/oofatfs/
mkdir -p build-PYBV11/lib/stm32lib/STM32F4xx_HAL_Driver/Src/
mkdir -p build-PYBV11/lib/timeutils/
mkdir -p build-PYBV11/lib/utils/
mkdir -p build-PYBV11/py/
mkdir -p build-PYBV11/usbdev/class/src/
mkdir -p build-PYBV11/usbdev/core/src/
CC ../../py/mpstate.c
CC ../../py/nlr.c
CC ../../py/nlrx86.c
CC ../../py/nlrx64.c
CC ../../py/nlrthumb.c
CC ../../py/nlrxtensa.c
CC ../../py/nlrsetjmp.c
CC ../../py/malloc.c
CC ../../py/gc.c
CC ../../py/pystack.c
CC ../../py/qstr.c
CC ../../py/vstr.c
CC ../../py/mpprint.c
CC ../../py/unicode.c
...
CC lcd.c
CC accel.c
CC servo.c
CC dac.c
CC adc.c
AS boards/startup_stm32f4.s
CC system_stm32.c
AS resethandler.s
AS ../../lib/utils/gchelper_m3.s
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c
CC ../../lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c
CC usbdev/core/src/usbd_core.c
CC usbdev/core/src/usbd_ctlreq.c
CC usbdev/core/src/usbd_ioreq.c
CC usbdev/class/src/usbd_cdc_msc_hid.c
CC usbdev/class/src/usbd_msc_bot.c
CC usbdev/class/src/usbd_msc_scsi.c
CC usbdev/class/src/usbd_msc_data.c
CC build-PYBV11/pins_PYBV11.c
LINK build-PYBV11/firmware.elf
text data bss dec hex filename
332432 32 27876 360340 57f94 build-PYBV11/firmware.elf
GEN build-PYBV11/firmware.dfu
Writing build-PYBV11/firmware.dfu to the board
Traceback (most recent call last):
File "../../tools/pydfu.py", line 586, in <module>
main()
File "../../tools/pydfu.py", line 566, in main
init()
File "../../tools/pydfu.py", line 97, in init
raise ValueError('No DFU device found')
ValueError: No DFU device found
make: *** [Makefile:442: deploy] Error 1
➜ stm32

3. Load MicroPython on a Microcontroller Board

The above ERROR message is telling that our board is NOT in the DFU mode yet. Therefore, according to the blog
How to Load MicroPython on a Microcontroller Board, we need to make sure P1 (DFU) and 3V3 pin are connected together before flashing.

Note: Before connecting P1 (DFU) and 3V3 pin, make sure power is disconnected from the pyboard.

Now, let’s try it again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  stm32 make BOARD=PYBV11 deploy
Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
Writing build-PYBV11/firmware.dfu to the board
File: build-PYBV11/firmware.dfu
b'DfuSe' v1, image size: 332773, targets: 1
b'Target' 0, alt setting: 0, name: "ST...", size: 332488, elements: 2
0, address: 0x08000000, size: 14824
1, address: 0x08020000, size: 317648
usb: 0483:df11, device: 0x0000, dfu: 0x011a, b'UFD', 16, 0x60c9ebae
Writing memory...
0x08000000 14824 [=========================] 100%
0x08020000 317648 [=========================] 100%
Exiting DFU...
➜ stm32

Let’s try picocom connection again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
➜  stm32 picocom /dev/ttyACM0
picocom v3.1

port is : /dev/ttyACM0
flowcontrol : none
baudrate is : 9600
parity is : none
databits are : 8
stopbits are : 1
escape is : C-a
local echo is : no
noinit is : no
noreset is : no
hangup is : no
nolock is : no
send_cmd is : sz -vv
receive_cmd is : rz -vv -E
imap is :
omap is :
emap is : crcrlf,delbs,
logfile is : none
initstring : none
exit_after is : not set
exit is : no

Type [C-a] [C-h] to see available commands
Terminal ready
MicroPython v1.11 on 2019-07-13; PYBv1.1 with STM32F405RG
Type "help()" for more information.
>>>
Terminating...
Thanks for using picocom
➜ stm32

4. Optional: dfu-util

Due to the Pyboard Firmware Update Wiki, we may also use dfu-util to flash the board.

1
2
3
4
5
6
7
8
➜  ~ sudo dfu-util -l
[sudo] password for lvision:
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/