vincent wong
Published © GPL3+

IoT Node with STM32F4 Discovery, MKR1000 and Azure IoT Hub

With MKR1000 and Azure IoT Hub, STM32F4 Discovery Board is used to send acceleration and other random telemetry data to Azure IoT Hub.

IntermediateFull instructions provided619
IoT Node with STM32F4 Discovery, MKR1000 and Azure IoT Hub

Things used in this project

Hardware components

STMicroelectronics STM32F407G-DISC1
×1
Arduino MKR1000
Arduino MKR1000
×1

Software apps and online services

GNAT Community
AdaCore GNAT Community
Arduino IDE
Arduino IDE

Story

Read more

Code

my_usart_polling.adb

ADA
Ada code sending acceleration data thur TX, RX
------------------------------------------------------------------------------
--                                                                          --
--                 Copyright (C) 2015-2017, AdaCore                         --
--                                                                          --
--                                                                          --
------------------------------------------------------------------------------

--  The file declares the main procedure for the demonstration.

with Ada.Strings.Fixed; use Ada.Strings.fixed;
with Ada.Real_Time;      use Ada.Real_Time;
with HAL;           use HAL;
with STM32.GPIO;    use STM32.GPIO;
with STM32.USARTs;  use STM32.USARTs;

with STM32.Device;  use STM32.Device;

with STM32.Board;        use STM32.Board;
with LIS3DSH;            use LIS3DSH;



procedure My_USART_Polling is

   Values : LIS3DSH.Axes_Accelerations;

   procedure My_Delay (Milli : Natural);

   procedure My_Delay (Milli : Natural) is
   begin
      delay until Clock + Milliseconds (Milli);
   end My_Delay;


   TX_Pin : constant GPIO_Point := PB7;
   RX_Pin : constant GPIO_Point := PB6;

   procedure Initialize_UART_GPIO;

   procedure Initialize;

   procedure Await_Send_Ready (This : USART) with Inline;

   procedure Put_Blocking (This : in out USART;  Data : UInt16);

   --------------------------
   -- Initialize_UART_GPIO --
   --------------------------

   procedure Initialize_UART_GPIO is
   begin
      Enable_Clock (USART_1);
      Enable_Clock (RX_Pin & TX_Pin);

      Configure_IO
        (RX_Pin & TX_Pin,
         (Mode           => Mode_AF,
          AF             => GPIO_AF_USART1_7,
          Resistors      => Pull_Up,
          AF_Speed       => Speed_50MHz,
          AF_Output_Type => Push_Pull));
   end Initialize_UART_GPIO;

   ----------------
   -- Initialize --
   ----------------

   procedure Initialize is
   begin
      Initialize_UART_GPIO;

      Disable (USART_1);

      Set_Baud_Rate    (USART_1, 115_200);
      Set_Mode         (USART_1, Tx_Rx_Mode);
      Set_Stop_Bits    (USART_1, Stopbits_1);
      Set_Word_Length  (USART_1, Word_Length_8);
      Set_Parity       (USART_1, No_Parity);
      Set_Flow_Control (USART_1, No_Flow_Control);

      Enable (USART_1);
   end Initialize;

   ----------------------
   -- Await_Send_Ready --
   ----------------------

   procedure Await_Send_Ready (This : USART) is
   begin
      loop
         exit when Tx_Ready (This);
      end loop;
   end Await_Send_Ready;

   ------------------
   -- Put_Blocking --
   ------------------

   procedure Put_Blocking (This : in out USART;  Data : UInt16) is
   begin
      Await_Send_Ready (This);
      Transmit (This, UInt9 (Data));
   end Put_Blocking;

   F : Float;
   Fs: String (1 .. 12);

