Microchip AVR-IoT Cellular Mini Development Board RoadTest Review

Table of contents

RoadTest: Microchip AVR-IoT Cellular Mini Dev Board for LTE-M and NB-IOT Prepaid SIM

Author: Gough Lui

Creation date:

Evaluation Type: Development Boards & Tools

Did you receive all parts the manufacturer stated would be included in the package?: False

What other parts do you consider comparable to this product?: Nordic Semiconductor Thingy:91, nRF91 Development Kit

What were the biggest problems encountered?: Arduino Libraries not sufficiently flexible or robust, not following Arduino conventions, connectivity losses causing hangs, unable to use power saving mode/power down modes.

Detailed Review:

Microchip AVR-IoT Cellular Mini Development Board RoadTest Review

By Gough Lui – August - October 2022

The internet-of-things is well and truly upon us, with smart-worlds relying on ever-increasing numbers of sensors providing data upon which intelligent decisions are made. In spite of this, connectivity for these sensors has always been an issue as these applications have strict requirements for size, weight, cost, energy, data rate and range. Technologies such as Bluetooth Low-Energy may suffice for short-range, consumer applications but fail to scale. While Wi-Fi can handle more devices, its range is still relatively limited and power consumption can be high. Bluetooth Low-Energy Mesh, Thread and Zigbee may be able to span further, but are still limited to operating in a relatively limited area. Ordinary 4G/LTE and 5G/NR technologies can certainly cover a wide range, but the energy consumption, complexity and cost are all high.

To truly have universal connectivity requires the use of low-power wide-area networks (LPWANs). But how does one span a wide area with little power? Most approaches (e.g. LoRaWAN, Sigfox) rely on reducing data rates, payload sizes and using coding on the signal to provide digital gain and increase robustness to interference. Such systems achieve data rates often in the kbit/s range – much slower than a dial-up modem. Some of these will require deploying your own infrastructure to act as a gateway to other existing connectivity, which is not always easy or ideal.

Thankfully, there is a middle-ground that exists. Through 3GPP standardisation, two common forms of machine-to-machine (M2M) connectivity include LTE-M (or LTE-MTC or LTE Cat-M1) and NB-IoT (or LTE Cat-NB1). The former is a simplified version of LTE which enables lower-cost modems which can be embedded within an existing LTE carrier. It uses lower data rates in a half-duplex connectivity mode and is suited to machine-type communication with increased range and handoff capability, although can have sufficient bandwidth to carry VoLTE if necessary. The alternative, NB-IoT uses a narrow-band carrier which can be run standalone or within guard-bands of LTE carriers. It also operates in half-duplex at even lower rates, enabling even lower power and better building penetration for low-data-rate applications (e.g. remote meter reading). It does not support handoff, thus is mostly suited for stationary applications. Both of these leverage the existing network infrastructure of LTE mobile carriers, allowing for ease of deployment although requiring payment of the necessary subscription costs.

To prototype with these connectivity standards often required purchasing relatively bulky development boards or the attachment of modules to existing microcontrollers which is not always elegant or straightforward. Instead, Microchip has introduced their AVR-IoT Cellular Mini Development Board which uses a familiar Adafruit Feather-compatible form factor, integrating a Sequans Monarch 2 GM02S Global Cellular Modem paired with a Microchip AVR128DB48 microcontroller and a Microchip ATECC608B Secure Element. Programming is enabled by an onboard PKOB Nano with debug GPIO, USB mass-storage and virtual COM port capability.

In this review, I will detail my experiences with onboarding, creating with and testing of the development board. As this is a brand-new product for which Microchip are seeking real-world feedback, I will flag any issues and hints for resolution with bold text so it stands out from the rest of the review. This way, the feedback is clear but also users may be able to find solutions to their problems more easily.

Introduction & Unboxing

image image

The board arrived in a red Microchip box and claims to be Made in Norway.

image

It contains a Truphone eSIM card, an antenna and the board itself. The latter two are packed in anti-static shielding bags.

image image

The SIM card is a Truphone 150MB/90-day Sequans Trial card in the combination multi-cut form factor. The smallest 4FF (Nano) SIM is what is required. The numbers on the rear are used to identify this card uniquely and are used for the activation process (hence are obscured).

image

The antenna is a Molex 207235 multi-band flexible self-adhesive antenna terminating to a 100mm coax cable leading to a u.FL connector. While the antenna is thin and lightweight, it is also somewhat fragile, so care is necessary while handling.

image

The top of the board looks as above, which is separated into a few sections. Staggered rows of holes are used to allow for solder-less connection to header pins which is convenient. The full schematics are available with the Altium Project and Design Documentation.

image

The left section contains the USB-C connector. The top half contains the charging and power regulation circuitry, with the bottom half containing the debugger connections.

image

The middle section houses the Microchip 25CSM04 4Mbit EEPROM, AVR128DB48 microcontroller, ATECC0608B secure element, MCP9808 temperature sensor and Vishay VEML3328 colour sensor. The right section is home to the Sequans GM02S cellular modem module with the u.FL connector for antenna. A row of indicator LEDs are below the module. There are also two buttons – one user input and the other reset (by default).

There is, however, more than meets the eye. The board actually has two I2C buses – a 1V8 bus mostly used by the ATECC0608B and VEML3328, and a 3V3 bus used by the pin header, Qwiic header and temperature sensor. There are also two rows of connections marked UA1 and UA2 which are connected to two auxiliary UARTs on the GM02S module. Finally, the power section contains cut-strap connections to facilitate measurement of different power nets, however, these are a bit small for comfort due to the Feather-compatible form-factor.

