Connecting an Avnet MaaxBoard to Azure IoT

Homepage Connecting an Avnet MaaxBoard to Azure IoT

Recently, we wrote about how to connect a Raspberry Pi to AWS IoT and talked about how connecting hardware to the cloud can enable richer and more meaningful customer experiences. In this guide, we’d like to continue demystifying the process of connecting IoT devices to popular cloud services by helping you learn how to connect an Avnet MaaXBoard to Azure IoT.

Throughout the guide, we’ll look at everything from the hardware and equipment you’ll need to how to connect your MaaXBoard to the cloud. Whether you’re an experienced engineer or complete beginner, this guide should cover all you need to know to get started with IoT devices like the Avnet MaaXBoard in Microsoft Azure!

Project Materials

The first thing to do before you dive into an IoT project is to make sure you have all the materials you’ll need in order to complete it. To finish this project, you’ll need some specific hardware and some software.

Required Hardware

  • The Avnet MaaXBoard (i.MX8M) which has 2GB RAM and a comparable GPIO configuration to a Raspberry Pi
  • A USB keyboard
  • A USB mouse
  • A monitor and HDMI Mini (Type C) cable to plug into the MaaXBoard. If your monitor also has an HDMI port then you can use this one
  • A 5V/3A USB Type C power supply cable to power the MaaXBoard like this one
  • At least one 16 GB micro SD card – Here is a relitively cheap option for getting three
  • A microSD card reader for your computer
  • A breadboard, LED light, jumper wires, and resistors which you can get inside of a kit like this one

Here are a few other options for starter kits:

Required Software and Accounts

In addition to this hardware, you’ll also need:

  • An Azure Subscription. You can create one for free here. When you create the account make sure you store your credentials somewhere as we’ll be doing a lot in Azure later in this tutorial.
  • The OS Image to flash to the SD card and software that we can use to flash the image to the microSD card. I’ll be using Etcher to do the flashing which you can download for free. We’ll get the OS Image in the next step.

With all this hardware and software ready to go we can start by flashing our microSD card!

Flashing Your MicroSD Card

The first step to using the MaaXBoard will be to create a MicroSD card with a specific operating system image compatible with the Avnet MaaXBoard. To do this, we’ll need to download the image and use Etcher to flash the image onto our SD card.

Downloading the Image

You can download the Debian image from the MaaXBoard manufacturer website here.

Look under the Reference Designs section and click the option to download the Debian Linux Out of Box Image.

After you download it you will need to unzip and unrar it. On a Windows machine, you can do this with the 7-Zip Program.

On Linux or Mac you can use the unzip command:


And then you can unrar it with the unrar command. If you don’t have unrar already you might need to install it:

  • On Linux with Sudo apt-get install unrar
  • On a Mac machine using Brew: brew install unrar

With unrar, you can run:

unrar e 91200026-MaaXBoard-LinuxShipmentImage-Debian-V1.1.1r10.rar

At the end of this process you should then have an .img file with a name like this:


Flashing the Card with Etcher

With this .img file you can now use Etcher to flash the MicroSD card. If you haven’t already, download Etcher and then put your MicroSD card into your MicroSD card reader and plug it into your computer.

With the SD card plugged in, open Etcher and select Flash from file:

Select the .img file from your file explorer:

And then back in Etcher press Select target and then select your microSD card from the options available:

The Location and Name values shown above will change based on your operating system but the size of the drive should be close to the side of your MicroSD card – in my case 16 GB. Press Select and then press Flash:

You may also have to enter your password in a system authentication prompt to write to this disk. Flashing the microSD can take several minutes to complete so go ahead and grab yourself a nice cup of tea:

When it’s finished, you should see a success message like this one:

Make sure the message says that the card has been flashed successfully or else the next steps will not work. After the card is flash, we can set up the Avnet MaaXBoard with the breadboard, LED and other hardware!

Setting Up Our MaaXBoard and LED Circuit

The next step in the process is to set up our MaaXBoard with an LED circuit that we can manipulate later using the GPIO pins on the device. To do this, we’ll need to make sure the device in unplugged and that we can access the GPIO pins on the MaaXBoard.

From here, you’ll need the cables, breadboard, LED, and resistors that came with the kit I linked to in the materials section. If you’re not using that kit, you’ll still need all those materials in some form in order to properly arrange this circuit.