begin
   Initialize;

   Initialize_Accelerometer;

   Accelerometer.Configure
     (Output_DataRate => Data_Rate_100Hz,
      Axes_Enable     => XYZ_Enabled,
      SPI_Wire        => Serial_Interface_4Wire,
      Self_Test       => Self_Test_Normal,
      Full_Scale      => Fullscale_2g,
      Filter_BW       => Filter_800Hz);

   Accelerometer.Get_Accelerations (Values);


   F := Float (Values.X);

   Move(Float'Image (F), Fs);

      for C of Fs loop  -- arbitrary
         Put_Blocking (USART_1, Character'Pos (C));

         My_Delay (1000);
      end loop;


end My_USART_Polling;

simplesample_http.c

C/C++
This code is modified from the Azure IoT sample tutorial.
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.


#include <stdlib.h>

#include <stdio.h>
#include <stdint.h>
#include "iot_configs.h"

/* This sample uses the _LL APIs of iothub_client for example purposes.
That does not mean that HTTP only works with the _LL APIs.
Simply changing the using the convenience layer (functions not having _LL)
and removing calls to _DoWork will yield the same results. */

#include "AzureIoTHub.h"

/*String containing Hostname, Device Id & Device Key in the format:             */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"    */
static const char* connectionString = IOT_CONFIG_CONNECTION_STRING;

// Define the Model
BEGIN_NAMESPACE(WeatherStation);

DECLARE_MODEL(ContosoAnemometer,
WITH_DATA(ascii_char_ptr, DeviceId),
WITH_DATA(int, WindSpeed),
WITH_DATA(float, Temperature),
WITH_DATA(float, Humidity),
WITH_DATA(float, AccelerationX),
WITH_ACTION(TurnFanOn),
WITH_ACTION(TurnFanOff),
WITH_ACTION(SetAirResistance, int, Position)
);

END_NAMESPACE(WeatherStation);

static char propText[1024];


EXECUTE_COMMAND_RESULT TurnFanOn(ContosoAnemometer* device)
{
    (void)device;
    (void)printf("Turning fan on.\r\n");
    return EXECUTE_COMMAND_SUCCESS;
}

EXECUTE_COMMAND_RESULT TurnFanOff(ContosoAnemometer* device)
{
    (void)device;
    (void)printf("Turning fan off.\r\n");
    return EXECUTE_COMMAND_SUCCESS;
}

EXECUTE_COMMAND_RESULT SetAirResistance(ContosoAnemometer* device, int Position)
{
    (void)device;
    (void)printf("Setting Air Resistance Position to %d.\r\n", Position);
    return EXECUTE_COMMAND_SUCCESS;
}

void sendCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
    unsigned int messageTrackingId = (unsigned int)(uintptr_t)userContextCallback;

    (void)printf("Message Id: %u Received.\r\n", messageTrackingId);

    (void)printf("Result Call Back Called! Result is: %s \r\n", ENUM_TO_STRING(IOTHUB_CLIENT_CONFIRMATION_RESULT, result));
}

static void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
{
    static unsigned int messageTrackingId;
    IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
    if (messageHandle == NULL)
    {
        printf("unable to create a new IoTHubMessage\r\n");
    }
    else
    {
        if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, sendCallback, (void*)(uintptr_t)messageTrackingId) != IOTHUB_CLIENT_OK)
        {
            printf("failed to hand over the message to IoTHubClient");
        }
        else
        {
            printf("IoTHubClient accepted the message for delivery\r\n");
        }
        IoTHubMessage_Destroy(messageHandle);
    }
    free((void*)buffer);
    messageTrackingId++;
}

/*this function "links" IoTHub to the serialization library*/
static IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubMessage(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
    IOTHUBMESSAGE_DISPOSITION_RESULT result;
    const unsigned char* buffer;
    size_t size;
    if (IoTHubMessage_GetByteArray(message, &buffer, &size) != IOTHUB_MESSAGE_OK)
    {
        printf("unable to IoTHubMessage_GetByteArray\r\n");
        result = IOTHUBMESSAGE_ABANDONED;
    }
    else
    {
        /*buffer is not zero terminated*/
        char* temp = malloc(size + 1);
        if (temp == NULL)
        {
            printf("failed to malloc\r\n");
            result = IOTHUBMESSAGE_ABANDONED;
        }
        else
        {
            EXECUTE_COMMAND_RESULT executeCommandResult;
        
            (void)memcpy(temp, buffer, size);
            temp[size] = '\0';
            executeCommandResult = EXECUTE_COMMAND(userContextCallback, temp);
            result =
                (executeCommandResult == EXECUTE_COMMAND_ERROR) ? IOTHUBMESSAGE_ABANDONED :
                (executeCommandResult == EXECUTE_COMMAND_SUCCESS) ? IOTHUBMESSAGE_ACCEPTED :
                IOTHUBMESSAGE_REJECTED;
            free(temp);
        }
    }
    return result;
}