image

The underside is where the nanoSIM socket resides, alongside a footprint for a solderable eSIM. A few test points and JTAG connections are also broken out. The majority of the area is devoted to a cell label which was not provided, but likely would have contained the ID of the board and a QR code for start-up. There is also a solder jumper for AREF-A5 and a polyfuse on the bottom side.

image image

image image

The board has a low profile, assuming you don’t fit header pins. The jumper shunt allows disconnection of VMUX and a convenient place to provide power directly to the board. The JST header also provides a convenient connection to a standard Li-Poly cell, although none is provided in the kit.

According to the RoadTest page and images, it is expected that header pins are provided with the bundle. Unfortunately, in this case, my package did not contain these. Thankfully, they are a standard item that I have plenty of spares on-hand, however, including these may make it easier for first-time users.

Getting Started with the Microchip Sandbox

So that users have something to start with, Microchip has an AWS-based sandbox environment for initial demonstration.

Step 1 – Prepare Hardware

To start requires plugging the antenna onto the board by gently snapping the u.FL connector into place, taking out the Truphone nanoSIM, inserting it into the socket on the rear and then plugging the board into a computer using a USB-C cable. The board should then appear on the computer as a mass storage device.

image image

Opening “CLICK-ME.HTM” will open your browser and redirect to the onboarding process with your particular board’s ID and is part of the first step.

image

Step 2 – Register and Activate SIM

The next step is to make the connectivity work by signing up at Truphone for an account and then activating the SIM.

image

At present, Truphone offers LTE-M only in the above 27 countries. If you are not in the list, then the Truphone SIM will not work for you and you will need a local alternative.

image image

Sign-up is relatively straightforward, taking a few details and verifying your e-mail address.

image image

Activation of the SIM requires the numbers on the card to be entered in. There is no cost, of course.

image

Once activation is complete, you also need to login and set the SIM card status to Active to ensure it will function correctly.

While the included Truphone SIM card is a nice touch for easily getting started with a generous 150MB allowance, the fact it is a 90-day trial SIM is not broadly publicised. I was under the impression that the 150MB provided could be used over a long period (as most IoT projects usually prioritise communication efficiency to reduce costs). Instead, this is likely to result in users needing to spend money to either continue with Truphone or obtain a compatible LTE-M service from another provider (e.g. iBasis, Hologram or directly from local operators). Failing this, the board will lose its cellular connectivity capabilities.

image

The current plan offerings do not look too expensive if your usage is relatively low.

Note that a fellow RoadTester had issues with this step and I helped them by activating their card for them. The cause of this issue was not determined, but it prevented them from accessing the administration section of the Truphone website.

Step 3 – Upgrade Board Firmware

image

The third step is simple – just download a .hex file and drop the file onto the CURIOSITY drive. The board is then programmed with the latest firmware version.

Step 4 – Connect to the Network … or not?

image

At this stage, I should have seen the CELL, CONN and DATA LEDs come up and the onboarding process should have completed.

image

Rather than lighting up in the way that was expected, it lit a red ERROR LED instead and no amount of waiting changed this.

image

The debugging instructions were consulted …

image

Following the debug instructions, I used a serial terminal and didn’t see anything at first. Hitting the reset switch, I managed to get this error message indicating several errors which suggests to me that the secure element may not have been provisioned correctly.

The user manual claims the board is pre-programmed for use with the Microchip Sandbox, but this experience suggests that the programming was incomplete and provisioning of the ATECC608B may not have been successful, resulting in the observed issues.

I attempted to follow the factory reset instructions, but they seemed a little lacking. Installing the IoT Provisioning Tool, I invoked it as instructed:

image

This resulted in ERROR – Operation failed with KeyError: ‘serial_port’. After a bit of poking about, I realised that I had to provide the serial port as a command line argument like so:

image

Then, the board had been completely provisioned.

Connected at Last!

image

After resolving the provisioning issue and restarting the onboarding process, it was possible to get the board to light up in the expected way – including occasional flickers of the amber DATA LED to indicate transactions were occurring.

image

The page also shows two large green banners to indicate your success. Clicking on it allows you to reach the demo page.

image

The demo allows you to log data remotely and toggle the LEDs, but not much more. The temperature reading is incorrect, and this seems to be because the firmware is built for a newer revision of the board with a different I2C address for the sensor. This is, however, not a major issue although if the firmware were just to detect the presence of a sensor instead of assuming it was there, it would be able to auto-detect the correct address.

It would be nice if the sandbox allowed the user to do more than just rudimentary data streaming and LED remote control, as it seems a rather abrupt handover to “now it’s your turn to develop with Arduino”. It is nice that the code that connects to the sandbox is part of the examples, but it is relatively undocumented. There are quite a few courses on the Microchip University webpages, but those appear to be quite general (and long-form video is not ideal either).

Debugging LTE-M Connectivity

Sometimes things may not be working and you may suspect problems with the modem connecting to an LTE-M carrier. In order to troubleshoot this, Microchip recommends the use of the DM-Light Tool from Sequans. Unfortunately, to obtain this tool requires signing up an account and committing to an NDA with Sequans which takes some time but is also something users may not be willing to do. I was, however, prepared to do this for the sake of troubleshooting the prior issue which turned out not to be LTE-M related.

DM-Light Tool

Installation of the DM-Light tool is relatively straightforward – just follow the prompts.

image

In order to use it, you will need to load the UART Bridge firmware to your AVR-IoT Cellular Mini board. It is not as simple as just firing it up though …

image       

