Programming the Taida Century NRF52832 developer board

Its been a long hiatus regarding this post. At the time I’ve bought a generic eBay/Aliexpress nRF52832 development board (the Taida Century NRF52832 based board) for performing some BLE testing, did some development with Nordic SDK and the NRF Arduino firmware using Platformio, but posted nothing on my blog regarding the tests.
The main trigger for picking up again this board and do some writing about it, is that I’m evaluating RIOT-OS and its capability to target several hardware platforms, namely the NRF52 based chips. Anyway, first the use of the Arduino framework for the NRF52 and platformio:

Programming the NRF52832:
For programming the Taida Century NRF52 board need a programmer supporting the NRF52 chip, that can be either a SEGGER JLink programmer probe (highly recommended), or with a STLink V2 coupled with modified Openocd software, that also does work fine (Recent versions of Openocd already support the NRF52 out of the box). The Blackmagic probe is also an alternative, but since I have now a Jlink probe, never bother again with it.

The hardware connections for programming and debugging:
Since that the board does not have a serial to USB chip and a USB connection, an external TTL to USB serial convert must be used to see any serial output on the computer from the Serial.println commands. Furthermore the USB serial adapter must also must work with the 3.3V used by the NRF52. The 3.3v power can be provided either by the USB serial converter or by the debug probe (but not both at the same time!). I normally use a 6 pin CP2102 USB serial adapters: they work with 3.3v and have all the serial pins exposed.

The Arduino framework for the NRF52 board and specifically for the Taida board variant uses the following pins for serial communication:

RXD – Pin 18
TXD – Pin 19

So the TXD labelled pin on the USB adapter connects to the Pin 18 labelled header on the board (RXD), and the RXD pin on the USB adapter, connects to Pin 19 on the pin header on the board. Ground connects to ground. That settles the serial connection for debugging. The ground pin should also be connected either on the header pin labelled GND on the top left when the IDC connector is on the left, or on the IDC connector itself.

The connections for programming are a bit tricker depending if we are using an STLink programmer or a Segger Jlink programmer. In both cases the power can be provided by the programmer, but with the JLink one, a special connection is also needed so that the SWD debug lines voltage reference used is 3.3v instead of 5v.

Connecting the ST-Link programmer:
Since we are powering up the board from the programmer, and using one of those cheap st-link usb dongles, only four connections are needed:

The USB programmer has a 3.3v output and so can power up the board directly to the 3.3v board pin.

Connecting the JLink probe:
The Jlink probe can only provide 5V output on the JTAG pins, and so while the JTAG pins TCK and TMS can be connected to the TCK and TMS pins on the JTAG connector, the 5V pin must be connected to the VBUS pin on the IDC connector. This pin will provide power to the board and the internal regulator drops it down from 5V to 3.3V. To adjust the logic levels from the probe to 3.3V the JTAG pin VREF must be connected to the IDC pin 3.3V pin, that informs the JLink probe the device target working voltage.
So in total one more connection that with the ST-Link programmer.

The connection diagram is as follows, where the Taida board 12 pin IDC connector is used:

After the connection is done, we can test if we can communicate with the board using the JLinkExe:

JLinkExe -if SWD -device NRF52 -speed 4000
SEGGER J-Link Commander V6.44 (Compiled Mar  1 2019 17:36:52)
DLL version V6.44, compiled Mar  1 2019 17:36:42

Connecting to J-Link via USB...O.K.
Firmware: J-Link V10 compiled Mar  1 2019 16:57:49
Hardware version: V10.10
License(s): FlashBP, GDB

Type "connect" to establish a target connection, '?' for help
Device "NRF52" selected.

Connecting to target via SWD
Found SW-DP with ID 0x2BA03466
Found SW-DP with ID 0x2BA03466
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
AP[1]: JTAG-AP (IDR: 0x02880000)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB00C SCS-M7
ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 003BB002 DWT
ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 002BB003 FPB
ROMTbl[0][3]: E0000000, CID: B105E00D, PID: 003BB001 ITM
ROMTbl[0][4]: E0040000, CID: B105900D, PID: 000BB9A1 TPIU
ROMTbl[0][5]: E0041000, CID: B105900D, PID: 000BB925 ETM
Cortex-M4 identified.