void simplesample_http_run(float value)
{
    if (platform_init() != 0)
    {
        printf("Failed to initialize the platform.\r\n");
    }
    else
    {
        if (serializer_init(NULL) != SERIALIZER_OK)
        {
            (void)printf("Failed on serializer_init\r\n");
        }
        else
        {
            IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, HTTP_Protocol);
            int avgWindSpeed = 10;
            float minTemperature = 20.0;
            float minHumidity = 60.0;

            srand((unsigned int)time(NULL));

            if (iotHubClientHandle == NULL)
            {
                (void)printf("Failed on IoTHubClient_LL_Create\r\n");
            }
            else
            {
                // Because it can poll "after 9 seconds" polls will happen 
                // effectively at ~10 seconds.
                // Note that for scalabilty, the default value of minimumPollingTime
                // is 25 minutes. For more information, see:
                // https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
                unsigned int minimumPollingTime = 9;
                ContosoAnemometer* myWeather;

                if (IoTHubClient_LL_SetOption(iotHubClientHandle, "MinimumPollingTime", &minimumPollingTime) != IOTHUB_CLIENT_OK)
                {
                    printf("failure to set option \"MinimumPollingTime\"\r\n");
                }

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
                // For mbed add the certificate information
                if (IoTHubClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
                {
                    (void)printf("failure to set option \"TrustedCerts\"\r\n");
                }
#endif // SET_TRUSTED_CERT_IN_SAMPLES

                myWeather = CREATE_MODEL_INSTANCE(WeatherStation, ContosoAnemometer);
                if (myWeather == NULL)
                {
                    (void)printf("Failed on CREATE_MODEL_INSTANCE\r\n");
                }
                else
                {
                    if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, IoTHubMessage, myWeather) != IOTHUB_CLIENT_OK)
                    {
                        printf("unable to IoTHubClient_SetMessageCallback\r\n");
                    }
                    else
                    {

                        /* wait for commands */
                        int sendCycle = 15;
                        int currentCycle = 0;
                        bool done = false;
                        while (!done)
                        {
                            if(currentCycle >= sendCycle) {
                                currentCycle = 0;
                                
                                myWeather->DeviceId = IOT_DEVICE_ID;
                                myWeather->WindSpeed = avgWindSpeed + (rand() % 4 + 2);
                                myWeather->Temperature = minTemperature + (rand() % 10);
                                myWeather->Humidity = minHumidity + (rand() % 20);
                                myWeather->AccelerationX = value;

                                {
                                    unsigned char* destination;
                                    size_t destinationSize;
                                    if (SERIALIZE(&destination, &destinationSize, myWeather->DeviceId, myWeather->WindSpeed, myWeather->Temperature, myWeather->Humidity, myWeather->AccelerationX) != CODEFIRST_OK)
                                    {
                                        (void)printf("Failed to serialize\r\n");
                                    }
                                    else
                                    {
                                        IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(destination, destinationSize);
                                        if (messageHandle == NULL)
                                        {
                                            printf("unable to create a new IoTHubMessage\r\n");
                                        }
                                        else
                                        {
                                            MAP_HANDLE propMap = IoTHubMessage_Properties(messageHandle);
                                            (void)sprintf_s(propText, sizeof(propText), myWeather->Temperature > 28 ? "true" : "false");
                                            if (Map_AddOrUpdate(propMap, "temperatureAlert", propText) != MAP_OK)
                                            {
                                                printf("ERROR: Map_AddOrUpdate Failed!\r\n");
                                            }
        
                                            if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, sendCallback, (void*)1) != IOTHUB_CLIENT_OK)
                                            {
                                                printf("failed to hand over the message to IoTHubClient");
                                            }
                                            else
                                            {
                                                printf("cycle=%d, windspeed=%d, temperature=%f, humidity=%f, accelerationX=%f\r\n", currentCycle, myWeather->WindSpeed, myWeather->Temperature, myWeather->Humidity, myWeather->AccelerationX);
                                                printf("IoTHubClient accepted the message for delivery\r\n");

                                                done = true;
                                            }
        
                                            IoTHubMessage_Destroy(messageHandle);
                                        }
                                        free(destination);

                                        ThreadAPI_Sleep(10000);
                                    }
                                }
                            }
                            
                            IoTHubClient_LL_DoWork(iotHubClientHandle);
                            ThreadAPI_Sleep(100);

                            currentCycle++;
                        }
                        
                    }

                    DESTROY_MODEL_INSTANCE(myWeather);
                }
                IoTHubClient_LL_Destroy(iotHubClientHandle);
            }
            serializer_deinit();
        }
        platform_deinit();
    }
}

void sample_run(float value)
{
    simplesample_http_run(value);
}

ReadDeviceToCloudMessages.js

JavaScript
JavaScript code reading device-to-cloud messages from a Azure IoT hub.
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

'use strict';


//
// Using the Azure CLI:
// az iot hub show-connection-string --hub-name {YourIoTHubName} --output table
var connectionString = 'iot hub connection string';


// The sample connects to an IoT hub's Event Hubs-compatible endpoint
// to read messages sent from a device.
var { EventHubClient, EventPosition } = require('@azure/event-hubs');

