Timon Skerutsch is a software and electronics engineer who enjoys the systems design aspect of the work the most, from the cloud all the way down to silicon. He is the founder of the product development consultancy Diodes Delight.

Last year, I made the decision to do a personal prototype project with Zephyr instead of my go-to prototyping choices of Arduino, MicroPython, and CircuitPython. The latter two I still use a lot for rapid prototyping, as scripting languages like Python are hard to beat.

For the forthcoming project, I already knew where I was heading. I needed a sensor for my garden irrigation system that tracks the water level in my water reservoir. I had two requirements:

  • See the water level live on-site
  • Have the data transmitted to the internet so that I can see how things are doing while I’m away

The system regularly had leaks and failures in the irrigation pipes, which caused the automated watering pump to not only waste water but also fail to water my plants. This is detrimental during a heat wave! That added an additional requirement of an alarm to alert me of abnormal situations. When I started the project, I reached for Zephyr first. Let’s talk about why.

Why Arduino, anyway?

Change is a constant; no more so, than the early design phases of a product, when requirements rapidly shift. Prototyping is a crucial aspect of any development process and we often employ different tools for this than we do for our production firmware.

In the firmware world, the Arduino framework has been an immense success. Not only for teaching firmware development, but also as a quick and easy way to try out concepts and develop prototype solutions.

Not without controversy though. To this day, many embedded engineers will utter a silent curse on Arduino whenever it is encountered on the way to production. The supposed prototype firmware has morphed into the production firmware and now that needs to be extended with very complex functionality.

When deadlines are near and the stress levels are high, it is very appealing to companies to just keep using the code base that already seems to do 90% of the job. A lot of products end up shipping firmware based on frameworks like Arduino and then try to deal with the “last 10% of the work”. If you have developed software for a while you probably know those famous last 10% can be 90% of the work, completely derailing budgets and timelines.

But what is the issue? At the end of the day, Arduino is just a very light HAL based on C and C++! You can do whatever you could do in a bare metal C project. The emphasis is on “light”, which is very beneficial when you have only very basic requirements. Maybe you can get by just fine with printf() debugging and hitting that compile button in your IDE.

The Arduino HAL’s success was in part due to its simplicity and fully integrated development flow but it offers very few solutions to the modern challenges firmware developers are facing. When you consider the complexities you are faced with in modern devices, Over-the-Air firmware updates, firmware update encryption, Continuous Integration, connection to a cloud service, tracking of device status and metrics, then things start to look different.

Zephyr is changing things up in the industry

The Zephyr Project Real Time Operating System (RTOS) has seen a lot of adoption over the past years, even by Arduino themselves. They became a member of the Zephyr Project in 2023 and now contribute to the code base.

Zephyr is a very “IoT aware” RTOS and offers a lot of robust solutions to many of the very complex topics I mentioned. It is also one of the main targets of the Golioth Firmware SDK for that reason.

When developers first start interacting with Zephyr they often tend to be a bit intimidated. Device Tree and KConfig may be familiar tools for Embedded Linux developers, but not for someone coming from bare metal C or FreeRTOS. (Editor’s note: this is why Golioth offers free training around Zephyr).

Zephyr-specific tooling like the west meta tool means there’s a lot to learn when you start diving into Zephyr. You might start to question if that work is worth it. Especially early on in a development process where you want to move quickly and prove your concepts. You might feel a huge system like Zephyr could slow you down.

Due to the steep learning curve, Zephyr does not really have a reputation for being a tool for prototyping. But I think Zephyr has very much a place in that phase of a project and it comes with a lot of benefits once you move beyond the prototype: You are already in an environment that won’t hold you back when it comes to solving the tough problems of modern production ready firmware.

Now that I am up the (arguably steep) learning curve associated with Zephyr, I think in many cases I can produce a working solution a lot quicker than with Arduino or even MicroPython.

Not just for production grade firmware

Since I was starting a prototype, I chose an ESP32 dev board I had laying around which came with a nice little OLED screen. For the sensor, I opted for an industrial liquid level sensor. They are essentially pressure sensors in a sturdy form factor that measure the pressure differential of the outside air and the pressure seen in the liquid container.

I needed something rugged and precise to track abnormal water usage so that was a perfect solution. I ended up getting a stable 0.2mm resolution for my water column, much more than I needed. The sensor is a simple 4-20mA current loop that you often see in industrial automation and I connected that to an external precision ADC.

My firmware needs included:

  • WiFi provisioning
  • Network and application protocol to get the data to a server
  • OTA to update the device remotely
  • A GUI to show water levels on the OLED
  • ADC reads to ingest the sensor data

I opted to use Golioth for networking and OTA. While not a typical service for a hobby project, they have a (recently updated) free tier for individuals and it made the whole thing really easy. It only takes a couple lines of code to integrate into any Zephyr project and makes transmitting data to a database as easy as Serial.print(). Having OTA available is a matter of a KConfig option. Most importantly I don’t need to manage an internet facing server application!

net_connect();

golioth_client_t client;
const golioth_client_config_t* client_config = golioth_sample_credentials_get();
client = golioth_client_create(client_config);
golioth_client_register_event_callback(client, on_client_event, NULL);

err = golioth_lightdb_set_int_sync(client, "water-level", water_level/1000, 2);
if (err) {
    LOG_WRN("Failed to transmit water-level: %d", err);
}

