Improve this doc

I2C and Other Interfaces

Raspberry Pi Family

Many sensors and peripherals use either the I²C (Inter-Integrated Circuit) or the SPI (Serial Peripheral Interface) to communicate with the CPU. In most linux environments, using this kind of low level communication requires enabling a kernel module. In balena containers this can be done in a similar way because the containers are run in --privileged mode.

I2C

I2C is enabled by default in BalenaOS via the dtparam=i2c_arm=on device tree parameter used on RaspberryPi devices. The i2c-dev module is loaded by the kernel automatically on startup. To access /dev/i2c-* char device files from a multi-container application, you can either list each file in your docker-compose.yml using device mappings:

services:
  my-service:
  ...
    devices:
      - "/dev/i2c-1:/dev/i2c-1"

or mark the container as privileged if you want to have all /dev/ nodes bind-mounted inside the container:

services:
  my-service:
  ...
    privileged:true

Single-container fleets run in privileged mode by default. If security and sandboxing are required then a multicontainer release should be created, even if only a single service is required.

To get you started, here is an example project that supports a variety of i2c sensors to build your own monitoring system for your environment and visualize data from a remote dashboard.

SPI

SPI is enabled by default on balenaOS via the dtparam=spi=on device tree parameter. This default behavior can be modified by editing the device configuration.

For Node.js applications it should work out of the box with the spi node module. For an example of this, check out this project: digitiser.

Serial

Serial is disabled by default on the Raspberry Pi 3. To enable it you will need to do the following:

  • Edit the config.txt in balena-boot partition of the SD card and append the following lines.
enable_uart=1

1-wire and Digital Temperature sensors

In order to work work with 1-wire and digital temperature sensors you will need to do the following:

  • Edit the config.txt in balena-boot partition of the SD card and append the following lines.
dtoverlay=w1-gpio
  • Add modprobe w1-gpio && modprobe w1-therm before your start scripts in either your package.json start command or Dockerfile CMD command.

An example of this is shown in our Firebase Temperature Logger project.

Using UART or Serial on Raspberry Pi 3

To enable UART on GPIO14 / UART0 TX and GPIO15 / UART0 RX , you will need to apply the pi3-miniuart-bt device tree overlay. This can be done in two ways:

  1. Add the following Device (or Fleet) Configuration variable to your device (or Fleet).

    BALENA_HOST_CONFIG_dtoverlay = pi3-miniuart-bt
  2. The second, more manual way to enable this configuration is to mount the SD card on your development machine. Find the resin-boot partition and in there you should see the Raspberry Pi's boot files, one of which is called config.txt. Open this file up and add the following line to the end of the file:

    dtoverlay=pi3-miniuart-bt

Now eject the SD card and pop it back into the RPI3, and you can boot the device up again.