var printError = function (err) {
  console.log(err.message);
};

// Display the message content - telemetry and properties.
// - Telemetry is sent in the message body
// - The device can add arbitrary application properties to the message
// - IoT Hub adds system properties, such as Device Id, to the message.
var printMessage = function (message) {
  console.log('Telemetry received: ');
  console.log(JSON.stringify(message.body));
  console.log('Application properties (set by device): ')
  console.log(JSON.stringify(message.applicationProperties));
  console.log('System properties (set by IoT Hub): ')
  console.log(JSON.stringify(message.annotations));
  console.log('');
};

// Connect to the partitions on the IoT Hub's Event Hubs-compatible endpoint.
// This example only reads messages sent after this application started.
var ehClient;
EventHubClient.createFromIotHubConnectionString(connectionString).then(function (client) {
  console.log("Successully created the EventHub Client from iothub connection string.");
  ehClient = client;
  return ehClient.getPartitionIds();
}).then(function (ids) {
  console.log("The partition ids are: ", ids);
  return ids.map(function (id) {
    return ehClient.receive(id, printMessage, printError, { eventPosition: EventPosition.fromEnqueuedTime(Date.now()) });
  });
}).catch(printError);

iot_configs.h

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef IOT_CONFIGS_H
#define IOT_CONFIGS_H

/**
 * WiFi setup
 */
#define IOT_CONFIG_WIFI_SSID            "wifi ssid"
#define IOT_CONFIG_WIFI_PASSWORD        "wifi password"

/**
 * Find under Microsoft Azure IoT Suite -> DEVICES -> <your device> -> Device Details and Authentication Keys
 * String containing Hostname, Device Id & Device Key in the format:
 *  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"    
 */
 
#define IOT_CONFIG_CONNECTION_STRING    "iot device connection string"
#define IOT_DEVICE_ID                   "AdaDevice01"


/** 
 * Choose the transport protocol
 */
// #define IOT_CONFIG_MQTT                 // uncomment this line for MQTT
#define IOT_CONFIG_HTTP              // uncomment this line for HTTP

#endif /* IOT_CONFIGS_H */

sample.h

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef SAMPLE_H
#define SAMPLE_H

#ifdef __cplusplus
extern "C" {
#endif

    void sample_run(float);

#ifdef __cplusplus
}
#endif

#endif /* SAMPLE_H */

simplesample_http.h

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef SIMPLESAMPLEHTTP_H
#define SIMPLESAMPLEHTTP_H

#ifdef __cplusplus
extern "C" {
#endif

    void simplesample_http_run(float);

#ifdef __cplusplus
}
#endif

#endif /* SIMPLESAMPLEHTTP_H */

simplesample_http_sonyhub.c

C/C++
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// Please use an Arduino IDE 1.6.8 or greater

// You must set the device id, device key, IoT Hub name and IotHub suffix in
// iot_configs.h
#include "iot_configs.h"

#include <AzureIoTHub.h>
#if defined(IOT_CONFIG_MQTT)
    #include <AzureIoTProtocol_MQTT.h>
#elif defined(IOT_CONFIG_HTTP)
    #include <AzureIoTProtocol_HTTP.h>
#endif

#include "sample.h"
#include "samd/sample_init.h"

static char ssid[] = IOT_CONFIG_WIFI_SSID;
static char pass[] = IOT_CONFIG_WIFI_PASSWORD;

int i;
byte buffer[12];

float getAccelerationX() {

    while (Serial1.available() > 0)  {
      int inByte = Serial1.read();

      if (inByte == 32 || inByte == 45) {  // space or - sign
        buffer[++i] = 0;
        float value = String((char *)buffer).toFloat();

        Serial.println(value);

        i = 0;
        buffer[i] = inByte;

        return value;
      } else {
        buffer[++i] = inByte;
      }
    }
    
}

void setup() {
    sample_init(ssid, pass);  // must run this line

    Serial1.begin(115200);
}

// Azure IoT samples contain their own loops, so only run them once
static bool done = false;
void loop() {
    Serial.println("loop");


    if (!done)
    {
        float valueX = getAccelerationX();
        Serial.println(valueX);
        
        // Run the sample
        // You must set the device id, device key, IoT Hub name and IotHub suffix in
        // iot_configs.h

        if (valueX != 0.00) sample_run(valueX);

        valueX = 0.00;
        delay(5000);
    }
    else
    {
      delay(500);
      Serial.println("delay 500");
    }
}

Credits

vincent wong

vincent wong

48 projects • 137 followers

Comments