I could have directly implemented CoAP or MQTT and host my own server for the receiving side. Both protocols are natively supported by Zephyr, which means I have flexibility if I change my mind on the server side in the future.

OTA firmware updates is also a concept native to Zephyr and very important: no matter what platform I choose! The Arduino ESP32 core has an option for OTA but if you are looking at any other MCU you would have to implement that from scratch which is a whole project in itself.
In Zephyr this is all enabled by the fantastic MCUBoot bootloader.

Abstractions are your friend in a complex world

The platform agnostic nature of Zephyr is powerful. Say you have already written a lot of code and then notice that your chosen MCU does not actually fulfill your needs. You don’t need to start from scratch because all of these advanced APIs are fully abstracted in Zephyr. You can retarget your code to a different platform with minimal code changes. The primary work will be in recreating your devicetree for the new hardware.

Arduino also is known for abstraction, but when it comes to more complex features the Arduino HAL is not defining an interface. Generally, you tend to need to stick to a particular platform if you want to take advantage of the underlying hardware’s fancy features, that is if they are available at all (in Arduino).

Lock-in with a specific IC is a painful lesson we all learned during the chip shortages of 2021 and 2022. Device Tree overlays are a great tool to stay on-top of changing hardware and describe those changes in a clean way. That flexibility is not only important from a risk perspective. Staying flexible during the prototype stage (where requirements change rapidly) allows you to try out different sensors and peripherals.

Changing a sensor in Zephyr is a matter of changing a dozen lines of devicetree definitions without needing to touch a single line of C code. This is made easier when the sensor is “in tree”, but it not the only way to use a new sensor. Devicetree also becomes a powerful tool in the early days of hardware development where your product might go through many revisions and changes. People on your team might be working with different hardware revisions but require the latest bug fixes.

This can quickly become tough to manage in the firmware if you had pin or even IC changes. No need for a ton of #ifdef‘s; all you need is a set of devicetree overlays that describe your various board revisions, the C code can most often stay the same. This not only makes your life easier but also helps reduce mistakes and stale code.

If you are still trying out options you can also interactively work with sensors through the Zephyr Shell, which makes for a great workflow to quickly try out several sensor candidates without writing firmware.

During my project I was unsure whether to choose a different MCU, because the built-in ADC of the ESP32 is quite noisy. In the end, I kept the ESP32 and chose to use an external ADC. My code did not have to change because the ADC API abstracts that away. It was just a matter of defining what ADC my project should use in the devicetree. My code does not need to care if that is an external I2C device or a peripheral internal to my MCU.

/{
    zephyr,user {
        io-channels =
            <&adc_ext 0>;
    };
};

&i2c0 {
    status = "okay";
    adc_ext: mcp3421@68 {
        compatible = "microchip,mcp3421";
        reg = <0x68>;
        #io-channel-cells = <1>;
    };
};

&adc_ext {
    status = "okay";
    channel@0 {
        reg = <0>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,resolution = <18>;
        zephyr,differential;
    };
};

That is the benefit of fully abstracted subsystems, your application’s assumptions can stay the same most of the time. Last minute system changes are less painful during firmware development.

Complex UI’s don’t have to be complex to build

For the GUI, I went with LVGL, a popular UI framework that has been integrated into Zephyr.
That was probably the most eye opening experience to me. Normally you would have to mess with display drivers that all work very differently depending on the plugged in display. Then I would need to write code to manually transfer the rendered framebuffer to that display, which  again, tends to work differently with each display.

In Zephyr all I have to do is to modify the devicetree for which display driver my OLED needs, the resolution, and the bus it is connected to.

&spi3 {
    status = "okay";
    st7789v_st7789v_ttgo_128x64: st7789v@0 {
        compatible = "sitronix,st7789v";
        spi-max-frequency = <20000000>;
        reg = <0>;
        cmd-data-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
        reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
        width = <135>;
        height = <240>;
        x-offset = <53>;
        y-offset = <40>;
        vcom = <0x19>;
        rgb-param = [CD 08 14];
    };
};

With that done you can write powerful UIs with just a couple lines of code, all the hard stuff is handled behind the scenes. I figured the UI part would be the majority of work for this project, but ended up being done in under an hour.

Often Arduino prototypes tend to have character displays or use the same old school bitmap font because fonts are hard and font systems even harder. In LVGL, you have an array of modern fonts available and it’s fairly easy to include your own font.

Arranging elements is also trivial in LVGL. No need to manually calculate a bunch of stuff like your text length. It has a lot of functions available for laying out complex arrangements.
You can build some really pretty smartphone level UIs with it. These run on very constrained hardware and it doesn’t cost you your sanity in the process!

const struct device *display_dev;
display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));

lv_obj_t *level_label;
lv_obj_t *status_label;
static lv_style_t level_style;
lv_style_init(&level_style);
lv_style_set_text_font(&level_style, &lv_font_montserrat_48);

level_label = lv_label_create(lv_scr_act());
lv_obj_align(level_label, LV_ALIGN_CENTER, 0, -20);

status_label = lv_label_create(lv_scr_act());
lv_obj_align(status_label, LV_ALIGN_BOTTOM_MID, 0, -50);
lv_obj_add_style(level_label, &level_style, 0);
// display the current water level
lv_label_set_text_fmt(level_label, "%llu", water_level/1000U);
lv_task_handler();

Quick, once you know how to get around

Within a day I had firmware for my hardware and it even looked…pretty!
Since its creation, my device has dutifully reported the water level and withstood the winter season.

