IoT Design with Cypress PSoC® 6 MCUs and Wi-Fi/Bluetooth using Arm® Mbed™

# Lesson GitHub Project
0 Introduction
1 Developer Resources
2 Your First Project & The Blinking Thread https://github.com/iotexpert/mouser-mbed-02.git
3 Display Thread https://github.com/iotexpert/mouser-mbed-03.git
4 Temperature Thread https://github.com/iotexpert/mouser-mbed-04.git
5 CapSense Thread https://github.com/iotexpert/mouser-mbed-05.git
6 WiFi & NTP Thread https://github.com/iotexpert/mouser-mbed-06.git
7 The CY8CKIT-062-WiFi-BT https://github.com/iotexpert/mouser-mbed-07.git 
8 Amazon AWS MQTT Thread - Part1 https://github.com/iotexpert/mouser-mbed-08.git
9 Amazon AWS MQTT Thread - Part2 https://github.com/iotexpert/mouser-mbed-09.git

You can “mbed import https://github.com/iotexpert/mouser-mbed-09.git“ to make a copy of the project in your workspace.

The final architecture of the thermostat looks like this.

 

Summary

In the last lesson we added an MQTT subscription that let’s the AWS servers control the setPoint.  In this lesson we will update the system to send out the current temperature every second – which I know is excessive.

To make the temperature publish changes I need to modify the awsThread to have a queue/command scheme just like the displayThread and the temperatureThread.  Then I will modify the temperatureThread to send out temperature changes to the awsThread which will take care of publishing changes.

To implement this I will:

  1. Import Lesson 08
  2. Modify awsThread.h
  3. Modify awsThread.cpp
  4. Modify temperatureThread.cpp
  5. Build, Program and Test

Import Lesson 09

Start by importing Lesson 08.

https://github.com/iotexpert/mouser-mbed-08.git

Modify awsThread.h

Add the function prototype for the other threads to queue temperature changes.

#ifndef AWS_THREAD_H
#define AWS_THREAD_H

void awsThread(void);
void awsSendUpdateTemperature(float temperature);

#endif

Modify awsThread.cpp

I will copy the scheme I built for the other threads.  There will be only one command, the one to send the temperature.

typedef enum {
    CMD_sendTemperature,
} command_t;

typedef struct {
    command_t cmd;
    float    value;   /* AD result of measured voltage */
} msg_t;


static Queue<msg_t, 32> queue;
static MemoryPool<msg_t, 16> mpool;

void awsSendUpdateTemperature(float temperature)
{
    msg_t *message = mpool.alloc();
    if(message)
    {
        message->cmd = CMD_sendTemperature;
        message->value = temperature;
        queue.put(message);
    }
}

Now I modify the main loop of the awsThread.  The AWSClient.yield function will time out every 1000ms which gives you the opportunity to do something.  That “something” is that I completely empty queue and then send the LAST update.

 bool doPublish=false;
    float currentTemp;
    while(1)
    {
        AWSClient.yield(1000);
        while(!queue.empty())
        {
            osEvent evt = queue.get(0);
            if (evt.status == osEventMessage) {
                msg_t *message = (msg_t*)evt.value.p;
                switch(message->cmd)
                {
                    case CMD_sendTemperature:
                        doPublish = true;
                        currentTemp = message->value;
                    break;

                }
                mpool.free(message);
            }
        }
        if(doPublish)
        {
            char buffer[128];
            sprintf(buffer,"%2.1f",currentTemp);
            AWSClient.publish(ep,"currentTemp", buffer, strlen(buffer),  publish_params);
        }
        doPublish = false;
    }

Here is the whole awsThread.cpp:

#include "mbed.h"
#include "aws_client.h"
#include "aws_config.h"
#include "temperatureThread.h"

#define AWSIOT_ENDPOINT_ADDRESS             "a1c0l0bpd6pon3-ats.iot.us-east-2.amazonaws.com"


