Post

ENG | nRF52840 Dongle and MicroPython

Very simple guide for using MicroPython and nRF52840 Dongle (PCA10059). Sadly Bluetooth LE does not work.

ENG | nRF52840 Dongle and MicroPython

In the last article, we learned how to upload blinky. But somehow there is MicroPython version for this gadget, which can be downloaded here:

https://micropython.org/download/PCA10059/

And surprise, it’s possible to create ZIP file and upload it to dongle:

Download and flash MicroPython firmware

1
2
3
4
wget https://micropython.org/resources/firmware/PCA10059-20250415-v1.25.0.hex
nrfutil pkg generate --hw-version 52 --sd-req=0x00 --application-version 1 --application PCA10059-20250415-v1.25.0.hex PCA10059-20250415-v1.25.0.zip
# Don't forget (as always 😜) to put device into boot loader mode
nrfutil dfu usb-serial -pkg PCA10059-20250415-v1.25.0.zip -p /dev/ttyACM1

Try Python shell (REPL)

1
minicom -D /dev/ttyACM1
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
Welcome to minicom 2.9

OPTIONS: I18n
Compiled on Jan 17 2025, 00:00:00.
Port /dev/ttyACM1, 13:58:33

Press CTRL-A Z for help on special keys

MicroPython v1.25.0 on 2025-04-15; PCA10059 with NRF52840
Type "help()" for more information.

>>> help()
Welcome to MicroPython!

For online docs please visit http://docs.micropython.org/

Quick overview of commands for the board:
  board.LED(n)    -- create an LED object for LED n (n=1,2,3,4)

Control commands:
  CTRL-A        -- on a blank line, enter raw REPL mode
  CTRL-B        -- on a blank line, enter normal REPL mode
  CTRL-D        -- on a blank line, do a soft reset of the board
  CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)

>>> import board
>>> l1 = board.LED(1)
>>> l1.on()
>>> l2 = board.LED(2)
>>> l2.on()
>>> l3 = board.LED(3)
>>> l3.on()
>>> l2.off()
>>> board.LED(4).on()
>>> import time
>>> time.ticks_ms()
7286588
>>> import sys
>>> sys.platform
'nrf52840-Dongle'
>>> sys.implementation
(name='micropython', version=(1, 25, 0, ''), _machine='PCA10059 with NRF52840', _mpy=7942, _build='PCA10059')

Exit minicom using Ctrl+A X.

Side note: LEDs on nRF52840 Dongle

I haven’t decoded how these work. There is documentation stating this

PartDescriptionGPIO
LD1GreenP0.06
LD2RedP0.08
LD2GreenP1.09
LD2BlueP0.12

The LEDs are active low, which means that writing a logical zero ‘0’ to the output pin will illuminate the LED.

But my effects of lx = board.lED(x), px = machine.Pin(x, Pin.OUT) are

LED(lx)Pin(px)When lx.on() or px.off()
16Right yellowish-green LED is on
28Left green LED is on, unless L4 is on
341Left red LED is on, unless L2 or L4 is on
412Left LEDs are off

Here it seems that documentation is wrong about green and red pins and whole behavior is weird.

Note: P1.09 corresponds to pin 1*32+9=41

Uploading program

Raspberry Pi Pico has Visual Studio Code extension called MicroPico. I’m not sure if it works (I suppose not), so I found out another tool: mpremote.

1
pip install mpremote

Useful commands are:

1
2
3
4
5
6
mpremote connect /dev/ttyACM1 # Connect to shell (just like minicom)
mpremote a1                   # Alias for above
mpremote a0 ls                # List files on a device connected to /dev/ttyACM0
mpremote a1 fs cp test.py :   # Copy file to device root directory (filesystem copy)
mpremote a1 run test.py       # Run that file
mpremote a1 fs rm :test.py    # Remove that file

Reality check

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[pavel@marten -=- /home/pavel/Downloads]$ mpremote a1 ls
ls :
[pavel@marten -=- /home/pavel/Downloads]$ mpremote a1 fs cp ble_peripheral2.py : && mpremote a1 run ble_peripheral2.py
cp ble_peripheral2.py :
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ImportError: no module named 'bluetooth'
[pavel@marten -=- /home/pavel/Downloads]$ mpremote a1
Connected to MicroPython at /dev/ttyACM1
Use Ctrl-] or Ctrl-x to exit this shell
import bluetooth
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: no module named 'bluetooth'
>>> %
[pavel@marten -=- /home/pavel/Downloads]$ mpremote a1 ls
ls :
        3145 ble_peripheral2.py
[pavel@marten -=- /home/pavel/Downloads]$ mpremote a1 fs rm :ble_peripheral2.py
rm :ble_peripheral2.py
[pavel@marten -=- /home/pavel/Downloads]$ mpremote a1 ls
ls :

Conclusion

This was surprisingly easy. Except there is sadly no support for standard bluetooth micropython module (as of 2025-06-08 and MicroPython 1.25), which is critical for this piece of hardware. Neither ubluepy or ble which I found on Seeed Xiao with the same chip and which are basically useless anyways - I mean for Bluetooth LE.

Bluetooth LE works with Zephyr RTOS, which is requires programming in C.

In my opinion, combination of either nRF52840 Dongle or XIAO nRF52840 and MicroPython is almost priceless. With exception of rapid prototyping and debugging. Raspberry Pi Pico 2 W costs roughly half and works way better.

This post is licensed under CC BY 4.0 by the author.