Start by making sure that you have a resistor with the appropriate resistance for your LED. If you’re using a different kit, then make sure you review the voltage of your LED and the resistance of your various resistors. This guide is a useful resource for helping to calculate the appropriate resistance for LEDs.

In my case, the kit I purchased has two resistors either a 330-ohm resistor or a 4.7k ohm resistor. After running the calculations for how much resistance I needed it looked like the 330-ohm resistor was a little too low for my needs, so I decided to use the 4.7k ohm resistor.

Because this is quite a bit of resistance, this does result in the LED being somewhat dim, but that’s better than something breaking!

Below, you’ll see the configuration I used (remember only to set this up with the power for everything off!):

A few notes here – The “Raspberry Pi” in this image should be an Avnet MaaXBoard. It just so happens that the Avnet MaaXBoard has the same 40-pin GPIO configuration as the Raspberry Pi and that Fritzing (my circuit drawing tool for making this image) has a nice visual for the Raspberry Pi.

Here’s a slightly larger example that also contains the labels for the GPIO pins that I’m plugging into.

If you’re using the kit I selected earlier, you’ll use one of the socket/plug cables and plug the socket of one cable into the GND pin. Then, you’ll put the plug side of the GND cable into the rail socket on row 1.
After that, you’ll connect the resistor as shown in the rail on row 2 and connect it to 2D.

Then, add the LED with the short side in 2E, closest to the resistor and the tall side away from it in 3E.

Finally, connect the plug from another cable in 3A and the socket of that cable to GPIO17 right next to the GND pin. It’s a little hard to see, but here’s what the actual setup looks like on my desk:

Now that we have everything plugged in and ready to go, we can set up the MaaXBoard operating system!

Configuring the MaaXBoard Debian Operating System

With our circuit set up, we can now configure the MaaXBoard operating system we just flashed to our microSD card.

First, plug in the mouse, keyboard, and monitor to our MaaXBoard. Then, take your newly flashed microSD card and plug it in to the microSD slot on the device. The SD card should slip in with a little smooth spring-loaded resistance until you hear that satisfying ‘click’ when it’s securely in place on the MaaXBoard.

From here, make sure your monitor is connected and turned on and plug the MaaXBoard in with your USB-C power cable. This should start the bootup process for the MaaXBoard and you should be greeted by a clean Debian-looking desktop.

To verify everything is set up correctly and installed properly, open the terminal program in the top left and enter the bash shell by typing bash and hitting enter. Then, to make sure you have the correct image use this command:

cat /etc/*release

At the time of this tutorial, the operating system has a PRETTY_NAME of Debian GNU/Linux 10 (buster).

You can also run:

uname -a

Which should return a result that includes something like: Linux maaxboard 4.14.78

Connecting Wi-Fi

With all of this confirmed, we can set up WIFI on the device! This can either be done through the WiFi GUI in the menu bar or via the command line. If you use the GUI, make sure to type your SSID and password in correctly the first time or you might have to run a terminal command to clear it properly. If you’re using the ethernet port on the device, then you might not need to go through this step.

From the terminal, you can set up Wi-Fi with these commands:

First, turn Wi-Fi network discovery on with the network manager CLI using this command:
nmcli r wifi on

Then, run this command to find the SSID information for nearby Wi-Fi networks:

nmcli dev wifi

You should see a series of SSIDs for nearby Wi-Fi networks that looks something like this:

This should show you the SSIDs of nearby networks. Press “q” to quit out of this view and then run this command with <Your-WiFi-SSID> and <password> replaced with your actual SSID and password.

nmcli dev wifi con “<Your-WiFi-SSID>” password “<password>” ifname wlan0

Make sure that you spell the SSID and password correctly to avoid having to remove this network and try again. You should see something like this with a different GUID when the MaaXBoard connects to the network:

Device ‘wlan0’ successfully activated with ‘77daa2fe-4c34-47e4-8721-bb39acd8a54f’

Next, look for the connection details with:

ip a show wlan0


ifconfig wlan0

This should tell you information about your IP address on the local network. If you want to test your connection just run a quick ping check:


If you see a result that includes a TTL and time value, then you’re good to go! If for any reason one of these steps doesn’t work, or you see an error that says “Error – secrets were required but not provided” you can always remove your WiFi network, turn the WiFi off and back on and try again:

nmcli con delete “<Your-SSID>”
nmcli r wifi off
nmcli r wifi on

Even if you were able to connect, you still might have to run this command again the next time you boot up the board in order to connect to WiFi:

nmcli device con wlan0

If you want to disconnect from the network later, you can run:

nmcli device dis wlan0

Toggling LEDs

Now we’ll test out how to control the LEDs built in to the MaaXBoard itself using bash. To do this, notice the built-in LEDs that are hopefully blinking on your board near the MaaXBoard logo on the short side of the board closer to the pins you’ve plugged in. Let’s turn these LEDs on and off!

For the usr_led (the LED closest to the pins) we’ll run:

echo 0 | tee /sys/class/leds/usr_led/brightness

To turn the LED off and then run this to turn it on:

echo 1 | tee /sys/class/leds/usr_led/brightness

You can also control sys_led/brightness. Use this to turn it off and stop it from blinking:

echo 0 | tee /sys/class/leds/sys_led/brightness

And this to turn it on:

echo 1 | tee /sys/class/leds/sys_led/brightness

But this is just to control the LEDs onboard the device itself. What if we want to control the LED we created our entire circuit for? In order to do that, we need to make sure we know which GPIO the socket is plugged into. If you followed my reference diagram above it should be plugged into pin 9 (a ground or GND pin) and pin 11 – AKA GPIO 17. If you’re using these exact pins then you can follow these next instructions to turn the LED on and off. If you’re using other GPIO pins then you’ll need to skip ahead to the Other Configurations section below to understand what’s happening here.

First, we need to set up the GPIO pin as an output pin that we can use with the LED. We’ll do this by manipulating the GPIOs through the /sys interfaces that allow communication from the operating system to the GPIO pin hardware. This is a good option for tinkering with the device and playing around with different pins and hardware. In other cases, we might use a library like libgpio to do this more efficiently.

On the MaaXBoard, we do this for pin 11/GPIO 17 with these two commands:

echo 81 > /sys/class/gpio/export

echo out > /sys/class/gpio/gpio81/direction

The export command “exports” control of this specific GPIO pin so that we can use it. Then, the direction command sets up the GPIO pin as an “out” pin meaning that we’re going to be providing output using this pin.

Then, we can set the initial value of the LED to off using this command:

echo 0 > /sys/class/gpio/gpio81/value

And then we can turn the LED on with this command:

echo 1 > /sys/class/gpio/gpio81/value

Remember, we might have to look closely at the LED when we do this because the light emitted with a 4.7k Ohm resistor is very faint! We can run those two commands back and forth several times to play with the LED state, but when we’re done we can clean everything up by turning the LED off:

echo 0 > /sys/class/gpio/gpio81/value

And running this to clean up the GPIO setup we did earlier:

echo 81 > /sys/class/gpio/unexport

With this cleaned up, let’s look at what’s happening here, how we’re getting “echo 81” and “gpio81” in these commands above, and how we could use other GPIO pins.

Other Configurations

If you were using other pins, you would need to figure out how to set up and reference those GPIO pins using the internal numbering for the GPIO pins that MaaXBoard has.

The easiest way to do this is probably to reference this Element 14 guide which explains some of the internal numbers for GPIO pins on the MaaXBoard and the MaaXBoard Pin Reference itself on page 22 of this document.

To find the “81” in the commands above that refers to pin 11/GPIO 17, you can use this formula from the Element 14 link above:

gpio_number = (chip_number – 1) * 32 + gpio port

To get the chip number and GPIO port you’d need to reference the MaaXBoard Pin Reference around page 22. For example, on page 22 you can look at the line referring to pin 11 (which we just used):

11    GPIO3_IO17   K22   General-purpose input/output

The number 81 that we used was calculated by taking the 3 and the 17 that are part of GPIO3_IO17 and including them in the formula like this:

(3 – 1) * 32 + 17 = 81

If you end up using other GPIO pins, you can calculate the values like that too. Now that we’ve tested everything out, let’s set up the resources we need in Microsoft Azure.

Setting Up Our Azure IoT Hub

If you haven’t already, the first step is to create an Azure subscription. After you’ve done so, sign into your Azure account and use the search bar to navigate to IoT Hub:

Then, press Create IoT Hub or press +Add:

From here, you’ll configure the details of your IoT Hub Resource Group, Region, and IoT Hub Name:

I gave my resource group a name of fmc-iot-hub-rg – fmc for my initials and rg for “resource group”. I named my IoT hub itself fmc-iot-hub. You can name your hubs whatever you’d like.

After this, you have to decide some the network settings for your IoT Hub:

Importantly, this isn’t necessarily giving anyone access to interact with our IoT Hub or our IoT Devices – there will be an authentication step that handles this for us. Instead, this is determining from a networking level which IPs are even allowed to make connections to our IoT Hub. There are a few different options we can pick from:

  • The Private endpoint option would allow us to configure an endpoint for our IoT Hub that is not accessible from the public internet and requires any device wanting to access it to connect through something like an on-premises network or VPN. This option might be less common for commercial consumer IoT devices but could be appropriate when working with IoT devices that will always be installed on a private corporate network such as in an office environment where secured company WiFi is available.
  • The Public endpoint (select IP ranges) allows us to select a range of IP addresses that we want to be able to access the IoT Hub and block any addresses not selected. This can be useful if there are certain IP addresses or ranges that we want to allow. However, if we don’t know where any of the devices will be installed and what the IPs of those devices might end up being, then we need to use a different option.
  • The Public endpoint (all networks) option is perfect when we have no idea what IP addresses our devices will be associated with. This is likely the case when we have consumer devices that we’re sending out to any customers who purchase them. In those cases, we can’t predict the IP addresses being used, and we can’t expect most consumers to connect device via our VPN (and we probably wouldn’t want them to!).

We’ll keep the Public endpoint (all networks) option selected here to keep things simple.

Next, we can select the capacity and price we’re interested in for our IoT Hub. There are a few different settings we can choose from here. The Pricing and scale tier allows us to select which level of capacity we need for our IoT Hub:

For our demo purposes we can select the F1: Free tier option shown in the screenshot above which has very limited configuration options but allows us to try out many of the features of an IoT Hub at a limited scale.

Outside of the F1: Free tier hub option there are two tier types each with their own feature sets.

The Basic tier is focused on unidirectional messaging from the device to the cloud and have a feature set that excludes things like IoT Hub Device Twins and Cloud-to-device messaging. This tier is the cheaper option.

The Standard tier allows for bidirectional communication between devices and the cloud and allows you to leverage all the features of IoT Hub including Device Twins and Cloud-to-device messaging and commands. Because of this, it’s more expensive than the basic tier.

For both the Basic and Standard tiers you can select numbered options like B1, B2, B3, S1, S2, and S3. These different options correspond to an amount of capacity allocated for each IoT Hub unit. For example, the B1 and S1 options each support 400,000 messages per day per IoT hub unit whereas the S3 tier and B3 tier each support 300 million messages per IoT Hub unit.

There are a few other settings like determining if you want to turn the Azure Security Center on if you select the Standard tier. However, for our purposes we’ll keep that Free tier option selected and leave it at that.

From here, we can press Review + create and review the configuration we’ve just set up for our IoT Hub:

Just confirm that you’re using the F1 pricing and scale tier then you can press Create! It will take a few minutes for your infrastructure to deploy, but then you’ll have access to the IoT Hub you just created:

With this created, we can now set up our MaaXBoard within Azure IoT Hub!

Manually Adding Our Avnet MaaXBoard to Azure IoT Hub

From the overview of our IoT Hub deployment we can click Go to resource. If we’ve already left that page, we can navigate to the IoT Hub section of the Azure Console and click on the IoT Hub we just created there as it should now show up:

On this blade view of the IoT hub we created we need to look under the Explorers section for IoT Devices:

From here, we can create a new device in IoT Hub manually by pressing +New:

And then going through the Create a device form:

On this page we’ll need to give the device an id. In a production environment we might use a serial number or logical naming convention with some prefix or suffix including the device name or type and some other identifier to search for it later. But because we’re just adding one device for now, we’ll keep it simple and call it maaxboard.

Authentication Types – MAKE INTO A HEADER

The next thing we need to pick on this page is the Authentication Type. As I mentioned earlier, the network connection options we set on the IoT Hub itself are additional security options, but they are unrelated to the mechanism for authenticating IoT devices to IoT Hub. This section is where we configure that for our device. We have a few different options here, each with different security implications so let’s look at each of them.

Symmetric Keys

If you select the symmetric key option to authenticate your IoT Device, then IoT Hub will automatically generate a primary and secondary key for you, though you can create your own keys. Having two keys allows you to rotate the are placed on your device, they allow for symmetric encryption between IoT Devices and IoT Hub.

While symmetric keys are the easiest option to get started with, they are usually regarded as a less secure option to use in production. This is because symmetric keys require securing the key both on the device and in the cloud leading to a larger attack surface and if a device is compromised, the device and the cloud must be updated to put the device back in service.

Additionally, symmetric keys can lead to bad development practices such as reusing one symmetric key for multiple devices or checking these symmetric key secrets in to your application code rather than properly securing them in something like a hardware security module. For these reasons, symmetric keys are typically only used for minimal experimentation and prototyping.

Self-Signed X.509 Certificates

Another option to authenticate your device is to use self-signed X.509 certificates. When creating these directly in Azure IoT Hub you include a thumbprint for the primary and secondary certificates you want your device to use:

With self-signed certificates you do not rely on a trusted third-party vendor for the management of your public key infrastructure but instead hand IoT Hub your certificate’s thumbprint hash directly. These thumbprints allow IoT Hub to validate the authenticity of the X.509 certificate that the device will later present to IoT Hub. From there, the device can provide the self-signed certificate and have the IoT Hub authenticate it as that device.

This simplified self-signed model is typically not used in production either because it can also lead to some of the poor security practices mention in the Symmetric Keys section. Additionally, generating the self-signed certificates individually for every device without the use of an intermediate or root certificate can lead to many scattered individual certificates without a streamlined way to reissue or reprovision them later.

X.509 CA Signed Certificates

Another option when working with X.509 certificates in Azure IoT Hub is to use CA Signed Certificates. While Azure uses thumbprinting to verify the authenticity of self-signed certificates, it also offers the ability to verify an entire certificate chain. This is what is used when you rely on CA Signed certificates.

First, you either purchase a certificate signed by a public root certificate authority or you create a self-signed certificate. Whichever route you choose, you will use this certificate to sign other certificates.

You can use your CA certificate to sign leaf certificates directly – one for each device. Or you can sign intermediate certificates with the CA certificate and those intermediate certificates can sign leaf certificates for each device.

There are many strategies and best practices on how you can manage these certificates and include them with devices during a manufacturing process. Usually, this involves using an intermediate certificate to generate a unique certificate for every device during a device manufacturing process. Then, when devices are connected to the internet, they connect to the Azure Device Provisioning service to authenticate and collect connection information for an Azure IoT Hub.

This option is one of the most secure and most likely to be applied in production.

For our demo purposes, we’ll be using the easiest option to get started with when we’re not in a production environment – the symmetric key. When you’re done, the configuration should look something like this:

Press the Save button and then refresh the list of the IoT device to see your new IoT Device:

your device’s name, in this case – maaxboard and review the details of that device. You should see a Primary Connection String which you can copy from the Azure console:

Hold onto the connection string somewhere for now. We’ll need it soon to connect our MaaXBoard to the Azure IoT Hub using one of the Azure Device SDKs.

Before we move on, I want to point out that in production, this manual process would be automated with a combination of steps during the manufacturing process to issue unique identities for each device. While the process shown in this guide is probably the simplest for a single device, imagine scaling this to a manufacturing line for hundreds, thousands, or hundreds of thousands of devices!

In that case, the process would almost certainly involve provisioning unique identities for each device with X.509 certificates and then using the Azure IoT Device Provisioning Service (DPS) to get the required IoT Hub connection information and credentials needed.

Connecting Our MaaXBoard with the Azure IoT Device SDK

Not that our device is created in the Azure IoT Hub, we can connect from our MaaXBoard to Azure. The first step is to get back into our MaaXBoard and install some dependencies and download the sample code we’ll need for this project.

Installing Dependencies

Open the terminal on your MaaXBoard back up and run:

apt-get install python3-venv

When prompted, type Y and press enter so that it proceeds with the installation. This should install Python’s venv module which is used to install dependencies within a virtual environment (e.g. venv). After we get this installed, we’ll need to change directories to somewhere we want to set up our project and then create our own venv. To do this, run these commands:


mkdir iot && cd iot

python3 -m venv venv

source venv/bin/activate

After running these commands, you should see a (venv) appear on the left side of your terminal prompt. This means that the virtual python environment is activated! It comes with its own Python installation and the package management tool – pip. We’ll use pip to install the Azure IoT Device SDK with this command:

pip install azure-iot-device

We’ll use the Azure IoT Device SDK as part of our sample code to view and update our Device’s device Twin.

Getting Our Sample Code

Next, let’s get our sample code from the GitHub repository I’ve put together for you:

git clone

You should see three files inside of that repository:

  • py
  • py
  • py

The file is a small utility that helps the other two files setup, turn on, turn off, and tear down GPIO pins. The file is used to control the LED locally without any interaction with the cloud. The file can either control the device locally and update the state in the cloud, or it can listen for state changes locally and update the device as needed when the cloud’s device twin state changes.

Importantly, note that all these files are only written/tested to work with the Avnet MaaXBoard on this specific Debian image that we flashed to our device. Other boards, and other operating systems might have their own pin configurations and might have more sophisticated helper libraries in different languages for manipulating GPIO pins.

Controlling Our LED Locally

Let’s try using the local script first to turn the LED on and off. Just run it with Python to get started:


The script should prompt you to enter in the pin number you’re using to connect the LED:

Please enter one of these pin numbers for the GPIO you would like to use: [‘7′, ’11’, ’22’, ’26’, ’29’, ’31’, ’32’, ’33’, ’36’, ’37’]

In the case of the example configuration earlier in the guide we’re using pin 11 so we can type that out and press enter.

Next, you should see this output and be prompted to turn the pin on or off:

Your system gpio number is 81.

Please enter ON or OFF to turn the pin on or off.

Enter ON or OFF:

Try typing out ON and pressing enter, then do the same with OFF. While you do that, look at your LED to confirm it’s turning on and off as you expect.

When you’re done, press Control + C once and the script should automatically clean up the GPIO configuration.

Controlling Our LED from the Azure IoT Hub Device Twin

From here, you can use the script to interact with Azure cloud. This script relies on the Azure IoT Device SDK to interact with your device’s device twin. But before you can use it, you’ll need to set the device’s connection string as an environment variable.

export IOTHUB_DEVICE_CONNECTION_STRING=”<your_connection_string>”

Remember that connection string we copied down earlier? You’ll need to type that out in between the quotation marks in the command above and then hit enter to save it as an environment variable. After you do that, you can run the script:


This should prompt you to again enter the pin you used to setup your LED (in this demo that’s still pin 11). After you enter in 1 it should provide you with an initial device twin document that tells you the state of the device.

From there, you should see the same options as before except that you now have a LISTEN option. Type out LISTEN in all caps and hit enter. It should initialize the device’s light property as OFF and then if the state in the device twin changes it should output updates.

Leave that running and go back to Azure IoT Hub and the entry for our device:

On this page, you should see the Device Twin section. Click that and scroll down to the desired section under the properties and add a new entry of “light”: “OFF”, if you don’t see one already before the metadata section:

You will probably notice that there is a reported property there already. After you do this hit the Save button. If you haven’t changed anything or you can’t save it, then change the desired light property to ON and then hit Save.

Within a few seconds, you should see the LED on your device change to on! If you then hit Refresh a moment later in the Azure console, you should see both the desired and reported property change to ON:

From the device twin you can change the light’s state between ON and OFF and see that reflected in the LED, and then reflected in the reported section of the device twin data as soon as the device sends back an update indicating that it has changed the LED to the desired state.

Great job! At this point, you’ve connected your Avnet MaaXBoard to Azure IoT Hub and used both Python and bash to manipulate the GPIO pins on your MaaXBoard. After this, you should be ready to undertake more projects that combine different kinds of hardware with the Azure IoT Hub!

If you have suggestions for future tutorials, or suggestions for this one, don’t hesitate to reach out to us. In the meantime, you can check out our previous post on Connecting a Raspberry Pi to AWS IoT!