Board Component

A board is the signal wire hub of a robot that provides access to GPIO pins.

If your board has a computer that is capable of running viam-server, or is connected to one, it can act not only as the signal wire hub for your robot, but also as the software hub.

Configure a board component on your robot to control and read from the other hardware components of the robot, signaling through the GPIO pins on the board as overseen by a computer running viam-server.

Figure: Two different board options: a single-board computer with GPIO pins running `viam-server` locally, or a GPIO peripheral plugged into a desktop computer's USB port, with the computer running `viam-server`.
Image showing two board options: First, running viam-server locally and second, running via a peripheral plugged into the USB port of a computer that is running the viam-server.

What does “signal wire hub” mean?

A robot’s board component has general purpose input/output (GPIO) pins. As the name suggests, these pins can be inputs or outputs, and can be set high or low–that is, turned on or off–and thus used to signal (or read signals from) other hardware. Many GPIO implementations also support PWM (Pulse Width Modulation), or can be used as more advanced signaling systems such as I2C, SPI, or UART/Serial.

What can I use as my board?

Generally, you should use a single-board computer with GPIO pins or a computer outfitted with a GPIO peripheral.

This way, overseen by a computer running viam-server, the GPIO pins on your board can receive signals from and send signals to the hardware components of your robot.

Single-Board Computer with GPIO Pins:

This refers to boards like the Raspberry Pi, BeagleBone, and Jetson.

These are all small computing devices outfitted with GPIO pins that are capable of advanced computation, including running viam-server.

Computer outfitted with a GPIO Peripheral:

A GPIO peripheral can act as the signal wire hub of your robot. However, a board like this does not contain a computer to run viam-server on the robot, so it can only act as the board if you have physically connected it to another computer.

In this case, the computer running viam-server signals through the GPIO peripheral’s GPIO pins to communicate with the other hardware components of the robot.

You can use any computer capable of running viam-server, whether it’s your personal computer or another machine, as long as it is connected to the GPIO peripheral.


Most robots with a board need at least the following hardware:

  • A power supply with the correct voltage and current to avoid damaging or power cycling the board. See the data sheet of your board model for requirements.

    • For example, a Raspberry Pi 4 takes a 5V power supply and converts it to 3.3V for its logic circuitry. The easiest way to power it is with a 5V USB-C power supply.

Configuration

Refer to the following example configuration file for a single-board computer like Raspberry Pi:

An example of configuration for a single-board computer in the Viam app config builder.

{
  "components": [
    {
      "type": "board",
      "model": <your_model>
      "name": <your_name>
    }
  ]
}
{
  "components": [
    {
      "type": "board",
      "model": "pi"
      "name": "viam-board-example"
    }
  ]
}
AttributeInclusionDescription
typeRequiredAll boards are of type board.
modelRequiredSpecify the correct model for your board.
nameRequiredChoose a name for your board. Note that the name you choose is the name you need to refer to this particular board in your code.

For the model, supported board models include:

  • pi: Raspberry Pi 4 or Pi Zero W2

  • beaglebone: BeagleBone AI 64

  • ti: TDA4VM devkit

  • jetson: Nvidia Jetson Xavier NX, Nvidia Jetson Nano

  • numato: Numato GPIO model (GPIO peripheral)

For more advanced configuration options, read on.

Deeper Dives: Advanced Configuration

Using GPIO

Essentially all electrical signals sent from and received by your board go through GPIO pins. It is important to understand some of what they can do and how to use them.

Here are a few use cases:

  • Can be set high (to 3.3V for example) or low (zero volts) to do things like:
    • Switch an enable or mode pin on a motor driver or other chip.
    • Light up an LED or similar.
    • Switch a relay.
  • Send a PWM signal to control the speed of a motor or servo.
  • Read the state of the pin (High/Low), which can be used to monitor the status of whatever is connected to it.
  • Receive digital signals from sensors see I2C & SPI protocols and Analogs sections below.
  • Receive input as a digital interrupt, detailed below.

Some things GPIO pins cannot do:

  • Power a motor or other high power draw device directly. GPIO pins are built for logic levels of power, that is 3.3V and 16mA per pin. Power amplification (a motor driver or relay) would be necessary.
  • Receive signals over 3.3V (or whatever the logic voltage is on a given board).

If you are using GPIO pin methods like gpio_pin_by_name (documented in our Python SDK) you do not need to configure anything about the pins in your config file. The pins are automatically configured based on the board model you put in your config, and you can access them using the board pin number (not the GPIO number). You can find these pin numbers from an online service such as pinout.xyz or by running pinout in your Pi terminal.

Getting started with GPIO and the Viam SDK

The following snippet uses the gpio_pin_by_name method to get a GPIO pin by name. It then uses the set method to set the pin to high. This turns the LED connected to pin 8 on.

from viam.components.board import Board

local = Board.from_robot(robot, 'local')
led = await local.gpio_pin_by_name('8')

# When True, sets the LED pin to high/on.
await led.set(True)
await asyncio.sleep(1)

# When False, sets the pin to low/off.
await led.set(False)
import (
  "context"
  "time"

  "github.com/edaniels/golog"

  "go.viam.com/rdk/components/board"
)

local, err := board.FromRobot(robot, "local")
if err != nil {
  logger.Fatalf("could not get board: %v", err)
}

led, err := local.GPIOPinByName("8")
if err != nil {
  logger.Fatalf("could not get led: %v", err)
}