… as by default, the modem is not active. You first need to connect to the COM port corresponding to your board at 115200bps and issue the AT+CFUN=1 command as noted in the debug guide in order to put the modem into full functionality mode.

image

After a while, you should see the boxes go green, with the board registered and camped on a cell. If the data session is up, then the board is allocated an IP address and should be ready to communicate. Signal strengths can also be seen on the right.

Unfortunately, DM-Light is not openly available, even though the AT Command Reference has been made available by Microchip. Instead, I would suggest that the tool either be made publicly available with Sequans’ blessing, or a simplified tool by Microchip be made available for users to debug their connections as the AT commands are known.

Another issue is simply the fact that Australia uses Band 28 (700MHz) for its LTE-M and NB-IoT connectivity. The supplied flexible, self-adhesive Molex Antenna unfortunately doesn’t cover this frequency which likely results in sub-optimal performance (reduced range, lower signal strengths). Perhaps providing a u.FL to SMA/RP-SMA pigtail and a proper, full-size multi-band stubby/whip antenna would improve performance and compatibility, at a cost to size. That being said, it is acknowledged that the design of the board is flexible enough to allow for this, should the user wish to provide this themselves. It should be noted that the metal from a breadboard may interfere with the antenna’s radiation pattern, so I would not recommend adhering it to a breadboard!

Oh No! My Antenna!

Around half-way through this RoadTest, I decided to take my board out for an excursion when it suddenly stopped connecting at all. I wondered what was going on, so I took it home and got DM-Light onto the case.

image image

The modem seemed to flicker between WAIT_CELL_ID and WAIT_RSSI. The signal strengths seemed just fine though. I did, however, suspect the antenna may have been damaged by external stresses as I replaced the antenna from a spare in my Molex Antenna Kit and it came back to life!

If you’re seeing the same messages, then check your antenna. It could be the u.FL connector, as it is only rated for 30 cycles and I may have inadvertently damaged it through the debugging process, or the thin flexible metallisation near where the coaxial cable terminates to the antenna.

What about a Regular SIM?

I decided to put in an ordinary Telstra-based SIM that is used for voice and data service. To my surprise, the LTE-M modem was able to make a connection just fine –

image

Testing with an Optus-based SIM didn’t work. I’m not sure whether this is because the modem isn’t finding a strong-enough Optus LTE-M carrier due to the antenna and my location, or whether it is because the SIM itself is barred from registering on the LTE-M carrier. The latter is likely as most regular SIM cards have it in the fine print that it is not for use in M2M applications and LTE-M/NB-IoT capacity is relatively limited. Unfortunately, I don’t have an active Vodafone-based SIM card to see if that was any different.

What about NB-IoT?

At this time, Microchip acknowledges the lack of NB-IoT support in the module due to a lack of firmware. As I am presently testing NB-IoT in my other roles, I decided to test a SIM in the modem just to be sure –

image

Indeed, no connection was possible as the modem tried LTE-M carriers and was denied registration. I did try using the AT+SQNSBANDSEL command manually with a parameter of 1 for NB-IoT (AT+SQNSBANDSEL=1,”standard”,””), but the modem just responded with ERROR. Unfortunately, when the firmware is available, the update will require using the second UART on the GM02S which is broken out on relatively small pads. Updating the firmware will require external hardware, it seems, which is not ideal.

Developing with Arduino & MPLAB

This chapter will look at developing for the AVR-IoT Cellular Mini, including the software set-up and the integrated GPIO debugging capabilities.

Poking Around the Board

The board appears as a USB Mass Storage device and there are several files of note in the root directory. You can, for example, read the device details, device status and even send serial commands.

image image

Aside from the USB to Serial interface, there is also a Debug GPIO interface which provides two logic analyser channels.

Arduino Set-Up

Setting up for Arduino is relatively straightforward, requiring the addition of the DxCore board manager URL into the preferences and installing the DxCore board support package.

image

Support libraries named AVR-IoT-Cellular, AVR-IoT VEML3328 and AVR-IoT MCP9808 also need to be installed through the Library Manager.

image

The board needs to be correctly configured by choosing the settings as shown here. This includes selecting AVR DB-series (no bootloader), AVR128DB48, 2xWire, Master or Slave, your COM port and Programmer -> Curiosity Nano. Additionally, I opted to choose full printf support at a slight cost to RAM to enable printing of floats as well.

Examples – MQTT(S)

There is an example MQTT program which is easy to modify and get started. I had no problems deploying this using a public MQTT broker for testing –

image

I tried to modify the example to connect to a private MQTTS server for which I have the server-side certificate and root certificates for, but does not use client certificates or expect it to be validated. Unfortunately, I could not get it working despite trying both with ECC and without –

image

It seems that MQTTS connections to third-party servers without certificate validation, or with customised certificates, is not something that is demonstrated by the examples or clearly documented. This is valuable to prevent data interception or modification in-flight, but it seems that the current MQTTS arrangement enforces server and client certificate validation and is aimed primarily for use with AWS, Azure or other large cloud providers.

Examples – Power Saving/Sleep

There are examples for a power saving mode and a power down mode, both of which are potentially important for long battery. Unfortunately, while I tried the code directly and incorporated into my own sketches, I was not able to achieve consistent results.

image

The first issue is that it seems that the error message indicating the requested period is not able to be matched (along with a spelling mistake). Attempting to match this and reloading the sketch, the the operator setting seems to change at every connection! This means it is never matched. I’m not sure if this is really an issue with the operator, or a bug in the way PSM itself is handled. Regardless, this means that power saving mode fails to be entered.

image

Trying the example sketch directly results in the board sleeping for much less than the expected time. As a result, I can only conclude that this does not work.