The application is ~180 lines of C code, including a lot of error handling. That is really not a lot of code, for so much complex functionality. This is only possible thanks to all of the available abstractions that make writing the actual application logic a breeze. In the background there are multiple threads running but my code doesn’t even need to be aware of that. It is all handled by the kernel and the well-written libraries.

While simple things like an ADC read can be very verbose in Zephyr and a bit more complicated than in Arduino land, the hard parts–the things we often perceive as the last 10%–are a whole lot easier! You don’t want to start empty handed when you are tasked to implement encrypted firmware updates, OTA, telemetry or integrating the cloud team’s new backend system.

The grass is not always greener, of course. Zephyr is still comparatively young in embedded terms and while there are a lot of devices already supported, it is hard to beat the vast amount of drivers available for Arduino. In some situations you might want to do a first board bring up with an existing Arduino driver before implementing a Zephyr driver. License permitting, the driver code could be the basis for a port to Zephyr.

One reason why I think it is so common for firmware to get “stuck” in Arduino-land is because there has not been a good (free) alternative if you wanted to write C (or C++) and not pigeon hole yourself early on into one specific obscure vendor toolchain. If there is nothing obvious to move to, it can make the decision even harder and it will be put off until it’s usually too late.

Concepts like devicetree and a complex build system like CMake can be daunting at first, but there are ripe benefits at the end of the learning curve. If you want to learn Zephyr, Golioth regularly offers free Zephyr training sessions or you can read some of the great blog posts that cover the more gnarly bits of Zephyr in digestible bite sized portions.

Today, we’re announcing a new Modbus-based reference design targeting industrial vibration monitoring solutions: the Golioth Modbus Vibration Monitor.

Many modern industrial facilities are turning to predictive maintenance strategies to increase uptime and reduce the cost of maintenance programs. Core to these strategies is condition monitoring, a maintenance approach that uses data collected from sensors to continuously monitor machine “health” and predict failures.

For rotating machinery—e.g. motors and turbines—the analysis of vibration data (vibration diagnostics) has proven to be the most effective method of condition monitoring and early fault detection. By continuously comparing the measured vibration signature against the “natural” vibration signature of the equipment, it’s possible to detect premature failure conditions due to shaft misalignment, rotor balance issues, bearing failures, etc.

Modbus Vibration Monitor

In this reference design, we demonstrate how to build a remotely-managed Industrial IoT vibration monitor designed for rotating machinery.

Firmware

The Modbus Vibration Monitor firmware uses the Golioth Zephyr SDK to securely connect to the Golioth Cloud.

Periodically, the device reads temperature and vibration measurements from an off-the-shelf Banner QM30VT industrial vibration sensor using the Modbus protocol.

(Note that with Modbus, it’s possible to target a wide range of different industrial sensors. The Banner sensor is simply a starting point for this example.)

It then streams these vibration measurements directly to the Golioth Cloud over a cellular LTE connection, enabling the device to operate without connecting to internal facility networks.

The firmware source code for this reference design is available on GitHub at the following URL:

https://github.com/golioth/reference-design-modbus-vibration-monitor

Hardware

The vibration monitor hardware is built using the Golioth Aludel Mini prototyping platform. Additionally, it includes the Ostentus front panel featuring an ePaper display for sensor readings, back-lit LED indicators, and capacitive touch buttons.

Inside the box is the custom-designed Aludel carrier board. Specifically, the carrier board integrates a SparkFun nRF9160 Thing Plus cellular LTE module and a MikroE RS485 8 Click board.

The off-the-shelf Banner QM30VT Modbus vibration sensor connects to the Aludel platform via an industrial cabling system with M12 connectors. Although we’re using the QM30VT vibration sensor in this reference design, we can easily connect any other industrial RS-485 sensor to this design using the same M12 connector interface.

Cloud Management

The Golioth Cloud provides all the services needed for deploying and remotely managing a fleet of condition monitoring devices:

  • LightDB State: bidirectional real-time device state database
  • LightDB Stream: database for storing time-series data
  • Logging: centralized device log storage
  • Settings: device settings management
  • OTA: over-the-air firmware updates with one-click rollback

You can manage devices by logging into the Golioth web console, as well as using the REST API or the Command Line Tools.

Data Visualization

The Golioth REST API makes it easy for external applications or services to access the sensor data streamed from devices.

For example, we created a Grafana dashboard that displays the temperature & vibration measurements reported by each device:

Build it yourself

What’s more, you can build your own Modbus Vibration Monitor using widely available off-the-shelf development boards from our partners!

We call this Follow-Along Hardware, and we think it’s one of the easiest ways to get started building an IoT proof-of-concept with Golioth.

Specifically, you will learn how to assemble the hardware, flash a pre-built firmware image onto the device, and connect to the Golioth cloud in minutes. The follow-along hardware runs the same open-source firmware as the custom Golioth hardware described above. We also provide instructions for building the firmware yourself if you want to make changes for your specific application.

We are releasing the nRF9160 DK Follow-Along Hardware Guide today, and plan to add support for additional development kits soon.

Project Page

For detailed information about the Modbus Vibration Monitor reference design, check out the project page at the following URL:

https://projects.golioth.io/reference-designs/modbus-vibration-monitor/

Additionally, you can drop us a note on our Forum if you have questions about this design.

Finally, if you would like a demo of this reference design, contact [email protected].