To demonstrate this functionality, you can push this project (https://github.com/balena-io-playground/rpi3-uart) to your RPI3. You will also need to add a small jumper wire between GPIO14 / UART0 TX and GPIO15 / UART0 RX, so that the data sent out of the UART is read back in and displayed in the logs.

Raspberry Pi camera module

Depending on the version of your balenaOS, the system contains different version of the Raspberry Pi firmware, and you need to apply slightly different settings. In both cases you can either modify config.txt on the resin-boot partition of your SD card, or add the settings remotely by using BALENA_HOST_CONFIG_variablename settings in your fleet or device configuration.

BalenaOS 1.16.0 and newer

Set the following values in config.txt:

gpu_mem=128
start_x=1

or for remote update

  • BALENA_HOST_CONFIG_gpu_mem to 128
  • BALENA_HOST_CONFIG_start_x to 1 in the fleet or device configuration.

BalenaOS 1.8.0 and earlier

Set the following values in config.txt:

gpu_mem=128
start_file=start_x.elf
fixup_file=fixup_x.dat

or for remote update

  • BALENA_HOST_CONFIG_gpu_mem to 128
  • BALENA_HOST_CONFIG_start_file to start_x.elf
  • BALENA_HOST_CONFIG_fixup_file to fixup_x.dat in the fleet or device configuration.

You will also need to add modprobe bcm2835-v4l2 before your start scripts in either your package.json start command or Dockerfile CMD command.

An example of this is shown in our Raspberry Pi python picamera project.

Raspberry Pi 7” Touchscreen Display

In order to work with the Raspberry Pi display you will need to do the following:

  • Edit the config.txt in resin-boot partition of the SD card and append the following line.
device_tree_overlay=rpi-ft5406-overlay.dtb

If you want a quick example project to get you started with you new screen, you might want to checkout our Raspberry Pi Electron starter App.

If you find that you need to change the orientation of you LCD screen, you can easily achieve this by adding the following key/value to your /boot/config.txt on your SD card:

lcd_rotate = 0

And set the value to either 0, 90, 180 or 270, depending on your desired orientation.

Note: The 90 and 270 degrees rotation options require additional memory on GPU, so won't work with the 16M GPU split.

Customizing config.txt

These are some tips and tricks for customizing your raspberry pi. Most of them require changing settings in the config.txt file on the SD cards boot partition. See here for more details.

You can also set all of these variables remotely for a single device or the entire fleet using the Configuration tab on the device or fleet level respectively. If the setting in config.txt is variable=value, you can achieve the same settings by adding a configuration variable with BALENA_HOST_CONFIG_variable set to the value value. For example:

Setting the device configuration for Raspberry Pi config.txt variables

For simplicity, below all examples are using the config.txt formatting, but all of them are available to set remotely as outlined above.

For further details and explanation regarding the settings below you may check the official config.txt documentation.

Binary Blobs for GPU/vcore

This is necessary for any graphics acceleration or if you want to use the official raspberry pi camera module

gpu_mem=128
start_file=start_x.elf
fixup_file=fixup_x.dat
Increase USB current throughput:

This can be useful if you are running a power hungry USB peripheral like a 3G dongle.

max_usb_current=1
safe_mode_gpio=4
overclock RPI2:
arm_freq=1000
core_freq=500
sdram_freq=400
over_voltage=0
over_voltage_sdram_p=0
over_voltage_sdram_i=0
over_voltage_sdram_c=0
OR
arm_freq=1000
sdram_freq=500
core_freq=500
over_voltage=2
temp_limit=80 #Will throttle to default clock speed if hit.
Fill the screen to the edges
disable_overscan=1
overscan_left=4
overscan_right=4
overscan_top=4
overscan_bottom=4

Beaglebone

Currently the Beaglebone devices are running a very new 4.1 kernel (which is obviously awesome), unfortunately many of the userspace libraries haven't caught up yet so they only work with the older 3.8 kernel. Luckily ruth0000 was kind enough to patch the Octalbonescript JS library and made a lovely node.js module over here: https://www.npmjs.com/package/octalbonescript_capemgr4_1 .

With this module you should be able to basic GPIO and analog-to-digital conversion stuff. To get you started we have a simple example using this module here.

Note: The ADC voltage is only rated to 1.8V, if you apply more you risk frying the pin.

Capemgr support

Warning: Capemgr is only supported in balena BBB devices with a 4.1 linux kernel. This kernel was only enabled in production on 25-09-2015. If you don't know which kernel you are running, open a web terminal to your BBB and run uname -a.

Loading a Cape
echo cape-universaln > /sys/devices/platform/bone_capemgr/slots
Checking which Capes are loaded.
cat /sys/devices/platform/bone_capemgr/slots
cat /sys/devices/platform/ocp/ocp:cape-universal/status

OCPDIR=/sys/devices/platform/ocp/ocp*
SLOTS=/sys/devices/platform/bone_capemgr/slots

Disable HDMI

Before provisioning, mount the .img, in the flash-boot partition you should see a file named uEnv.txt_internal open that up with your favorite text editor and add the following line to the bottom of the file:

fdtfile=am335x-boneblack-emmc-overlay.dtb

You should now be able to use any of the pins that used to be occupied by the HDMI. To test this you can run the following from your web terminal:

echo 74 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio74/direction
echo 1 > /sys/class/gpio/gpio74/value

Pin 41 of Header P8 should go high.

Intel Edison

MRAA for GPIO and hardware access

The best and easiest way to interface with GPIO, I2C, SPI or UART on the Intel Edison is to use the MRAA library, this library gives you a simple way to write C, python or Node.js applications that interact directly with the Edison hardware.

If you use our balenalib/intel-edison-node or balenalib/intel-edison-python base images in your applications, you will automatically have the mraa setup correctly for node.js or python respectively.

Have a look at this python example or this node.js example to get started.

UPM for high level sensor and actuator libraries

Intel provides the UPM library which contains software drivers for a wide variety of commonly used sensors and actuators. These software drivers interact with the underlying hardware platform (or microcontroller), as well as with the attached sensors, through calls to MRAA APIs.

Edison in USB Host mode

The Edison needs a kernel module to be loaded to trigger the UBS HOST mode. This can be done in the following way.

Hardware Pre-requisites:

Your Edison will need to be powered externally for the USB host mode to be active - Either through the DC jack on the Arduino board or through the battery connector on the smaller Intel carrier board.

Software Pre-requisites:

The following code needs to be placed at the start before any device operations run in the container.

#!/bin/bash

mount -t devtmpfs none /dev
udevd --daemon

# g_multi needs a file to be passed which shows up as USB storage if Edison is in device mode.
# We are creating a blank file here.
dd if=/dev/zero of=/data/blank.img bs=10M count=1

# The following is needed to get the Edison to switch to host mode - If the power connections aren't made for the HOST mode this exposes the file above as USB storage, emulates a USB network card and USB serial connected to the Edison.
sync && modprobe g_multi file=/data/blank.img stall=0 idVendor=0x8087 idProduct=0x0A9E iProduct=Edison iManufacturer=Intel

udevadm trigger
udevadm settle

# Shutdown the unnecessary usb0 spawned by g_mutli
sleep 5s && ifconfig usb0 down

After this you should be able to easily use your Intel Edison in USB host mode.

IOT-GATE-iMX8

Serial ports

The IOT-GATE-iMX8 has at least one serial port that can be configured as either RS232 or RS485. To select the RS232 operating mode, in the host operating system, add the following line to /mnt/boot/extra_uEnv.txt:

uart_mode=rs232

Similarly, rs485 can be selected in the environment file as well. The device should be rebooted after setting the uart operating mode the for the changes to take effect.

Up Squared

Serial Ports

Depending on the HAT Configuration defined in BIOS, the Up Squared UART communication on pins 8 and 10 can be performed using either /dev/ttyS4 or /dev/ttyS5. Please consult the HAT Configurations menu in BIOS for details on how pins are configured on your device.

Jetson Devices

Custom device trees

Loading of custom device trees in balenaOS is supported by the Jetson Nano, Jetson TX2 and Jetson Orin family of devices. The list of devices that support this function includes:

  • Floyd Nano
  • Jetson Nano SD-CARD
  • Jetson Nano eMMC
  • Jetson Nano 2GB Devkit SD
  • JN30B Nano
  • Photon Nano
  • Astro TX2
  • Jetson TX2
  • Jetson TX2 NX (with Xavier NX Devkit)
  • Orbitty TX2
  • Photon TX2 NX
  • Spacely TX2
  • Jetson AGX Orin Devkit
  • Jetson Orin NX in Xavier NX Devkit NVMe (16GB RAM)
  • Jetson Orin Nano 8GB (SD) Devkit NVME

Loading of custom device trees is not supported for the Jetson Xavier family of devices in balenaOS. U-Boot provides the complete set of functionality necessary for loading custom device-trees in balenaOS for the Jetson Nano and TX2 devices, and this bootloader is not supported by the Jetson AGX Xavier and Jetson Xavier NX BSP. The Jetson AGX Orin family of devices uses a new Tegra UEFI bootloader which allows balenaOS to load custom device-trees.

To test a custom device tree on a Jetson Nano, TX2 or Jetson AGX Orin or Orin NX device, place your custom compiled device tree in the host operating system of your device, in the following path: /mnt/sysroot/active/current/boot/ After that, navigate to the Device Configuration tab in the balenaCloud dashboard, activate the following configuration with the description Define the file name of the DTB to be used, and specify the file name of the custom device tree. The value of this configuration should contain the file name only. After the change is applied, the device will automatically reboot and load the new device tree.

After the custom device tree has been validated, it can be included in newer balenaOS images. For Jetson TX2 and Nano, open a pull request in the balena Jetson device repository following this example commit. For the Jetson AGX Orin, the PR should be opened in the balena Jetson Orin repository. Once your PR is approved and merged, a new balenaOS image that includes your custom device tree will become available shortly.

Please note that if the changes for your carrier board expand past kernel device-trees, or require modifications to board configuration files like pin multiplexing configuration files or any other device-trees or files used by firmware, these may not be provided by the existing cloud images. During provisioning the resulting configuration changes are stored in the QSPI or in the hardware defined boot partitions, and thus will be replaced with the default values when updating the Host Operating System. Please contact us if you would like to use a Jetson carrier board which may not be fully compatible with its' corresponding devkit, or with any of our cloud images for your Jetson module.

Container packages

The Jetson specific packages installed in your container images need to be in sync with the Linux for Tegra version used by the Host Operating System. Our base images for Jetson devices come pre-populated with /etc/apt/sources.list.d/nvidia.list files, which include the necessary links so that the apt repositories are in sync with the L4T version used by our latest OS images. If you suspect you encountered a mismatch, please check the L4T version in your Host OS using uname -r and compare it to the release version in your container's /etc/apt/sources.list.d/nvidia.list file. Please check our Jetson Examples repository for more information on how to set-up your container images.