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

By accident I found that mpremote itself works on Windows and COM port does not need to be specified (at least if there is only one present).

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 modules which I found on Seeed Xiao with the same chip are available. And they are basically useless anyways - I mean for Bluetooth LE.

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

In my opinion, combination of either nRF52840 Dongle or XIAO nRF52840 and MicroPython makes very little sense - strength of this microprocessor is BLE, which is currently not supported. I have not tried low power modes yet though, it may be good for data logger, but it’s a bit too expensive and there are likely better options. Or just use Zephyr RTOS.

Raspberry Pi Pico 2 W costs roughly half and at time of writing, it has better support (wifi and BLE works).

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