image

Trying the power down mode instead results in the board seemingly crashing and rebooting infinitely. This does not achieve the expected behaviour either. As a result, I can only suggest that significant improvements need to be made to this part of the code.

Arduino Support Caveats

Unfortunately, there are still more things that are noteworthy. For example, this documentation regarding the LEDs had a small, subtle error.

image

This led to a compilation error because Led::CONN is not correct and it should instead be Led::CON instead.

image

Porting other code over to this board doesn’t always succeed either – in this case, using the SPS30 library fails because it seems to make some hard-coded hardware assumptions. While this is not strictly the fault of this board, prospective users should take note that the difference in core on this board may make code that would otherwise run on AVR/ESP8266/ESP32 fail to build for this board.

image

It seems the provided libraries and examples are quite simple and fail to demonstrate some important real-world considerations, such as detecting and recovering robustly from intermittent connectivity in mobile settings and handling network-specific issues with power-saving. The provided libraries and examples also have unusual flakiness – initialising the temperature sensor passes even though the address is wrong, resulting in incorrect temperature readings, the temperature itself seems to be an integer at all times even though the sensor is capable of more (even when the cast to int is removed), reading sensors after a begin() results in stuck or incorrect values without a delay and more. Grappling with these issues cost me a few hours more than I would have liked.

image

Further to this, the libraries fail to demonstrate more complex use cases for which the modem supports, such as post with header parameters which I made a quick hack for a fellow RoadTester to fix, or the use of CoAP/LwM2M connectivity which is increasing in popularity and significance. Finally, there seems to be very little in the way of Arduino-convention being followed – without any direct documentation of GPIO access and not having board definitions to allow the familiar Serial, pinMode() and digitalRead() or digitalWrite() calls, leaves the user to try and reverse-engineer the led_ctrl and logger library to learn how to do this. For a board which seems to target Arduino as the primary development environment, this is not a good idea. I feel that a board-support package targeting this board directly, rather than the AVR chip itself, would be a good idea to reduce manual configuration required, restore Arduino pin conventions and allow for code to be more easily ported. Full use of the ATECC0608B secure element in third-party contexts (i.e. not AWS, etc) would be something I look forward to seeing code for – e.g. to load your own self-signed certificates or other root certificates and have the GM02S use them. Finally, a documented method to send/receive AT commands to the modem may be of value where direct library-based support is not available (e.g. to check LTE-M status).

While it is a good start in the sense the board does allow for development of simple projects in Arduino, it seems that a lot of potential is left on the table. Many improvements to the examples and libraries can be made to improve robustness and add capabilities, while changes to respect Arduino conventions could be made to ease the development process for newcomers. There still seems to be a number of unusual behaviours especially with power saving/sleep modes which may be carrier-dependent but would diminish the appeal of the solution.

MPLAB Data Visualiser – Debug GPIO Data Gateway Interface

To use the debug GPIO channels requires installing the MPLAB Data Visualiser. This can be downloaded and installed separately, although it may just be easier to grab the whole MPLAB X IDE package if you’re intending also to develop with MPLAB X IDE. Installing is a simple matter of following the prompts:

image

The data visualiser itself supports receiving data from serial ports, and from the data gateway interface. Unfortunately, the debug GPIO does not allow you to debug all GPIO pins, just the two that are connected to the debugger. For this board, GPIO0 in the screen is connected to LED4 which is available as D13, while GPIO1 is connected to SW0 input which is also available as D11 on the header pins.

image

It is operable in several modes – change triggers only updates when a change event is measured, while continuous data reads values all the time. The latter mode is slightly slower and does not handle higher change rates very well.

image

Peak performance seems to occur using change triggers mode on just one input – I was able to measure a 5kHz square wave, albeit with occasional glitching. The manual seems to state that 2kHz is the expected practical maximum.

image

Exceeding the capabilities of the debugger results in the acquisition being stopped and this error being thrown. Analysis has to be manually restarted to continue.

image

However, such a feature is not without its own strangeness – stopping and starting acquisition again sometimes results in aliasing and the appearance of a signal with a much lower frequency than expected. While this is a potentially great time-saver for slow-speed logic signal capture, it is no replacement for dedicated test instrumentation.

MPLAB X IDE for Bare Metal?

Bare-metal development is technically supported through the MPLAB X IDE, however, there does not seem to be much guidance around this. Opening the IDE gives an error that no compilers were found –

image

To get around this requires downloading and installing the MPLAB XC8 C Compiler and ensuring that it is added to the PATH variable. This allows a new project to be configured with the necessary settings.

image

Not being too familiar with programming with MPLAB X and seeing the lack of current documentation mentioning this, I decided not to explore this any further. Instead, I continued to use Arduino IDE, as it is “supported” and I am familiar with it, however I would imagine the process to be relatively similar to developing with MPLAB X and other AVR 8-bit/PIC 32-bit devices.

Practical Applications & Testing

Having evaluated the kit, documentation and supporting software, it is now time to evaluate the kit from the point of running practical applications and synthetic tests.

LTE-M Signal Strength and Quality

As the test results do depend to some extent on the LTE-M signal strength and quality, I first decided to assess this for my location to ensure that test results can be correctly interpreted. I used the board with the UART bridge code and wrote my own Python script to poll the modem for data as the DM-Light tool records this data in their own proprietary format. The code is below:

# Monitor Signal Strength on Sequans Monarch 2 Modem
# Use with Microchip AVR-IoT Cellular Mini with UART Pass-through
# Outputs to terminal - pipe to file for later analysis!
# by Gough Lui - October 2022