Nordic’s nRF9160 cellular modem includes a great peripheral called the Key Management Unit (KMU). This secure key storage mechanism lets you write keys to it which cannot be read back. However, they can still be used for DTLS authentication. In this video and blog post I’ll walk you through how to use the feature with the newest release of the Golioth Firmware SDK.

Overview of secure storage and TLS Tag authentication

With the v0.10.0 release of the Golioth Firmware SDK, credentials may be selected using the TLS secure tag. One example of hardware that embraces this is the Nordic nRF9160, which implements Zephyr’s TLS credential management API. Credentials (either x509 certificates or pre-shared keys) are stored on the device using a security tag. Pass that tag to the Golioth Firmware SDK and enable offloaded DTLS sockets in order to utilize those securely stored secrets.

Since these credentials are stored separately from firmware, they are persistent and you can store multiple different credentials. At runtime, pass the security tag as a parameter when creating the Golioth client and you’re all set.

How to store credentials on the nRF9160

Storing credentials on the nRF9160 is accomplished in two steps: first generate and prepare the credentials, then place them on the device using AT commands. (Don’t worry, there are helper tools to generate the AT commands for you.)

Generating Certificates

Golioth has long supported certificate authentication. You can follow the Certificate Authentication guide in our Docs. You will need to use the .pem version of the device certificate and key, and you’ll also need the root certificate from the CA that issued Golioth’s server certificate (we use LetsEncrypt.org).

  1. Generate the root certificate and device certificate by following the docs page.
  2. Download the CA certificate from Let’s Encrypt

Now upload the public root certificate you generated (golioth.crt.pem) to Golioth so it may be used to authenticate your device. From the left sidebar choose Project Settings, select the Certificates tab, and click Add CA Certificate:

Upload public root certificate to Golioth

Generating PSK Credentials

You should not use PSK credentials for production purposes, certificates are far more secure. However, for demonstration purposes, here’s what you need to do to prepare your PSK:

  1. Use the Golioth console to add a new device.
  2. Copy the PSK-ID and PSK from your newly generated device.
  3. Use the following command to format your PSK as a HEX string—the format required by the nRF9160 (note this is only for the PSK, not for the PSK-ID).
echo "your-psk-here" | tr -d '\n' | xxd -ps -c 200

Loading Credentials onto the nRF9160

  1. Build and flash the Nordic at_client sample onto your device.
  2. Use the Nordic nRF Connect for Desktop tools to write credentials to the device.
    1. Older versions of this tool will use the LTE Link Monitor, newer versions will use the Cellular Monitor.
    2. Choose the security tag you wish to use.
    3. Add your credentials to the interface and use the Update certificates button to write to the device. I found that I wasn’t able to write all three certificate artifacts at the same time and instead needed to enter them one at a time.

Nordic Cellular Monitor used to store device credentials on nRF9160

The credentials are stored using AT commands over a serial connection. You do not need to use the Nordic desktop tools if you don’t care to as the commands can be sent from any serial terminal connection.

Configure Golioth to locate credentials by tag

Now that our credentials are stored on the device, it is a trivial process to adapt the Golioth client to use them. In the video, I stored my certificates at security tag 24. I simply pass this to my application by adding the following Kconfig symbols to the prj.conf file:

CONFIG_GOLIOTH_AUTH_METHOD_CERT=y
CONFIG_GOLIOTH_SAMPLE_AUTH_TYPE_TAG=y
CONFIG_GOLIOTH_COAP_CLIENT_CREDENTIALS_TAG=24

(If you are testing PSK authentication instead of certificates, do not use the Kconfig symbol that sets CERT as the auth method. Without it, PSK will be selected by default.)

You must also remove one symbol from the boards/nrf9160dk_nrf9160_ns.conf file. This symbol tells the application to skip the offloaded DTLS sockets, however, that’s exactly the feature we want when using tag-based credential selection. Remove this line to re-enable socket offloading:

# Remove this line from nrf9160dk_nrf9160_ns.conf
CONFIG_NET_SOCKETS_TLS_PRIORITY=35

With that in place, compile the application and flash it to your nRF9160. It will now use the stored credentials to authenticate with Golioth.

Understanding the Golioth client config

The Golioth samples are configured to use a common library that configures the Golioth client on your behalf. However, the configuration process is very simple as I demonstrated it in the video.

Create a config struct that chooses TLS tags. Use the struct to pass the security number where the credentials are stored. Here’s what that would look like for my credential authentication example:

/* Config for credential tag authentication */
struct golioth_client_config client_config = {
    .credentials =
        {
            .auth_type = GOLIOTH_TLS_AUTH_TYPE_TAG,
            .tag = 24,
        },
};

client = golioth_client_create(&client_config);

Device Credentials with Golioth

The new APIs present in the Golioth Firmware SDK make it really easy to select credentials using tags. We’d love to hear how you plan to utilize this functionality. Show off your project on the Golioth Forum, or hit us up at the DevRel email!

An Internet of Things (IoT) device is a special snowflake of a device (seasonal reference, happy holidays!). It has many more requirements than a piece of hardware that doesn’t connect to the internet. In this post (and the video above), we talk through pitfalls when manufacturing a new piece of electronics. One topic that is particularly important in the IoT space is the provisioning process once a piece of hardware has been manufactured. As it so happens, this is a strength of Macrofab and Golioth working together.

What is Macrofab?