So the JLink probe works just fine.

The above did work, because the JLink probe is programmed to provide 5V power with the power on perm command.

Using Platformio to programm the board:

To program the board, it is necessary to specify correctly the Nordic SoftDevice and for that, the platformio.ini file needs special configuration, namely on the build_flags and build_unflags.

platform = nordicnrf52
board = stct_nrf52_minidev
framework = arduino
lib_deps = 259
build_unflags = -Os, -O1, -O2, -O3, -g1
;upload_protocol = stlink
debug_tool = jlink

With this file, any example from the NRF Arduino Library compiles.


fldigi slow startup on Linux

I installed fldigi on my ne laptop computer, with Arch Linux, and I hit trouble right away: The startup of fldigi on this computer was around 130s until the start command and the ui display. During that time one of the CPU cores hit 100% and stayed there. Not acceptable.
On my desktop computer, that is much older and has at least less than half the processing power of the new laptop, fldigi started up right away and I had no issues with CPU occupation.

It took me a while to find out the cause, and with the source code available (yay for open source) I’ve found the issue at the confdialog.cxx file specifically here:

Fl_Double_Window* ConfigureDialog() {
  Fl_Double_Window* w; 
  font_browser = new Font_Browser;

A lot of the time was lost inside the call to the new Font_Browser.

So I’ve checked the fonts installed on my new computer, and low and behold: 1248 more or less fonts !!! compared to 234 installed fonts on my desktop computer.

Comparing the Arch Linux packages that I had installed on one computer and on the other, the laptop had the ttf-google-fonts-git AUR package installed that added the bulk of all the fonts.

Removing this package solved the issue with fldigi startup delay. With the fonts removed fldigi started right away as soon I execute the command to start it up.

Self hosted mobile phone push notifications

Google cloud messaging (GCM), Pushbullet, among others, allows to notify users though their mobile phone or portable device for events that where trigger either, programmatically or by any other mean.

A nice self hosted solution that does not depend in form of third party services, and as far as I can see is being actively developed, is Gotify that offers a self hosted server, and mobile application for Android.

Gotify offers a docker images (and unfortunately in the last few days they stopped producing the Docker image for Raspberry Pi), that allows to have a running Gotify server in less than 2 minutes.

Anyway, I’m still running the latest docker image for the RPI. Since I have already running something at the HTTP port 80, I’ve started the Gotify container with an alternate port:

docker run -p 1080:80 -v /var/gotify/data:/app/data gotify/server-arm7

After docker pulls the image and starts it up, we can access the Notify Web Server interface at http://rpi:1080/ and access it with the default user/password admin/admin.

The first thing that we need to do is to change the default admin password and add an application. Both steps are straight forward.

The key aspect for the application after it is created is to take notice of the application token. This token will be necessary for inject messages on Gotify and associate the injected message to the application. Also there is the possibility to associate an icon to the application, that also be shown on the mobile application, by pressing the pen icon and adding an image.

After this, to inject a message from anywhere we can use CURL:

curl -X POST "http://rpi:1080/message?token=AhV-43qgmkKSj07" -F "title=RPI" -F "message=Status Alert"
{"id":16,"appid":2,"message":"Status Alert","title":"RPI","priority":0,"date":"2019-02-25T12:13:35.777531495Z"}

Anyway, to make things short, Gotify works more or less well. I still have some issues with the web interface and with the mobile application, but those issues might be associated to being using an older version of the server.

Synology reverse proxy and websockets
Gotify uses websockets as the transport medium for the push notifications.

As a final note, since I’m using the Synology reverse proxy to access the Gotify server from the internet, some special configuration must be done so that the Synology reverse proxy let’s websockets to “pass through” to the Gotify server.

Basically we need on to go to Control Panel -> Application Portal -> Reverse Proxy and create our rule that maps out the Gotify server to the external URL. I’ve create something like to be pointing to the internal Gotify server http://rpi:1080:

The important bit is that after creating the reverse proxy rule, we must edit and add the support for websockets by going to Custom Header and press the Create -> WebSocket button.

And that’s it. We have now a self hosted notification system. We can now, for examble, by using Node-Red or bash scripts, to start sending notifications to our clients when important events happen.

Lorawan/TTN with the TTGO ESP32 board

So I’m testing my TTGO Lora32 board with the RIOT-OS operating system to connect to the The Things Network, and while at first I had some success, then out of the blue things didn’t worked anymore.

The code that I’m using is based on the standard RIOT-Os Loramac example but with supporting code for ABP instead of the OTA activation.

The code is available at this Github repository.

Since I saw no activity on any channel for the Lora transmission by using the RTLSDR dongle, I suspected that something was up.
The Arduino based code from for connecting to TTN using Lorawan worked fine, and so it excluded an issue with the hardware.

By going to RIOT-OS installation directory, under drivers and on the sx127x directory, I’ve enabled on th sx127x.c file the debug to 1, since enabling debug on the semtech_loramac.c file held no useful information:

#define ENABLE_DEBUG (1)

With debug enabled, lo and behold, at startup:

2019-01-22 14:11:02,993 - INFO # [sx127x] error: failed to initialize SPI_0 device (code -1)
2019-01-22 14:11:02,993 - INFO # [sx127x] error: failed to initialize SPI

This is rather strange since at the initial tests the sx127x was detected and worked.
The only thing that changed is that I periodically update the RIOT local repository, and checking my board definition with other ESP32 boards that have a sx127x transceiver, the way that the pins where declared were quite different from what I had initially.

So I’ve changed the way that the pins for the SPI and the sx127x peripheral where defined, and the result:

2019-01-22 14:28:00,847 - INFO #  -> Node activation by: ABP
2019-01-22 14:28:00,847 - INFO # [sx127x] SPI_0 initialized with success
2019-01-22 14:28:00,848 - INFO # Set ABP information.

And the data arrives at TTN without any issue:

So either I had initially had the pins for SPI and the sx127x defined wrong or the latest RIOT build changed the way pins where defined.

A more complete example, working with multiple threads, is also available at this Github repository.

SDRPlay, CubicSDR on Arch Linux

This is just a simple post for writing the instructions for installing and using SDRPlay RSP1A (Should work for other versions) and CubicSDR on Arch Linux. I’ve previously installed most of the supporting software manually on my PC, and also had trouble installing the SDRPlay driver on Arch Linux with the SDRPlay installer on my PC. Since I have a lot of QRM (Noise) in my home, the next step was to use a portable computer to move the SDRPlay outside.

So, the following instructions are much more streamlined, since all the required software is on the AUR repositories, and so no “hacking” is needed.

Installing yay AUR package manager
If necessary we should install a AUR package manager. There are several ones, but as far as I’m aware, for now the yay is the currently maintained AUR package manager:

git clone
cd yay
makepkg -si

We can now use yay.

Installing CubicSDR with SDRPlay support:
If before installing CubicSDR we install HamLib support we will have a new menu on CubicSDR for rig control, otherwise it wont appear.
Then we need to install the SDRPlay driver, Soapy support and also CubicSDR.

yay -S hamlib
yay -S libsdrplay
yay -S soapysdr-git
yay -S soapysdrplay-git
yay -S soapyremote-git
yay -S soapyrtlsdr-git
yay -S cubicsdr-git

I’ve also added support for remote devices and the ubiquitous RTLSDR dongles.
CubicSDR will take a while (20 minutes, it will depend how fast is your computer) to compile, mainly because of the wxgtk widgets.

After it ends just connect the SDRPlay to the computer USB port, and execute CubicSDR. If the SdrPlay does not appear on the device list, press the Refresh button:

And that’s it, no fuss install, at least for me.

Docker container web interface – Portainer and Riot-OS Development

This post is a follow up of starting up with RIOT-OS. To be able to develop with RIOT-OS an easy (and easier) way to do so is just to install docker and web UI docker interface Portainer to control docker.

So we will install Docker, Portainer, and finally the RIOT-OS building environment.

Installing Docker and Portainer, is an initial stepping stone for using the dockerized development environment for RIOT-OS, since I don’t want to install all the development environments in my machine.

Installing Docker:
On Arch-Linux is as simple as installing the Docker package using pacman, enabling the services and rebooting.
Basically we need to run, as root the following commands:

pacman -S docker
systemctl enable docker.service

After rebooting the following command should return some information

docker info

A sample output is:

Containers: 2
 Running: 0
 Paused: 0
 Stopped: 2
Images: 9
Server Version: 18.09.0-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog

Installing Portainer
Installing the Docker Portainer Web UI is as simple as:

docker pull portainer/portainer

To run Portainer a set of complete instructions on this page, but basically on the simplest way is:

$ docker volume create portainer_data
$ docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

We can now check if the docker image is up:

$ docker ps
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                    NAMES
7a38ae7fc922        portainer/portainer   "/portainer"        4 seconds ago       Up 3 seconds>9000/tcp   portainer

Since I have already ran the Portainer container, the initial setting up steps when accessing the URL HTTP://localhost:9000 do not appear, but we need to choose:

  1. A set of credentials to use as de administrator for portainer
  2. The local machine registry to connect to the local docker containers.

1- At initial access we define an user and password:

Portainer Credentials

2- Then we connect to our local docker instance:
Portainer Local Docker

Press Connect and then we can now access our Docker instance from Portainer:
Portainer Main Screen

Pressing the Local Docker Connection we can now manage our docker resources.

Installing the build environment for RIOT-OS
We can do it by two ways:

From the command line:

docker pull riot/riotbuild

or use Portainer:

This container is very big, so we need to wait some time for the container image download. The command line shows in greater detail the download process.

After the image is downloaded, we can follow these instructions for building our apps using the docker container as the build environment.

After the image is installed:

To use is is as simple as going the the examples directory and do:


From this we are now able to build based RIOT-OS applications for several targets, including the ESP8266/ESP32.

As we can see we even don’t need to have a running container, just the image.

A simple start with the RiotOS operating system for IoT devices

The RiotOS operating system is an Open Source operating system that targets different embedded platforms while allowing to use the same code base for some aspects of IoT development: Connectivity, protocols and security. It also supports other key aspects such as threads, Inter process communication, synchronization support on the kernel side. It also supports several communications protocols, suche BLE, 6LoWPAN, Lorawan, and so on.

At the target level for the RiotOS operating system, RiotOS supports a wide scope of different platforms, including a special native platform. What does this means? It means that within certain limitations, it is entirely possible to develop an IoT application that runs where the code is developed, this includes our PC and any SBC such as the RaspberryPI. This support opens a new window of opportunities where it is possible to integrate different classes of devices, such as Arduino, STM32 and RPI while leveraging the knowledge on the same supporting code base.

How to start:

This is a very quick start instructions for building a native demo application with network support. As usual all the instructions apply to a Linux Operating system, in my case Arch Linux.

Clone the RiotOS repository:

Just run:

cd /opt
git clone

I’ve chosen the /opt directory for the sake of example.

Compile one the example application:

All example applications are under the example applications.
In each directory, there is a Makefile file with a specific content.

For example on the examples/default there is Makefile that targets the native environment.

Of key interest is the line in this file that defines the target board:

BOARD ?= native

If the BOARD variable is not defined on the running environment it will use the native board.

We just need now to run the make command:

[pcortex@pcortex:default|master]$ make
Building application "default" for "native" with MCU "native".

"make" -C /opt/RIOT/boards/native
"make" -C /opt/RIOT/boards/native/drivers
"make" -C /opt/RIOT/core
"make" -C /opt/RIOT/cpu/native
"make" -C /opt/RIOT/sys/shell
"make" -C /opt/RIOT/sys/shell/commands
   text    data     bss     dec     hex filename
  88189    1104   72088  161381   27665 /opt/RIOT/examples/default/bin/native/default.elf

We can see that the compilation output was placed at /opt/RIOT/examples/default/bin/native/default.elf.

But if we ran the default.elf executable, we get:

[pcortex@pcortex:default|master]$ bin/native/default.elf 
usage: bin/native/default.elf  [-i ] [-d] [-e|-E] [-o] [-c ]
 help: bin/native/default.elf -h

    -h, --help
        print this help message
    -i , --id=
        specify instance id (set by config module)
    -s , --seed=
        specify srandom(3) seed (/dev/random is used instead of random(3) if
        the option is omitted)
    -d, --daemonize
        daemonize native instance
    -e, --stderr-pipe
        redirect stderr to file
    -E, --stderr-noredirect
        do not redirect stderr (i.e. leave sterr unchanged despite
        daemon/socket io)
    -o, --stdout-pipe
        redirect stdout to file (/tmp/riot.stdout.PID) when not attached
        to socket
    -c , --uart-tty=
        specify TTY device for UART. This argument can be used multiple
        times (up to UART_NUMOF)

A little side note, under bin there is a native directory but if we target the compilation to a different platform, a new directory under bin will be created to that platform.

Returning to result to the above command, we notice that the command requires a TAP (terminal interface point) interface. The fact is that the RiotOS code to access the network resources of the hosting operating system doesn’t access the network interface directly, but does it through the TAP interface. We can create only one TAP interface, or several TAP interfaces, which in such case, means that we can have several RiotOS applications using an TAP based network to communicate between themselves and also with the external network. Neat!

RiotOS offers a script to the TAP intefaces, but before running the script, just make sure if any Linux operating system Kernel was done recently, a reboot migh be needed to the interfaces be successfully created.

[pcortex@pcortex:RIOT|master]$ ip a

1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp6s0:  mtu 4000 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:24:8c:02:dd:7e brd ff:ff:ff:ff:ff:ff
    inet brd scope global noprefixroute enp6s0
       valid_lft forever preferred_lft forever
    inet6 fe80::224:8cff:fe02:dd7e/64 scope link 
       valid_lft forever preferred_lft forever

Now we run the tapsetup script that creates the TAP interfaces. This script when called without any parameters, it creates two TAP interfaces. If we pass the -c argument with a number, for example -c 4, it will create 4 TAP interfaces. The -d parameter deletes all interface that where created.

[pcortex@pcortex:tapsetup|master]$ pwd
[pcortex@pcortex:tapsetup|master]$ sudo ./tapsetup 
creating tapbr0
creating tap0
creating tap1
[pcortex@pcortex:tapsetup|master]$ ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp6s0:  mtu 4000 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:24:8c:02:dd:7e brd ff:ff:ff:ff:ff:ff
    inet brd scope global noprefixroute enp6s0
       valid_lft forever preferred_lft forever
    inet6 fe80::224:8cff:fe02:dd7e/64 scope link 
       valid_lft forever preferred_lft forever
8: tapbr0:  mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 2e:bd:d8:88:64:55 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::2cbd:d8ff:fe88:6455/64 scope link 
       valid_lft forever preferred_lft forever
9: tap0:  mtu 1500 qdisc fq_codel master tapbr0 state DOWN group default qlen 1000
    link/ether 9a:a0:bc:fa:c7:61 brd ff:ff:ff:ff:ff:ff
10: tap1:  mtu 1500 qdisc fq_codel master tapbr0 state DOWN group default qlen 1000
    link/ether 2e:bd:d8:88:64:55 brd ff:ff:ff:ff:ff:ff

We can see that both tap0 and tap1 where created and are down.

Within two different windows we can run the default.elf with each interface now:

Window one: > sudo ./default.elf tap0
Window two: > sudo ./default.elf tap1

The two instances will start communicate and the tap interface have addresses and are up now.

11: tapbr0:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 0e:db:a6:77:3b:e5 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::cdb:a6ff:fe77:3be5/64 scope link 
       valid_lft forever preferred_lft forever
12: tap0:  mtu 1500 qdisc fq_codel master tapbr0 state UP group default qlen 1000
    link/ether 0e:db:a6:77:3b:e5 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::cdb:a6ff:fe77:3be5/64 scope link 
       valid_lft forever preferred_lft forever
13: tap1:  mtu 1500 qdisc fq_codel master tapbr0 state UP group default qlen 1000
    link/ether be:65:4f:4d:a0:ed brd ff:ff:ff:ff:ff:ff
    inet6 fe80::bc65:4fff:fe4d:a0ed/64 scope link 
       valid_lft forever preferred_lft forever

The above is a simple example, but RiotOS offers several examples including COAP, MQTT-SN and OpenThread examples.

The next step is to test RiotOS on ESP8266 and ESP32.