Predict Power Demand from M5 Stack using Soracom Beam and Amazon SageMaker

Hey there! My name is Taketo, and I’m a Solution Architect here at Soracom.

Today, I want to share a new and exciting integration that’s been making waves in the tech world. I’m talking about integrating Amazon SageMaker with Soracom Beam , a data transfer service that is now compatible with AWS Signature V4 .

With the integration of Amazon SageMaker and Soracom Beam, you no longer have to worry about managing authentication information and SigV4 generation logic on your device. This makes it possible for your devices to send data to Amazon SageMaker without aws credentials and integrate AI features into your devices. For example, you can easily predict some statistics with Amazon SageMaker Endpoints.

It is that latter feature that this blog will focus on. Together, we’ll take a closer look at how microcontrollers M5Stack can be integrated with Amazon SageMaker. So, let’s get started!

Architecture Overview

Let’s look at the system architecture first.
M5Stack sends data to Amazon SageMaker via Soracom Beam. In this step, Soracom Beam will receive HTTP traffic without TLS encryption and forward them to Amazon SageMaker WITH TLS encription. And Soracom Beam will add SigV4 Authentication header in requests to Amazon SageMaker.

Next, I will show you the hardweare architecture below.

M5Stack captures Humidity, Temperature and Pressure with ENV Ⅲsensor and send data to Soracom Beam with 3G extension board.

How to Set Up Environments

So now let’s create your environment!

Build AI Model With Amazon SageMaker

Please follow the topic Soracom SigV4 Linkage and Inference with Amazon SageMaker to create your endpoint. By this configuration HTTP traffics from your cellular devices to Soracom Beam are forwarded to Amazon SageMaker Endpoint, for example, with AWS authentication headers.

:warning: In this example, the model is optimised for weather condition in Tokyo base on real data in December 2022. You may get low accuracy for your prediction depending on your climate environment.

Configure M5 Stack

  1. Please install the following softwares in your Arduino IDE.
  1. Create a new sketch and install it in your M5Stack
#include <M5Stack.h>

//Libraries for cellular connectivity
#include <TinyGsmClient.h>
#include <HTTPClient.h>
#include <ArduinoHttpClient.h>

//Libraries for sensor
#include "UNIT_ENV.h"

TinyGsm modem(Serial2); 
TinyGsmClient ctx(modem);

const char* beamServerAddress = "";
const int beamPort = 18080;
const String powerModelName = "sagemaker-xgboost-2023-02-28-00-54-23-394";

const char* clockServerAddress = "";
const int clockServerPort = 80;
const String datetime_prefix = "datetime: ";
SHT3X sht30;
QMP6988 qmp6988;

void setup() {

  M5.Lcd.println("M5Stack Now Powered On");

  //Initializing the modem and configure APN
  M5.Lcd.print("Restarting Modem...");
  Serial2.begin(115200, SERIAL_8N1, 16, 17);

  M5.Lcd.print("Modem Info:");
  String modemInfo = modem.getModemInfo();

  M5.Lcd.print("Waiting to be registered..");
  while (!modem.waitForNetwork()) M5.Lcd.print(".");

  M5.Lcd.print("Creating PDP context with APN");
  modem.gprsConnect("", "sora", "sora");

  M5.Lcd.print("Connecting to the network..");
  while (!modem.isNetworkConnected()) M5.Lcd.print(".");

  M5.Lcd.print("My IP addr:");
  IPAddress ipaddr = modem.localIP();
  //Initializing the sensor


void loop() {

  //1.Get hour
  M5.Lcd.setCursor(0, 0);
  String datetime = get_datetime();
  int currentHour = datetime.substring(11,13).toInt();  
  //2.Get temperature and humidity
  float tmp = 0.0; // temperature
  float hum = 0.0; // humidity
    tmp = sht30.cTemp; 
    hum = sht30.humidity; 
  M5.Lcd.printf("Hour: %d Temp: %2.1f Humi: %2.0f%%  \r\n", currentHour, tmp, hum);

  M5.Lcd.printf("Predicting power demand.. ");
  HttpClient client = HttpClient(ctx, beamServerAddress, beamPort);

  //3.Inference power demand for the next hour based
  String contentType = "text/csv";
  String body = String(currentHour) + ","  + String(tmp) + ","  + String(hum);
  int err ="/endpoints/" + powerModelName + "/invocations", contentType, body);

  //Check if the request is succeeded
   if (err != 0) {

  // Read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();

  M5.Lcd.printf("Power Demand: ");
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("Retrying now...");


//Get time info
String get_datetime()
  M5.Lcd.printf("Get current time..");

  HttpClient client = HttpClient(ctx, clockServerAddress, clockServerPort);

  int err = client.get("/api/timezone/Asia/Tokyo.txt");

  //Check if the request is succeeded
   if (err != 0) {
    return "";
  String response = client.responseBody();

  int start = response.indexOf(datetime_prefix);
  int end = response.indexOf('\n', start);
  String datetime = response.substring(start + datetime_prefix.length(), end);
  return datetime;

I will explain what’s doing in the loop() method In the sketch.

  1. Get current time from WorldTimeAPI and extract hour in 24 hours.

  2. Get temperature[℃] and humidity[%] with ENV III Unit with Temperature Humidity Air Pressure Sensor (SHT30+QMP6988)).

  3. Inference power demand for the next hour:Send hour, temperature and humidity to Amazon SageMaker via Soracom Beam to predict power demand for next 1 hour. Please note that there is not aws credentials required to call Amazon SageMaker via Soracom Beam, because Soracom Beam add its authentication header.


Now let’s run it!

You will get a prediction result as below. I tested it in Feb 2023 where the temperature was 24.2 and humidity was 37% and it was 3pm, then the predicted power demand was about 2873.53 in 10,000 kW.