Macrofab is an online service that helps engineers manufacture electronics without the normal back-and-forth with traditional Contract Manufacturers (CMs). They are a web layer on top of two different resources:

  • Their own in-house manufacturing, based out of Houston
  • A range of different CMs, of increasing size and capabilities as you scale

As you decide to build more and more devices, your assembly will be built by larger and larger manufacturing outlets, without any interruption to the workflow that you’re used to. One benefit that I like, and one discussed in the video, is the ability to view different price breaks on an assembled board. Entering different numbers of desired assemblies will trigger recalculation of the end price and lead times:

Pricing 1 unit vs 100 units at Macrofab

Macrofab prices out parts and take things into consideration such as the price break of individual components, as well as targeting different scale manufacturing capabilities (again, all invisible to the user). They have calculated the “per part” cost of attaching the part to a board as well—an 0603 resistor costs less per part than a more complex BGA component which costs less than a hand-soldered connector.

I spoke with Brenden Duncombe, who is the Director of Customer Engineering at MacroFab. On any given day you might find him working with a customer on test fixtures, or helping to improve Macrofab capabilities to make a more seamless hardware ordering experience.

What we are building

You can see an early look at the Aludel Elixir in the video (please note this is Rev A and subject to change…including soldermask color!), but we’re creating a test platform for our reference designs. The Elixir’s predecessor, the Aludel Mini, is featured in many Golioth Reference Design videos and project pages, but it is a combination of different off-the shelf development boards that requires a lot of hand soldering. We wanted something that can be produced in higher volume, as well as including additional hardware that isn’t present on some of the off-the-shelf boards that are available (including extra GPIOs).

 

One benefit for you, the reader, is we will be showcasing a more holistic picture of what it looks like to build an IoT device for production. We still employ Mikroelectronica Click boards to tap into the flexibility of that ecosystem. But more sensors are included “by default” on this board to increase capabilities. We still provide multiple build targets in our reference design repositories, in order to allow people to use entirely off-the-shelf hardware in their own evaluation. We call this “Follow Along Hardware“.

When it came time to build up some early prototypes, Macrofab immediately sprung to mind. I wanted to be able to get budgetary pricing and make decisions around including different parts in a dynamic fashion. I also wanted to hand over the design and feel comfortable sitting back and letting someone else do the work.

Special considerations with IoT

When your electronics assembly rolls off the line and passes all tests…then what? For many test devices we work on at Golioth offices, the next step is to program in a PSK-ID and PSK. That’s an easy way to provision a new device. Also an easy way to re-provision/change things later, which is great in the prototyping stage. Once you get to production, your requirements change. Sure, you get security by default with Golioth, but you also get efficiency and hands-off provisioning onto the Golioth cloud. That’s where certificates come into play. Programming certificates into your brand new devices allows the device to present credentials the first time it connects to Golioth and a new record is created for that device.

Future Testing and BEOL

The “back end of line” (BEOL) testing is something engineers don’t think about unless they are deep into production, but could benefit from some early planning. One thing that Brenden brought up many times was the importance of creating a test fixture from the early days of a prototype. This includes having copious test points and programming pins on your PCB. This is a step that I thought I could skip because I was on my Rev A hardware. I see the value he is mentioning about reliable, standardized testing from day one. As I move into the next revision of hardware, this will be a major consideration, both for at the factory during assembly and once the boards are on my bench trying out new capabilities.

Other elements we’ll be looking into and writing about are things like serialization (adding a serial number to devices) and adding certificates onto devices being made. Golioth doesn’t sell hardware directly, but we expect to be building many more reference designs in the new year. It will make sense to follow our own advice and make a “product”, even if it’s only an internal one.

CMs that have many layers of service

We know and love many CMs in the electronics ecosystem. But we find ourselves gravitating towards the ones that have a structured approach to taking products to market and strong backgrounds in helping engineers build reliable products. We think both of these elements mesh well with Golioth’s principles. If you’re interested in building your next prototype with Macrofab, check out their online capabilities and get started today.

In the last blog post about the PPK2,we explained operating modes for embedded devices and how current consumption is generally measured. With Nordic’s Power Profiler Kit II, we were successful in reducing the current draw of Golioth’s hello sample by a factor of 10 by simply turning the modem off. But, truth be told, 4mA is still a significant current draw for battery-operated devices in Standby mode. The aim for today is to lower the current consumption even more.

General Power Saving Recommendations

Let’s discuss some general recommendations for lowering current consumption. Every device/product has a set of constraints. From the sensor reading period to the number of sensors connected to the MCU, the current consumption for your particular device may vary based on which function you are performing and how much you are asking of your device.

Disable Unused peripherals

Some peripherals are enabled by default, depending on the devicetree of the board you are using. Peripherals that are not in use should be disabled in the overlay file. Even though it might not seem obvious at first,  some peripherals could potentially draw current just by being enabled. And the result could be milliamps of unnecessary current draw.

Peripherals are enabled or disabled in the device overlay file. For the hello sample, we won’t use any of the peripherals, and we’ll disable them all in the nrf9160dk_nrf9160_ns.overlay file.

You only need to disable the peripherals which are not utilized in your project. You can use the Device Power Management module to put peripherals into sleep mode in inactivity periods; more about that later on.

Disable Serial Logging

By default, logging is performed over the serial port associated with the UART(E) peripheral with Nordic SoCs. If a device is expected to work without human interaction over the serial port, then there is no need for logging over serial output and having the associated current consumption. By doing this, we can reduce the current consumption by ~1mA.

  • Disable serial output with: CONFIG_SERIAL=n
  • Disable serial logging with: CONFIG_LOG=n
  • Disable the UART console with: CONFIG_UART_CONSOLE=n