import serial
import time

ser = serial.Serial("COM32",115200,timeout=0.5)

while True :
  ser.write("AT+SQNMONI=9\r\n".encode())
  time.sleep(0.2)
  while ser.in_waiting > 0 :
    x = ser.readline()
    #print("Read: "+str(x))
    if x[0] == 43 :
      print (str(time.time())+" "+x.decode('utf-8').strip())
  time.sleep(0.6)

Analysing the data showed the following results:

image

While I am literally within 350m of my nearest Telstra mobile tower and have a clear line-of-sight, this modem puts the coverage in the fair-to-good category instead. This may reflect the sub-optimal antenna and the fact that with a SISO radio front-end, the signal will be more vulnerable to propagation effects from multipath fading without diversity from MIMO to compensate. I would say this corresponds to a 3.5- to 4-bars out of 5 signal.

Power Saving Modes

Power measurements were first made using the sandbox firmware installed. This was done by using the Rohde & Schwarz NGM202 power supply and its FastLog capability, recording 500kS/s over the network with the board powered via the VMUX jumper pin and GND.

image

With the unit running 500ms streaming of sensor values, the power peaks at around 1.8W for short periods corresponding to transmissions. Baseline power shifts between 0.2W and 0.56W which may correspond to CPU/modem power states plus LED power consumption.

image

At the end of the data acquisition run, it seems that there is somewhat more data traffic and this keeps the baseline at about 0.56W.

In spite of the previously mentioned issues about getting power-saving modes to operate, I did make a measurement of power with the power saving mode sketch in its broken state.

image

The resulting power shows a similar 0.2W baseline with LEDs off. Peaks of close to 1.8W for transmission are seen, although it seems less time is spent in the 0.56W awake state with only occasional bursts. I would surmise this periodic burst may be the modem waking up for receive time windows. At about 231s, this stops but only for a few seconds before it is woken up again although the cause is not known. The sketch itself was observed to sleep for much less than the expected amount of time with the key culprit perhaps being the network not agreeing on power-saving mode period with the modem.

HTTP Throughput

I tested HTTP throughput with my own VPS server by transferring a 16,384 byte file repeatedly and measuring the time taken from request to response. The Arduino test code is as follows, making use of 1500-byte chunk reads due to RAM and modem limitations.

// HTTP Download Benchmark by Gough Lui
// Microchip AVR-IoT Mini element14 RoadTest - October 2022

#include <Arduino.h>
#include <http_client.h>
#include <led_ctrl.h>
#include <log.h>
#include <lte.h>

#define DOMAIN "INSERT_DOMAIN_HERE"

void setup() {
    LedCtrl.begin();
    LedCtrl.startupCycle();

    Log.begin(115200);
    Log.info("Starting HTTP example");

    // Start LTE modem and connect to the operator
    if (!Lte.begin()) {
        Log.error("Failed to connect to the operator");
        return;
    }

    Log.infof("Connected to operator: %s\r\n", Lte.getOperator().c_str());

    // --- HTTP ---

    Log.info("---- Testing HTTP ----");

    if (!HttpClient.configure(DOMAIN, 80, false)) {
        Log.info("Failed to configure http client\r\n");
    }

    Log.info("Configured to HTTP");
    for (int z=0;z<10;z++) { // Number of Iterations
      HttpResponse response = HttpClient.get("FILE_TO_DOWNLOAD_HERE");
      unsigned long begint = millis();
      //Log.infof("GET - status code: %u, data size: %lu\r\n",
      //          response.status_code,
      //          response.data_size);
      uint32_t datasize,readnbytes;
      datasize=readnbytes=response.data_size;
      char body[1501] = {0};
      //Log.rawf("Body:\r\n");
      while (readnbytes) {
        if (readnbytes>1500) {
          HttpClient.readBody(body,1500);
          //body[1500]='\0';
          readnbytes = readnbytes - 1500;
          //Log.rawf("%s",body);
        } else {
          HttpClient.readBody(body,readnbytes);
          //body[readnbytes]='\0';
          readnbytes = 0;
          //Log.rawf("%s",body);
        }
      }
      unsigned long endt = millis();
      Log.rawf("%lu,%lu,%lu\r\n",datasize,begint,endt);
    }
    Log.infof("Done!\r\n");
}

void loop() {}

The results are as follows:

image

Transfers ranged significantly in time from 1.55s to just shy of 30s. In some cases, the test hung as it seems that above 30s, the modem may just time-out. This suggests download failures may be in part due to transient signal loss.

Regardless, the median time was 1.648s which corresponds to a 9.9kB/s (79.2kbit/s) throughput rate. This is around 86.3% of the 115200bps UART rate which is likely to be a key bottleneck. If the modem was operating at a higher baud rate with the AVR microcontroller, faster speeds may be achievable. This is unlikely to be a major issue in practice, due to the limited computational capability of the AVR 8-bit microcontroller which may prove to be the bottleneck instead.

Latency

Another item of interest was the latency of the connection, given that LTE-M is half-duplex with some low-power optimisations. To test this, the UART bridge firmware was used with the AT+PING=”x.x.x.x”,64 command to ping a host 64 times in a row with 64-byte payloads. This was repeated again for a total of 128 samples per host.

image

Reported times from the GM02S were with a granularity of 10ms, with the second run seemingly showing about an 80ms disadvantage. This may reflect a firmware issue. The first ping of each run did take longer than all others, which may be reflective of the data channel set-up time. In both servers, the ping times averaged around 245ms which is significantly longer than ordinary 4G/LTE which I have measured averaging 28ms to the same hosts via the same carrier and on the same tower. Whether this is due to different routing by Truphone or due to physical layer constraints was not determined.