// When true, sets the LED pin to high/on.
led.Set(context.Background(), true, nil)
time.Sleep(1 * time.Second)

// When false, sets the LED pin to low/off.
led.Set(context.Background(), false, nil)

Analogs

If an analog to digital converter (ADC) chip is being used in your robot, analog readers (analogs) will have to be configured. An ADC takes a voltage as input and converts it to an integer output (for example, a number between 0 and 1023 in the case of the 10 bit MCP3008 chip).

Configuration

Some boards like Numato have built-in ADCs which makes configuration more straightforward.

Some boards (such as Raspberry Pi) communicate with the ADC over SPI so both analog and SPI must be configured. An example:

{
  "components": [
    {
      "attributes": {
        "analogs": [
          {
            "chip_select": "24",
            "name": "current",
            "pin": "1",
            "spi_bus": "main"
          },
          {
            "chip_select": "24",
            "name": "pressure",
            "pin": "0",
            "spi_bus": "main"
          }
        ],
        "spis": [
          {
            "bus_select": "0",
            "name": "main"
          }
        ]
      },
      "model": "pi",
      "name": "local",
      "type": "board"
    }
  ]
}

Note that the name of the SPI bus (“main”) matches between the analog configuration and SPI configuration.

Required Fields
NameTypeDefault ValueDescription
namestringChoose a name for the analog reader
spi_busstringThis value should match the name given to the relevant SPI bus in its section of the config file.
pinstringSpecify which pin of the ADC chip to use.
chip_selectstringSpecify the pin number of the board GPIO pin connected to the ADC chip. Use the pin number, not the GPIO number.
Optional Fields

average_over_ms (int) and samples_per_sec (int): Together these allow for the use of AnalogSmoother. Specify the duration in milliseconds over which the rolling average of the input should be taken, and the sampling rate in samples per second, respectively.

Digital Interrupts

Digital interrupts are useful when your code needs to be notified immediately anytime there is a change in GPIO value. Contrast this with running the Get method on a GPIO pin only at specific times when you want to know its value, which you can do without configuring interrupts; you only need to call Get on the name yielded by GPIOPinByName.

Configuration

An example:

{
  "components": [
    {
      "attributes": {
        "digital_interrupts": [
          {
            "name": "example-interrupt-1",
            "pin": "15"
          },
          {
            "name": "example-interrupt-2",
            "pin": "16"
          }
        ]
      },
      "model": "pi",
      "name": "local",
      "type": "board"
    }
  ]
}
Required Fields
NameTypeDefault ValueDescription
namestringChoose a name for the digital interrupt.
pinstringSpecify which GPIO pin of the board to use. Use the pin number, not the GPIO number.
Optional Fields
NameTypeDefault ValueDescription
typestringSet type to “basic” to count the number of interrupts that occur. Set type to “servo” to count the average time between the interrupts (akin to pulse width).
formulastringApply a mathematical function to the input.

Other Communication Methods

Boards can communicate with other hardware components in a few different ways. Some devices only require basic GPIO pins whereas others require more specialized methods. For example, the TMC5072 stepper motor microcontroller requires SPI bus communication. The following are brief descriptions of each protocol Viam supports, as well as the corresponding configuration information.

SPI Bus

Serial Peripheral Interface (SPI) uses several pins for serial communication: main out/secondary in (MOSI); main in/secondary out (MISO); SCLK, a clock for serial communication; and chip enable (also called chip select) pins. If you are using a Raspberry Pi, the “built-in” chip select pins are labeled CE0 and CE1 on the pinout sheet. The required connections between corresponding board pins and peripheral device pins must be wired, but each of these pins does not need to be specified in the config as most boards have them configured by default. Only the index of the entire bus must be specified.

Configuration

The attributes section of a board using SPI will contain the following:

{
  "spis": [
    {
      "name": "main",
      "bus_select": "0"
    }
  ]
}
Required Fields
NameTypeDefault ValueDescription
namestringChoose a name for the SPI bus. Note that a component that uses this bus must then have this same name configured in its attributes.
bus_selectstringA Raspberry Pi has two SPI buses: 0 and 1. See your board’s data sheet for specifics on its SPI wiring.

I2C

I2C stands for inter-integrated circuit and is similar to SPI but requires fewer pins: serial data (SDA) and serial clock (SCL). Some boards that support I2C have the SDA and SCL pins configured by default, so in your config file you need only specify which I2C bus you are using. For example, if you use I2C bus 1 on a Raspberry Pi 4, SDA and SCL will be pins 3 and 5, respectively. You will also need to enable I2C on your board if it is not enabled by default. Review the instructions in our documentation to learn how to enable I2C on a Raspberry Pi 4. Pinout.xyz has additional information about I2C on Raspberry Pi.

Configuration
{
  "i2cs": [
    {
      "name": "bus1",
      "bus": "1"
    }
  ]
}
Required Fields
NameTypeDefault ValueDescription
namestringChoose a name for the I2C bus. Note that a component that uses this bus must then have this same name configured in its attributes.
busstringUsually a number. Raspberry Pi recommends using bus 1. See your board’s data sheet for specifics on its I2C wiring.

Implementation

See the example code above to get started, and check out our Python SDK Documentation.

Troubleshooting

You can find additional assistance in the Troubleshooting section.

You can also ask questions in the Community Discord and we will be happy to help.

Next Steps