For the purposes of the hello sample, we won’t disable the logging subsystem because we want the log messages to be sent to Golioth’s Logging device service, but we have disabled the uart0 peripheral, which is used as a serial console by default.

Enabling Device Power Management

The idea behind the Device Power Management module is to allow device drivers to handle power management operations. For instance, it turns off clocks and peripherals, lowering the current consumption. The Device PM module provides an interface that the device drivers use to be informed about entering the suspended state or resuming from the suspended state. This enables the application developer to suspend peripherals when the CPU goes to sleep, depending on the application’s behavior.

For example, we can turn of an SPI peripheral while it is not in use to reduce the current draw. A device driver must have an implementation of the PM action callback used by the PM subsystem to suspend or resume devices.

Since we won’t use any of the nRF9160 SoC peripherals in the hello sample, we won’t see any benefit from using the Device PM. Nordic’s documentation explains how to utilize the PM module on the external flash case.

Results

As in the previous blog post, we are going to connect to the cellular tower, Golioth Cloud, and send 5 hello messages; afterward, we’ll stop the Golioth system client and call the lte_lc_offline API function, which sets the device to flight mode, disabling both transmit and receive RF circuits and deactivating LTE and GNSS services.

 

From the picture above, we achieved an average current of 2.69 µA when all peripherals are disabled, the modem is turned off, and the CPU is in IDLE. It’s up to the application developer to decide when to enter this minimal operating state, and deal with the consequences when coming back online after this deep sleep. Things like ConnectionID can help cellular devices save power on handshakes with the tower when re-connecting.

Conclusion

We showed how disabling unused peripherals can benefit our current consumption bottom line and save milliamps in the process by achieving ~3uA current draw. In the next blog post, we’ll talk about Power Optimizations specific to the nRF9160 SoC and how to use Power Saving Mode (PSM) with the modem and eDRX method instead of turning the modem off completely.

Golioth’s newest Zephyr support is now part of our cross-platform Golioth Firmware SDK. Yes, we have always supported Zephyr. This latest development includes our top-tier Zephyr offering alongside the other platforms we support–all in one single software development kit.

We want to hear what you think of the new Zephyr support. Right now we’re in the beta release, but we are rapidly moving toward general availability in the new year. Give it a try and let us know what you think, as we are currently making improvements based on feedback from early testers. Please send your thoughts to [email protected].

How to test Zephyr with the Golioth Firmware SDK

Using the new beta support will feel very familiar. Follow our Zephyr readme which will guide you through setting up your own Golioth Zephyr workspace, or adding Golioth to an existing Zephyr project. The SDK is installed to modules/lib/golioth-firmware-sdk folder and immediately available to your applications.

Where the newest changes become most apparent is in the APIs. While the same great APIs are still available, everything is a little easier to get up and running, and there are many additional helper API calls, like dedicated functions for pushing specific data types (int, bool, string, etc.) up to Golioth without the need to first format them as JSON or CBOR.

Chris and Mike cover many of these changes in the video above, however, you may want to spend some time perusing the Golioth Firmware SDK documentation as well. For anyone wanting to look at everything under the sun, the Doxygen reference is for you.

Why the Change?

First off, this is in addition to our existing Golioth Zephyr SDK, which will continue to work with Golioth. A full writeup on the new beta support is a good place to look for background on our motivations. But one of the biggest reasons is making sure that all of the platforms we support immediately benefit from our testing and development cycles. By collecting all of the Golioth device SDKs under one repository, we are able to deliver new features everywhere at the same time.

This is a dual benefit to you when Golioth rolls out something new. You know that both the cloud side and the device side have been tested and proven to live up to our very high standards. Since all of the ports are now under the same API, you will never have to wait for these features to make it into the SDK you are using, you’ll get them on the day they release, every time!

We Won’t Be in Beta for Long

Golioth solicited feedback from our ambassadors and other close partners as soon as the beta support was released. We’ve already been adding improvements from the early round of testing and continue to do so. But we’re eager for you to give it a try today. Please send your thoughts on the overall experience, the API, the architecture, and anything else that comes to mind. It will be invaluable to us as we move toward a wide release at the beginning of 2024.

Golioth Reference Designs now include purchasable hardware setups that mirror all functionality on our custom hardware solution. Utilize Golioth firmware and cloud together to showcase complex IoT applications in minutes!

Compact designs have custom elements

Golioth Reference Designs help to showcase end-to-end IoT applications using quasi-custom hardware. If you’ve seen any of our articles or our guides on projects.golioth.io, you have probably seen a setup that looks something like this:

The Cold Chain Asset Tracker with an open case

This is a stackup of a custom board (the “Aludel Mini”) that ties together a battery, ClickBus based sensor boards, a custom display made out of a PCB (the “Ostentus”), switches, buttons, antennas, and off-the-shelf devboards with processing and connectivity (the “Sparkfun ThingPlus nRF9160”). These are all placed inside a case with cutouts where we can insert custom 3D printed panels to fit whichever Click boards we’re using. This creates a relatively compact package, at least given that it can be reused across a range of different ideas:

The Golioth Cold Chain Asset Tracker with an open case: It’s not the smallest form factor possible, but it’s also not a mess of wires and devboards glued together.