MQTT with Onboard Sensors

The first test was just to use the onboard sensors to simulate a networked sensor application. Problems with the libraries as previously detailed were encountered, so some workaround delays were used. The code for the “fast” version that sends out messages with measurements as quickly as possible is shown below. This version of the code does not have any power-saving modes enabled.

// MQTT Monitor for Microchip AVR-IoT Cellular Mini Using Internal Sensor
// Without Power Saving Modes - Maximum Speed, LEDs Disabled
// by Gough Lui - October 2022

#include <Arduino.h>
#include <ecc608.h>
#include <led_ctrl.h>
#include <log.h>
#include <lte.h>
#include <mqtt_client.h>
#include <avr/io.h>
#include <mcp9808.h>
#include <sequans_controller.h>
#include <veml3328.h>

#define SW0 PIN_PD2

#define MQTT_SUB_TOPIC "INSERT_TOPIC_NAME_HERE"
#define MQTT_PUB_TOPIC "INSERT_TOPIC_NAME_HERE"

#define MQTT_THING_NAME    "INSERT_CLIENT_ID_HERE"
#define MQTT_BROKER        "INSERT_BROKER_ADDRESS_HERE"
#define MQTT_PORT          1883
#define MQTT_USE_TLS       false
#define MQTT_KEEPALIVE     0
#define MQTT_USE_ECC       false
#define MOSQUITTO_USERNAME ""
#define MOSQUITTO_PASSWORD ""

static uint32_t counter = 0;

void resetViaSWR() {
  _PROTECTED_WRITE(RSTCTRL.SWRR,1);
}

void setup() {
    Log.begin(115200);
    LedCtrl.beginManual();
    LedCtrl.off(Led::CELL);
    LedCtrl.off(Led::CON);
    LedCtrl.off(Led::DATA);
    LedCtrl.off(Led::ERROR);
    LedCtrl.off(Led::USER);

    // Establish LTE connection
    if (!Lte.begin()) {
        Log.error("Failed to connect to operator");
        resetViaSWR();
    }

    // Attempt to connect to the broker
    if (MqttClient.begin(MQTT_THING_NAME,MQTT_BROKER,MQTT_PORT,MQTT_USE_TLS,MQTT_KEEPALIVE,MQTT_USE_ECC,MOSQUITTO_USERNAME,MOSQUITTO_PASSWORD)) {

        Log.infof("Connecting to broker");
        while (!MqttClient.isConnected()) {
            Log.rawf(".");
            delay(500);
        }
        Log.rawf(" OK!\r\n");
    } else {
        Log.rawf("\r\n");
        Log.error("Failed to connect to broker");
        resetViaSWR();
    }
    Mcp9808.begin(0x18);
    Mcp9808.setResolution(res_00625);
    Veml3328.begin();
    delay(500);
}

void loop() {
    int16_t red = Veml3328.getRed();
    int16_t green = Veml3328.getGreen();
    int16_t blue = Veml3328.getBlue();
    int16_t ir = Veml3328.getIR();
    int16_t clear = Veml3328.getClear();
    int celc = Mcp9808.readTempC();
    char message_to_publish[128]={0};
    sprintf(message_to_publish,"%lu,%d,%d,%d,%d,%d,%d",counter,red,green,blue,ir,clear,celc);
    bool publishedSuccessfully = MqttClient.publish(MQTT_PUB_TOPIC,message_to_publish);
    if (publishedSuccessfully) {
        Log.infof("Published message: %s\r\n", message_to_publish);
    } else {
        Log.error("Failed to publish");
        resetViaSWR(); // Lazy Error Recovery
    }
    counter++;
}

I logged the resulting data using the Python paho-mqtt library and my own script running on my VPS which logged the time each message was received and the payload for later analysis.

# Script using Python3 and paho-mqtt to log messages
# for element14 Microchip AVR-IoT Cellular Mini RoadTest
# by Gough Lui - October 2022

import paho.mqtt.client as mqtt
import time

def on_message(client, userdata, message):
    print(str(time.time())+","+str(message.payload.decode("utf-8")))
    f.write(str(time.time())+","+str(message.payload.decode("utf-8"))+"\r\n")
    f.flush()

logfn = input("Log Filename? ")
f = open(logfn,'a')
broker_address="INSERT_BROKER_ADDRESS"
client = mqtt.Client("INSERT_CLIENT_ID")
print("Connecting...")
client.connect(broker_address,keepalive=60) # Simple MQTT Unauthenticated
print("Subscribing to topic...")
client.subscribe("INSERT_TOPIC")
client.on_message=on_message
client.loop_forever()

Testing with and without power saving mode enabled unfortunately revealed instances of connectivity hangs which do not seem to resolve with time. In fact, if the board hangs longer than about 30s, it seems never to recover on its own. To try and get around this, I have tried implementing a software reset in case of failure to publish but that was not enough. I added on a watchdog timer, but that seems only able to go up to 8s, which can cause more resets than absolutely necessary. Unfortunately, the watchdog cannot be enabled during the initial connection to the network which can easily exceed 8s, but this leaves the board vulnerable to hanging if it resets when just out of coverage. Excessive reconnections can cause networks to flag/block your SIM due to the induced network strain, so at this time, so this resolution is not an ideal one.

image image

Looking at the sequential message counters from both the power-saving and non-power-saving versions of the code, it seems that there is no pattern to the resets. The resets could happen due to connectivity issues, or the public MQTT broker going down, however a separate monitoring process I have did not identify any MQTT server outages. The cause may be modem connectivity issues or timeout in completing a message publish to MQTT.

