balenaOS on the Advantech AIR-020X

Last week I posted the review of the Advantech AIR-020X with which I used to create the labSentinel 2 system.

I remarked that the hardware was great, however the software support and update capability of the system was severly lagging behind for an "industrial floor, always on" type of machine. Luckily, thats exactly what balena has been created for.

Even better, their environment already support Nvidia Jetson devices - also Nvidia Jetson Xavier NX modules. With the AIR-020X being a really nice carrierboard (and housing) for this module, I went to work.

Spoiler Alert - it works!

Installing balenaOS on the AIR-020X

1.) I setup an Ubuntu 20.04 LTS machine, installed npm and setup jetson-flash

2.) I went to https://www.balena.io/os and downloaded the latest NVIDIA JETSON XAVIER NX DEVKIT EMMC image (2.107.10) in the development version.

3.) Unzip the file after setting up jetson-flash and getting your AIR-020X into recovery mode. This means opening the bottom of the case by unscrewing the 4 philipps head screws, connecting the Micro USB port of the AIR-020X with your Ubuntu host computer, applying power to the AIR-020X, but do not yet press the power switch.

4.) There is foil/recovery switch next to the Micro USB connector and LAN port. You need to press and hold this switch and at the same time press the power on button of the unit for about 4 seconds.

5.) On Ubuntu, run lsusb | grep Nvidia - this should return a similar line to this

Bus 003 Device 005: ID 0955:7023 NVIDIA Corp. APX

Import is the ending "APX", which means it is in recovery mode.

6.) Now you can start the flash process

user@balenaTest:~/jetson-flash$ ./bin/cmd.js -f ./jetson-xavier-nx-devkit-emmc-2.107.10-v14.4.4.img -m jetson-xavier-nx-devkit-emmc

The .img value points to the unzipped image file, the -m tells the jetson-flash tool that we are running a Xavier NX system and want to install balenaOS on the internal eMMC module.

7.) This will now start the process which will take some minutes and also ask you for your sudo password. At the end you should see something like this:

[ 255.8670 ] Flashing completed

[ 255.8670 ] Coldbooting the device
[ 255.8696 ] tegrarcm_v2 --ismb2
[ 255.9454 ]
[ 255.9502 ] tegradevflash_v2 --reboot coldboot
[ 255.9530 ] Bootloader version 01.00.0000
[ 255.9984 ]
*** The target t186ref has been flashed successfully. ***
Reset the board to boot from internal eMMC.

8.) As soon as you reboot the device, you will be greeted with the balenaOS logo and can use it as any other balenaOS device.

Adding the AIR-020X to a fleet

If you want to use it e.g. in a fleet, I would recommend creating a new one with the device type Nvidia Jetson Xavier. This is important to allow sample projects to correctly work, as its basically the same thing as the more specialized version "jetson-xavier-nx-devkit-emmc" - but most demo projects just implement the former one :).

To now join the installed device onto your new fleet, download and install balenaCLI - login to your balena Cloud account and do a balena scan using balenaCLI to find your AIR-020X on the network.

-
  host:          56e1ef3.local
  address:       192.168.178.112
  osVariant:     development
  dockerInfo:
    Containers:        1
    ContainersRunning: 1
    ContainersPaused:  0
    ContainersStopped: 0
    Images:            1
    Driver:            overlay2
    SystemTime:        2023-03-10T14:05:52.568438957Z
    KernelVersion:     4.9.253-l4t-r32.7
    OperatingSystem:   balenaOS 2.107.10
    Architecture:      aarch64
  dockerVersion:
    Version:    20.10.17
    ApiVersion: 1.41

After that, you can easily join this device with

.\balena join 192.168.178.112
? Select fleet <yourFleetNameToSelect>
? Check for updates every X minutes 10
[Success] Device successfully joined balena-cloud.com!

... and voila, its online!

What does work?

Testing GPIO pins with a multimeter

The AIR-020X has a lot of custom GPIO chips, 2x RS485/RS232 interface, 1x CANbus interface, a second network interface and even a NVMe. Luckily, everything just works out of the box.

- HDMI works
- USB works
- onboard network card (dmesg + dhcp test, gets ip / works)
[   29.231807] eqos 2490000.ether_qos eth0: Link is Up - 1Gbps/Full - flow control rx/tx

