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.
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?
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:
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.