image

Nevertheless, it was possible to measure light intensity per-channel remotely, along with temperature, over the period of a few days which included two overcast days. Night-time illumination is inconsistent due to the room it is in. Temperature readings are integer, due to library limitations mentioned earlier.

image

The fast version of the code did provide much more data over the period of a day. Aside from the issues with connectivity hangs, the board seems to work as expected.

MQTT with External Accelerometer

The project was extended to use an external sensor. At first, I wanted to build a portable particulate monitor sensor, but the idea was scrapped as the library would not build for this board due to some hard-coded hardware expectations of the library. Instead, I opted to use an NXP MMA8451 3-axis accelerometer as the sensor, connected on the 3.3V I2C bus (Wire1). The code was as follows:

// MQTT Accelerometer Monitor for Microchip AVR-IoT Cellular Mini
// Use with NXP MMA8451 Accelerometer - No Library Required!
// Mostly "hacky" code for efficiency, does the job with some error recovery.
// by Gough Lui - October 2022

#include <Arduino.h>
#include <ecc608.h>
#include <led_ctrl.h>
#include <log.h>
#include <lte.h>
#include <mqtt_client.h>
#include <avr/io.h>
#include <mcp9808.h>
#include <sequans_controller.h>
#include <veml3328.h>
#include <Wire.h>

#define MMA_ADDR 0x1C

#define MQTT_SUB_TOPIC "INSERT_TOPIC_NAME_HERE"
#define MQTT_PUB_TOPIC "INSERT_TOPIC_NAME_HERE"

#define MQTT_THING_NAME    "INSERT_CLIENT_ID_HERE"
#define MQTT_BROKER        "INSERT_BROKER_ADDRESS_HERE"
#define MQTT_PORT          1883
#define MQTT_USE_TLS       false
#define MQTT_KEEPALIVE     0
#define MQTT_USE_ECC       false
#define MOSQUITTO_USERNAME ""
#define MOSQUITTO_PASSWORD ""

static uint32_t counter = 0;

void resetViaSWR() {
  _PROTECTED_WRITE(RSTCTRL.SWRR,1);
}

void wdt_enable() {
  _PROTECTED_WRITE(WDT.CTRLA,WDT_PERIOD_8KCLK_gc); // 8s
}

void wdt_reset() {
  __asm__ __volatile__ ("wdr"::);
}

void wdt_disable() {
  _PROTECTED_WRITE(WDT.CTRLA,0);
}

void setup() {
    wdt_disable();
    Log.begin(115200);
    LedCtrl.beginManual();
    LedCtrl.off(Led::CELL);
    LedCtrl.off(Led::CON);
    LedCtrl.off(Led::DATA);
    LedCtrl.off(Led::ERROR);
    LedCtrl.off(Led::USER);

    // Establish LTE connection
    if (!Lte.begin()) {
        Log.error("Failed to connect to operator");
        resetViaSWR();
    }

    // Attempt to connect to the broker
    if (MqttClient.begin(MQTT_THING_NAME,MQTT_BROKER,MQTT_PORT,MQTT_USE_TLS,MQTT_KEEPALIVE,MQTT_USE_ECC,MOSQUITTO_USERNAME,MOSQUITTO_PASSWORD)) {

        Log.infof("Connecting to broker");
        while (!MqttClient.isConnected()) {
            Log.rawf(".");
            delay(500);
        }
        Log.rawf(" OK!\r\n");
    } else {
        Log.rawf("\r\n");
        Log.error("Failed to connect to broker");
        resetViaSWR();
    }
    wdt_enable();
    Wire1.begin();
    Wire1.setClock(400000); // I2C Fast Mode
    Mcp9808.begin(0x18);
    Mcp9808.shutdown();
    Veml3328.begin();
    Veml3328.shutdown();
}

void loop() {
  wdt_reset();
  int accelx;
  int accely;
  int accelz;
  long accelmag;
  long accelsum=0;
  long accelmax=-2147483648;
  long accelmin=2147483647;
  int counts=0;
  unsigned long ltime = millis();
  
  writeRegister8(0x2B,0x40);  // Device Soft RST 
  delay(50);                  // Wait for Reset
  writeRegister8(0x2A,0x00);  // Device Standby
  writeRegister8(0x0E,0x02);  // 8G, No Filt
  writeRegister8(0x2A,0x01);  // Enable Device - looped in case of glitchy connection
    
  while (millis()<ltime+1000) {
    Wire1.beginTransmission(MMA_ADDR);
    Wire1.write(0x00);
    Wire1.endTransmission(false);
    Wire1.requestFrom(MMA_ADDR, 1);
    if(Wire1.read()&(1<<3)) {
      Wire1.beginTransmission(MMA_ADDR);
      Wire1.write(0x01);
      Wire1.endTransmission(false);
      Wire1.requestFrom(MMA_ADDR, 6);
      accelx = (Wire1.read()<<8|Wire1.read());
      accely = (Wire1.read()<<8|Wire1.read());
      accelz = (Wire1.read()<<8|Wire1.read());
      Wire1.endTransmission();

      accelmag = sqrt(pow((long)accelx,2) + pow((long)accely,2) + pow((long)accelz,2));
      if (accelmag > accelmax) {
        accelmax=accelmag;
      }
      if (accelmag < accelmin) {
        accelmin=accelmag;
      }
      accelsum = accelsum + accelmag;
      counts = counts + 1;
    }
  }
  wdt_reset();
  char message_to_publish[128]={0};
  sprintf(message_to_publish,"%lu,%ld,%ld,%ld,%d",counter,accelmax,accelmin,accelsum,counts);
  bool publishedSuccessfully = MqttClient.publish(MQTT_PUB_TOPIC,message_to_publish);
  if (publishedSuccessfully) {
      Log.infof("Published message: %s\r\n", message_to_publish);
  } else {
      Log.error("Failed to publish");
      resetViaSWR(); // Lazy Error Recovery
  }
  wdt_reset();
  counter++;
}