extern WiFiInterface *wifi;

typedef enum {
    CMD_sendTemperature,
} command_t;

typedef struct {
    command_t cmd;
    float    value;   /* AD result of measured voltage */
} msg_t;


static Queue<msg_t, 32> queue;
static MemoryPool<msg_t, 16> mpool;

void awsSendUpdateTemperature(float temperature)
{
    msg_t *message = mpool.alloc();
    if(message)
    {
        message->cmd = CMD_sendTemperature;
        message->value = temperature;
        queue.put(message);
    }
}

void messageArrived(aws_iot_message_t& md)
{
    float setPoint; 
    aws_message_t &message = md.message;
    sscanf((char*)message.payload,"%f",&setPoint);
    tempSendUpdateSetpointF(setPoint);
}

void awsThread(void)
{
    AWSIoTClient client;
    AWSIoTEndpoint* ep = NULL;

    /* Initialize AWS Client library */
    AWSIoTClient AWSClient(wifi, "thermostat" , SSL_CLIENTKEY_PEM, strlen(SSL_CLIENTKEY_PEM), SSL_CLIENTCERT_PEM, strlen(SSL_CLIENTCERT_PEM));

    aws_connect_params conn_params = { 0,0,NULL,NULL,NULL,NULL,NULL };
    ep = AWSClient.create_endpoint(AWS_TRANSPORT_MQTT_NATIVE, AWSIOT_ENDPOINT_ADDRESS, 8883, SSL_CA_PEM, strlen(SSL_CA_PEM));

    /* set MQTT connection parameters */
    conn_params.username = NULL;
    conn_params.password = NULL;
    conn_params.keep_alive = 60;
    conn_params.peer_cn = (uint8_t*) AWSIOT_ENDPOINT_ADDRESS;
    conn_params.client_id = (uint8_t*)"thermostat";

    /* connect to an AWS endpoint */
    AWSClient.connect (ep, conn_params);
 
    AWSClient.subscribe(ep, "setPoint", AWS_QOS_ATMOST_ONCE, messageArrived);
    aws_publish_params publish_params = { AWS_QOS_ATMOST_ONCE };
    
    bool doPublish=false;
    float currentTemp;
    while(1)
    {
        AWSClient.yield(1000);
        while(!queue.empty())
        {
            osEvent evt = queue.get(0);
            if (evt.status == osEventMessage) {
                msg_t *message = (msg_t*)evt.value.p;
                switch(message->cmd)
                {
                    case CMD_sendTemperature:
                        doPublish = true;
                        currentTemp = message->value;
                    break;

                }
                mpool.free(message);
            }
        }
        if(doPublish)
        {
            char buffer[128];
            sprintf(buffer,"%2.1f",currentTemp);
            AWSClient.publish(ep,"currentTemp", buffer, strlen(buffer),  publish_params);
        }
        doPublish = false;
    }
}

Modify temperatureThread.cpp

In order to use the new functionality in the awsThread you need to modify the temperatureThread.

First add the #include “awsThread.h” (so that it has access to the awsThread public interface):

#include "mbed.h"
#include "temperatureThread.h"
#include "displayThread.h"
#include "awsThread.h"

Each time the temperature changes send the awsThread the update.

        {
            readTemp();

            // Control the HVAC system with +- 0.5 degree of Hystersis
            if(temperatureF < setPoint - 0.5)
                displaySendUpdateMode(-1.0);
            else if (temperatureF > setPoint + 0.5)
                displaySendUpdateMode(1.0);
            else
                displaySendUpdateMode(0.0);

            displaySendUpdateTemp(temperatureF);
            awsSendUpdateTemperature(temperatureF);
        }

Build, Program and Test

In order to test this I log into the AWS Test Console, and subscribe to the currentTemp topic.  Notice that temperatures keep coming!

 

Recommended Posts

2 Comments

  1. With respect !!!


Add a Comment

Your email address will not be published. Required fields are marked *