Golioth is well tailored to users who make their own custom hardware. Unlike other cloud platforms, we don’t lock you into using a module you can only buy from us. Instead, we publish an SDK that can be used across a range of supported hardware and connectivity types. You can put just about any type of connected embedded device onto the Golioth Cloud.

However, there’s a problem if you want to re-create the Reference Designs pictured above: You can’t buy the custom hardware setup that we use!

What if you want to follow along?

Keen readers of this blog will note that we just open-sourced the firmware for our Reference Designs, including the template we use to create our designs. That’s only really useful if you have hardware to run it on. Since you can’t buy all of the hardware that we showcase, how can you benefit from the open source firmware? We now have an accessible, alternative option for you.

The Hardware

Follow-Along Hardware is the full set of development boards, interface boards, sensor modules, and helper items to replicate the setup that we use at Golioth.

We take advantage of the fact that many vendor development boards (still?) utilize an Arduino Uno pinout on their larger development boards. There is a conversion board that goes from Arduino Uno to 2 Click headers, which is the form factor of the majority of sensors and peripherals we integrate into our Reference Designs.

The OBD-II / CAN Asset Tracker Design, assembled on top of the Nordic Semiconductor nRF9160-DK

The Firmware

In order to support both the custom hardware shown in the photos above, we lean on the portability of the Zephyr Real Time Operating System (RTOS) and ecosystem. Because the Aludel Mini and the nRF9160-DK both have the same chipset on them, we can write a new set of board files that target the pin differences between these two boards. The flexible “fabric” of the nRF9160 (the SIP on both of these boards) allows the pins to be reassigned, as needed. The difference in build commands in Zephyr is as simple as:

# Build for Nordic nRF9160 Development Kit:
$ west build -p -b nrf9160dk_nrf9160_ns app

# Build for custom Golioth hardware:
$ west build -p -b aludel_mini_v1_sparkfun9160_ns app

These two commands will target their respective hardware.

For the “optional” modules that are part of the quasi-custom hardware solution–like the Ostentus display with an eInk screen and touch buttons–we check at runtime whether the module is present. If you’re running on an nRF9160-DK without the display (maybe you’re looking at data output on the serial terminal), the program will disengage the code that runs the Ostentus until the device is reset.

Try before compiling

We want to make it so easy to try out these Reference Designs that have a Follow-Along Hardware component, that we don’t make you compile anything. Each supported piece of hardware (on a per-project basis) also includes a pre-compiled image in the associated firmware repository. If you follow the directions for your hardware, you will have a fully functional project on your bench in a few minutes. Then you can start to customize to your heart’s desire.

More Reference Designs

We are dedicated to supporting hardware and firmware engineering teams building real-world applications. A custom piece of hardware has a ton of challenges, but Golioth makes sure that cloud connectivity and device management are an easy checkbox on your list. If you are working on an application you don’t see covered on our Projects site, drop us a line and we’ll see if we can spin up a new design. You’re always welcome to stop by our forum to discuss your IoT application, as well.

We always recommend connecting ESP32 devices to the Golioth Cloud with the Golioth Firmware SDK. We believe that is the lowest friction way of connecting a device to the internet. But sometimes I want to get under the hood and tinker, and I thought you might like to see how that works as well. We sometimes run into platforms that aren’t yet supported in Golioth, or have other requirements that means they would need to communicate directly to our CoAP endpoints. So in this post, I will demonstrate how to send data to Golioth’s LightDB Stream and LightDB State using only the ESP-IDF, not the Golioth Firmware SDK.

We previously had shown how to connect to Golioth’s hello CoAP endpoint using an ESP32, which sends back a hello message every time the device connects to it. This post will build on that progress, so if you’d like to follow along, check out the setup that Miguel detailed in that post.

Sending Data to LightDB State

LightDB State is Golioth’s state-based database service, used for tracking an application’s resource state. In the last post, the CoAP endpoint was: `coaps://coap.golioth.net/hello` In order to send set or get resource state, we need to change the CoAP endpoint from coaps://coap.golioth.io/hello to coaps://coap.golioth.io/.d/{path=**}, where path can be any valid URI sub path.

Now let’s change the example code according to the comments on line 431 in the coap_client_example_main.c.

Variable idx will increment every time the while loop is executed (every 10 seconds), and the change to the value of idx will be visible in the Golioth Console.

Observe the server’s OK response in the terminal:

Sending Data to LightDB Stream

LightDB Stream is Golioth’s persistent time-series database service, which records data that can be extracted using our Cloud REST API or Output Streams.

In this minimum configuration, to send data to LightDB Stream, we only need to change the CoAP endpoint to: coaps://coap.golioth.io/.s/{path=**}, where path can be any valid URI sub path.

Notice how with the LightDB Stream there is a history for variable value, with the addition of a timestamp added by our server when it receives the data. Try to change the example and add a timestamp to the payload.

Conclusion

While the Golioth Firmware SDK turns data transmission into a single-line API call from ESP-IDF, this post shows how accessible it can be to publish data directly to a CoAP endpoint using some of the built in tooling.

Now it’s your turn. Try out Golioth’s examples lightdb and lightdb_stream to see how we abstracted and simplified the connection to the Cloud. You can always peek under the hood to check how we did it.

It’s a tale as old as IoT. You get a project with a cellular connection working, but when you move to a different physical location, all of a sudden you cannot connect to the internet. You know your network provider has cellular coverage in the area, and your SIM card is paid up. So why is data not working?