void writeRegister8(uint8_t reg, uint8_t value) {
  Wire1.beginTransmission(MMA_ADDR);
  Wire1.write((uint8_t)reg);
  Wire1.write((uint8_t)(value));
  Wire1.endTransmission();
}

Note that the code deliberately reconfigures the sensor at each reading to defend against power interruptions as it was built on a breadboard and could be subject to shock. The maximum 8g range was used to try and avoid saturation. It computes the acceleration magnitude, sum of readings and count of readings in a one-second period before sending this via MQTT.

image

This was configured with the antenna taped to a cardboard box to elevate it over the breadboard and improve performance. A power bank was used to power the project, however, it was later discovered that during transient connectivity issues, the power can fall low enough for it to shut down, so it was replaced with a ZMI power bank featuring a “low-power” charge mode that keeps the output on for a fixed time instead.

image

This was then packed tight with foam and sealed shut, placed in my backpack as I went around some regular activities. The data was processed to remove the Earth’s gravity and plotted.

image

While walking to the bus stop, the profile seems to show about +1g/-0.5g magnitude. Average remains near zero, as expected, but is a good check of whether there is any sustained accelerations/decelerations greater than 1s or if an axis has saturated.

image

The profile while on a train shows clear stopping phases, with small acceleration phases. The actual g-loads are very subtle, around +/- 0.05g, making it a very smooth ride.

image

A bus ride, however, is much more variable. Aside from the cornering forces, there are also sharp transients from when the bus runs over rough road, including potholes. As a result, the measurements varied between +2g/-1g although the majority of readings were within about +/- 0.3g.

In all cases, loss of data stream occurred and the board rebooted itself due to watchdog or publish failure. While these runs were successful, it was observed during the longer recording that a reboot which occurs when out of coverage results in the board being stuck at attempting to connect to an operator leading to no data being collected. The library may require refinement to improve this situation.

Conclusion

The Microchip AVR-IoT Cellular Mini aims to be an easy-to-use, Arduino-compatible LTE-M-connected development board in the familiar and relatively compact Feather-compatible form-factor. It features the Sequans Monarch 2 GM02S Global Cellular Modem Module, a Microchip AVR128DB48 microcontroller, ATECC0608B secure element, MCP73830 battery charger, MCP9808 temperature sensor, 25CSM04 4Mbit EEPROM, PKOB nano debugger, Molex 207235 antenna and Vishay VEML3328 colour sensor. Connectivity is provided through a Truphone 150MB 90-day trial SIM.

While the solution is more compact and hobbyist-friendly than most, some difficulties were encountered with initial onboarding that appears to stem from incomplete programming from the factory. The provided cellular antenna was not optimal for the Band 28 (700MHz) connectivity in Australia, even though it worked at first, with its fragile form factor succumbing during testing.

Arduino support, while present, did not feel complete nor robust. Much still had to be learned by reverse-engineering the libraries, as many Arduino-conventions cannot be used (e.g. Serial.print(), digitalWrite()) which makes porting code more difficult. The libraries themselves had a number of bugs which resulted in hung readings if there was insufficient delay, and integer-only results from the temperature sensor, with results being provided even if the sensor was not present at the I2C address configured. Power saving and power down modes did not operate correctly, and use of MQTTS without certificate validation or by loading custom certificates is not adequately documented. A minor inconsistency in LED controller documentation is noted as well as an absence of support for more sophisticated use cases even if the modem module itself is capable of it (e.g. large file download, custom headers, CoAP/LwM2M connectivity).

Testing of the debug GPIO capability showed the capability of having two hard-wired logic analyser channels connected to LED4/D13 and D11/PB0. The system is capable of measuring signals up to around 2kHz according to the manual and was able to be pushed to 5kHz in my testing. Unfortunately, as it is hard-wired and has a relatively limited sample rate, it’s really only useful for basic debugging purposes and cannot replace a dedicated logic analyser.

While in use, the potential to have ubiquitous connectivity and data streaming into the cloud was fully apparent. However, the stability of the connection and robustness of the code to recover from poor coverage events and timeouts is definitely lacking, resulting in communication hangs that the board doesn’t recover from. Workarounds using watchdog timers and software resets are not ideal, as the initial connection takes longer than the watchdog period and can hang indefinitely in my experience. It would be nice to have a more robust set of examples and supporting libraries, with a more feature-rich implementation that provides more functions or the documented ability for the users to directly use AT commands in a supported way.

By the end of testing, I had managed to use nearly half of my data allowance with Truphone, showing just how hard I was pushing the modem.

image

This does seem to be a case of the hardware being willing, but the software and documentation still needing some work. It’s not only the Microchip-provided stuff that needs some improvement - the Sequans Monarch 2 also needs new firmware to enable NB-IoT support. Unfortunately, the upgrade seems to require physically connecting to the second UART via the tiny pads on the board, so it won’t be all that simple.

Thanks to element14 and Microchip for selecting me to review the AVR-IoT Cellular Mini Development Board. I hope you found this review interesting, informative or entertaining. If you have any questions, feel free to leave a comment. Otherwise, do like and share this with people who might be interested in this!

Anonymous