- 2nd network card (dmesg + dhcp test, get ip / works)
[  104.307175] igb 0004:05:00.0 enP4p5s0: igb: enP4p5s0 NIC Link is Up 1000 Mbps Full Duplex, Flow 
- NVMe is recognized (lsblk)
nvme0n1      259:0    0 119.2G  0 disk
|-nvme0n1p1  259:1    0    96G  0 part
|-nvme0n1p2  259:2    0    64M  0 part
|-nvme0n1p3  259:3    0    64M  0 part
|-nvme0n1p4  259:4    0   448K  0 part
|-nvme0n1p5  259:5    0   448K  0 part
|-nvme0n1p6  259:6    0    63M  0 part
|-nvme0n1p7  259:7    0   512K  0 part
|-nvme0n1p8  259:8    0   256K  0 part
|-nvme0n1p9  259:9    0   256K  0 part
|-nvme0n1p10 259:10   0   300M  0 part
`-nvme0n1p11 259:11   0  22.8G  0 part
- can bus interface is auto loaded on boot (see ifconfig -a)
can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          NOARP  MTU:16  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:63
- gpio/dio, works, but bit3 does sadly not work
( more info: http://ess-wiki.advantech.com.tw/view/File:AIR-020-nVidia_GPIO.docx )
Pin Number AIR-020X AIR-020T AIR-020N
GPIO bit1 	393 	269 		38
GPIO bit2 	421 	425 		149
GPIO bit3 	265 	411 		65
GPIO bit4 	424 	264 		168
GPIO bit5 	418 	476 		202
GPIO bit6 	436 	396 		246
GPIO bit7 	417 	337 		169
GPIO bit8 	268 	338 		194

# set bit 1 as GPIO pin
echo 393 > /sys/class/gpio/export
# get value 0=low, 1=high
cat /sys/class/gpio/gpio393/value
# set direction out or in
echo out > /sys/class/gpio/gpio393/direction
# get direction
cat /sys/class/gpio/gpio393/direction
out
# set value on out pin
echo 1 > /sys/class/gpio/gpio393/value

test:
# 265, bit3 did not work on export
echo 393 > /sys/class/gpio/export
echo 421 > /sys/class/gpio/export
echo 265 > /sys/class/gpio/export
echo 424 > /sys/class/gpio/export
echo 418 > /sys/class/gpio/export
echo 436 > /sys/class/gpio/export
echo 417 > /sys/class/gpio/export
echo 268 > /sys/class/gpio/export

echo out > /sys/class/gpio/gpio393/direction
echo out > /sys/class/gpio/gpio421/direction
echo out > /sys/class/gpio/gpio265/direction
echo out > /sys/class/gpio/gpio424/direction
echo out > /sys/class/gpio/gpio418/direction
echo out > /sys/class/gpio/gpio436/direction
echo out > /sys/class/gpio/gpio417/direction
echo out > /sys/class/gpio/gpio268/direction

echo 1 > /sys/class/gpio/gpio393/value
echo 1 > /sys/class/gpio/gpio421/value
echo 1 > /sys/class/gpio/gpio265/value
echo 1 > /sys/class/gpio/gpio424/value
echo 1 > /sys/class/gpio/gpio418/value
echo 1 > /sys/class/gpio/gpio436/value
echo 1 > /sys/class/gpio/gpio417/value
echo 1 > /sys/class/gpio/gpio268/value
- com ports, running as RS-232 or RS-485 (not tested, but recognized)
( more info: http://ess-wiki.advantech.com.tw/view/AIR-020-RS-485 )
root@56e8bf3:/# ls /dev/ | grep ttyTH
ttyTHS0 <- COM1
ttyTHS1 <- COM2
ttyTHS4

More info to the hardware can be found in the Advantech Wiki.

GPU Demos

Last but not least I want to point you towards the nice balena Jetson tutorial which can be found here.

It will help you getting started with Jetson samples that are hosted here.

In the end I was able to also get CUDA acceleration to work and see this smoke demo:

Nothing like some GPU accelerated smoke

With that I am closing this post. It was surprisingly easy to get this device to work - the only thing left would be to get it to boot and to work from its internal NVMe storage, but other than that its a nice tool for working with GPU workloads like Edge Impulse.

gpsTime

I think there is nothing more pleasing than having extremely precise measurements at your fingertips. Like time. While in the past it was quite problematic to measure time accurately (not talking about sundials, but... why not? ;)) - mankind has created one precise time source as the byproduct (read: "waste") for usage in accurate navigation: GNSS and their different kinds like GPS, Glonass, Galileo, BaiDou and others.

Taping into this time source and providing it to your local computer network via NTP has been done by countless people and is an extreme rewarding task. Is it necessary? Maybe not. Is it really cool? Yes. And now it is even easier as you don't need to configure it yourself, but can use the balenaHub and the preconfigured gpsTime project.

We do not waste time on fancy logos 😉

Basically you just need an RPi B+ (2/3/4), Micro SD Card, Powersupply and 3v3 TTL Level GPS Module with PPS Output. The rest is just done by going on the balenaHub entry shown above, creating a free account and flashing balenaOS onto your SD card, booting the RPi on the internet for the first time and let it get the needed containers. Afterwards you can use the RPi offline and still enjoy your precise time source.

A watterott CQM-M8Q Breakout and an good old RPi 2B+ are more than powerful enough

More details can be found in the Github Repo and you can work and improve that project to your hearts content. I am probably going to do an PiAndMore talk about it - and use the project myself as a block for precise timing in some support equipment.