While there are a number of carriers that offer nearly global coverage, not all coverage is the same. IoT devices generally use the NB-IoT or the LTE-M standard. Each is different and has different use cases. Golioth is your instant IoT cloud, and works with devices using either standard. Let’s learn more about what the differences are and how to use them in your IoT projects.

NB-IoT vs. LTE-M

NB-IoT stands for Narrowband IoT. It is a low-power wide-area network (LPWAN) radio technology standard developed by 3GPP for cellular network devices. NB-IoT uses a subset of the LTE standard, but limits the bandwidth to a single narrow-band of 200kHz. It’s suitable for applications that require more frequent communication with the backend (cloud), and it doesn’t support tower handoff. NB-IoT is suitable for stationary devices, such as smart metering devices.

On the other hand, LTE-M standard is designed to transfer low-to-medium amounts of data (200-400 kbps) across a wide geographical range and supports cellular tower handoff. LTE-M is suitable for mobile applications such as asset tracking and fleet management.

There are a couple of older standards you may remember hearing about. Largely these have been grouped into the two mentioned above. LTE Cat-M1 is part of the LTE-M standard. LTE Cat-NB1 and Cat-NB2 are part of the NB-IoT standard.

Cellular World Coverage

Screenshot of an interactive world map of NB-Iot and LTE-M coverage from gmsa.com

Click the image to open an interactive map of NB-Iot/LTE-M coverage at gmsa.com

Depending on your location, you might have NB-IoT or LTE-M coverage. Some areas of the world have coverage for both standards, so choosing which one to use can be challenging. Check the interactive map at GSMA to see how your country is adopting for the future.

Switch Between Cellular Standard in Zephyr

Nordic’s nRF Connect SDK (based on Zephyr RTOS) offers an elegant and simple way of prioritising the connection standard. A pair of network mode Kconfig symbols are available when building for the Nordic nRF9160 cellular modem.

By defining the CONFIG_LTE_NETWORK_MODE_NBIOT symbol in board-specific conf files, the NB-IoT cellular standard will be preferred. On the other hand, CONFIG_LTE_NETWORK_MODE_LTE_M will prioritise the LTE-M standard.

Try including one of these KConfig symbols in your application, and compare the differences in connection time when connecting to Golioth.

# Prioritise NB-IoT
CONFIG_LTE_NETWORK_MODE_NBIOT=y

# Prioritise LTE-M
CONFIG_LTE_NETWORK_MODE_LTE_M=y

Conclusion

In this blog post we talked about differences between NB-IoT and LTE-M standards and how to prefer one over the other in the Zephyr ecosystem. In the next blog post, we’ll investigate automatic switching between NB-IoT and LTE-M, connection time-out, and how Zephyr RTOS handles all of that.

Get your IoT fleet started today. With the Golioth Dev Tier your first 50 devices are free, so try Golioth now!

IoT projects and products fail at a spectacularly high rate; not in the field, but by never making it out of the lab. One of the myriad reasons is time to market. When you have a fixed amount of time to make an idea work and deliver that product to the marketplace, you don’t get a lot of retries. That’s why I gave this talk about how to get the most out of your “Rev A” (first revision of) hardware. It was delivered as one of the free talks from the Embedded Online Conference (EOC) in 2023. You can view this and many other highly specialized talks on the EOC site. Registration is required for viewing the other free talks and there is a nominal fee to join the site and view the talks from this year and last year.

Balancing Act

Why not “move fast and break things”? Why bother caring about Rev A? Despite reduced costs around hardware thanks to quick turn manufacturing services domestic and abroad, it’s possible to get hardware fast…but there is still a delay between a Rev A and Rev B board. What’s more, the decisions you make in your early hardware prototypes can carry with you throughout the life of a product, and it makes sense to shoot for a best-case scenario when planning and executing your first spin of a prototype. This talk covered three areas of the prototype process.

Before Rev A

The “before” is all about planning, especially across different teams. Hardware designers for IoT products need to make sure they communicate properly with their firmware and cloud teams, in order to maintain good expectations. A written plan about what you’re hoping to get out of the Rev A prototype and how to maximize the testing of that prototype will ensure you don’t waste or duplicate efforts later. Design reviews are a crucial component to allow different teams to voice their needs before manufacturing.

During Rev A

Once your prototype is planned, designed, and manufactured, you need to execute on your testing plan. Your testing methods will help you to understand when a prototype has met or missed goals set during planning. This part of the talk also reviews some testing tools that can help teams get more data from their prototype device.

After Rev A

Once you have thoroughly tested your Rev A prototype, a post-mortem of what went wrong (and right) is crucial. It will ensure you improve your process (for future Rev A prototypes) and also capture all of the needed changes for a Rev B prototype.

Case Study

Golioth does not build and sell finished hardware products.  But we do regularly create “Rev A” hardware when we create different Reference Designs. These are built to help accelerate teams looking to build an end product but wouldn’t mind benefiting from someone else showing how to build the first spin of a design. Our Reference Designs are built on top of a prototyping platform we created that attempts to balance flexibility, a quasi-finished look, and a relatively compact design. None of these categories are super optimized, as that is left up to the user hoping to build a finished product.

We’re always looking for new Reference Designs to build to help accelerate engineers’ Rev A prototypes. If you have any requests or need help building out your prototype, let us know on our forum or drop us a note.

Conference Talk Slides