Skip to content

14. Interface and application programming

This week I worked on defining my final project idea and started to getting used to the documentation process.

Group Assignment:
- [x]Compare as many tool options as possible.
- [x]Document your work on the group work page and reflect on your individual page what you learned.

Individual assignment:
- [x]Write an application that interfaces a user with an input and/or output device(s) on a board that you made.

Group Assignment

Why I need Interface and application programing.

When I first started working on this final project, the main purpose was to deploy it to my grandparents because they were older and lived alone. I’m very concerned about accidents happening to them at home, such as falls in the bathroom or room, so a fall monitoring device is a very effective solution.
However, how to interact with the fall monitoring device has become a very important issue.At the beginning, I also considered using Bluetooth, GPRS, etc. to implement IoT data reporting and communication, but in the end I chose to allow the entire device to report real-time monitoring data and remotely control it when connected to WiFi in the home wireless network. operating functions.
So, I learned the basic knowledge about MQTT, understood its basic principles, then learned the basic settings and configuration operations, and completed my remote control and data acquisition functions.

Learn about MQTT

What is MQTT? - MQTT is a protocal for data transport like http which is a stanard communication from webrowsers and web servers. MQTT have clients server publish/subsribe messages.
MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT). It is designed as an extremely lightweight publish/subscribe messaging transport that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth. MQTT today is used in a wide variety of industries, such as automotive, manufacturing, telecommunications, oil and gas, etc.
In my opinion, MQTT is an IoT remote connection protocol that remotely interacts with small-scale data signals through a LAN configuration connection.
Breif history of MQTT The Origin of MQTT. In 1999, Andy Stanford-Clark of IBM and Arlen Nipper of Arcom (now Cirrus Link) developed the MQTT protocol to enable minimal battery loss and bandwidth usage when connecting with oil pipelines via satellite.
Adcantages of MQTT. - MQTT messages are exremely lightwight.
- MQTT clients are decoupled and managed by a broker
- Communication over MQTT is very stable and reliable
- MQTT is easily scalable.
- MQTT can scale up many IoT devices.
Structures of MQTT The main function of MQTT is the process of data communication between MQTT Client and MQTT Broker. The Client usually publishes some information to the Broker. The Broker is like a server that stores a large amount of information and waits for the client to subscribe. At this time, Broker is like a temporary data storage center.
Data format of MQTT Under normal circumstances, MQTT client needs to follow a certain data format when publishing data. The basic content includes topic, response, payload and other information. Of course, we can also set the number of times to send information and whether to receive related message replies.

Preparation of MQTT Broker

I get the use of many tools from the MQTT official website, such as some open source software.

From the MQTT official website, I saw that there are many MQTT Brokers on the market. There are some big companies like IBM that are providing data services.
Here are some common brokers in MQTT ecosystem.
- Open-Source Brokers
1. Mosquitto
2. EMQX
3. HiveMQ Community Edition
4. VerneMQ
5. Moquette
6. NanoMQ
- Commercial Brokers
1. HiveMQ Enterprise
2. EMQX Enterprise
3. VerneMQ Enterprise
4. Solace PubSub+
From the FabAcademy tutorail, we have a ready to used the MQTT brokers. We only need to change the topics and name my address. Its quite easy to use.
I also tried the HIVEQM and registered a free account. Its seemk like this broker is quite easy for begineers. You just need to apply the new broker which generate by default. However, I didnt choose to use this one.
For more detailed information and a comprehensive list of brokers, visit.
mqtt.org/software.

Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.
The MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.
The Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.

Preparation of MQTT Clients

Wifi Configuration

Only an ordinary wifi connection is needed here. The main function of this is to allow the sensor clients to successfully connect to the LAN and publish data to the broker. I connect my local wifi in my program, but whenever I need to use the device in different situations, I need to modify the code in the Arduino IDE, modify the wifi part and recompile the burning and uploading program. The device can continue to work.
Image

MQTT Sensor Clients

The main things is connect the following pins with the microcontroller accoording to the Sensors wiki page.Since ESP32C3 has its own wifi function, it is very simple and convenient to connect to wifi and use the MQTT protocol.
Image

Explanation & Source Code

1. Function Definition

In order to successfully conduct MQTT data communication, I need to set up multiple topics. Raw monitoring data from mmWave sensors, sign data from mmmWave detection of someone passing/falling, and signal data from remote control of motor closing and opening and closing.

const char* mqtt_topic = "fabacademy/chaihuo/crail/sensor"; // MQTT Topic
const char* mqtt_topic1 = "fabacademy/chaihuo/crail/rawdata"; // MQTT Topic1
const char* mqtt_topic_fall = "fabacademy/chaihuo/crail/fall"; // MQTT Topic for Fall
const char* mqtt_topic_motor = "fabacademy/chaihuo/crail/motor"; // MQTT Topic for Motor Control
2. Detailed Working Principle

Initialization (setup()):
- WiFi Setup: Connects to the WiFi network using the provided SSID and password.
- MQTT Setup: Connects to the MQTT broker, sets up the server, and subscribes to the motor control topic.

Main Loop (loop()):
- MQTT Connection Check: Ensures the device stays connected to the MQTT broker. If disconnected, it attempts to reconnect.

Handling Radar Reports (handleRadarReport(uint8_t report)):
- Interpretation: Interprets the radar report to determine if there’s no one, someone, or a specific activity (e.g., fall, movement).
- MQTT Messaging: Publishes corresponding messages to different MQTT topics based on the radar report.
- LED Indication: Sets the color of the LED strip based on the type of activity detected.
- Delay: Introduces a short delay to prevent rapid flashing of the LED strip.

MQTT Callback (mqttCallback(char topic, byte payload, unsigned int length)):
- Message Parsing: Parses incoming MQTT messages and converts them into a string.
- Motor Control: If the message is for motor control, it runs or stops the motor sequence based on the message content (“ON” or “OFF”).

MQTT Publishing (publishMQTT(const char* topic, String message)):
- Ensures the MQTT connection is active.
- Publishes the message to the specified MQTT topic.

WiFi Setup (setup_wifi()):
- Connects to the WiFi network and prints the IP address once connected.

MQTT Reconnection (reconnect()):
- Attempts to reconnect to the MQTT broker if the connection is lost.
- Subscribes to the necessary MQTT topics upon successful reconnection.

Source Code
#include "Arduino.h"
#include <60ghzfalldetection.h>
#include <SoftwareSerial.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_NeoPixel.h>

// Define the pins for SoftwareSerial
#define RX_Pin A2
#define TX_Pin A3
#define LED_PIN 9

// Define the control inputs for a single motor
#define MOT_A1_PIN D0
#define MOT_A2_PIN D1

// MQTT Broker Details
const char* ssid = "fros_wifi";               // WiFi Name
const char* password = "66668888";    // WiFi Password
const char* mqtt_server = "mqtt.fabcloud.org"; // MQTT Broker Name
const char* mqtt_username = "fabacademy"; // MQTT Username
const char* mqtt_password = "fabacademy"; // MQTT Password
const char* mqtt_topic = "fabacademy/chaihuo/crail/sensor"; // MQTT Topic
const char* mqtt_topic1 = "fabacademy/chaihuo/crail/rawdata"; // MQTT Topic1
const char* mqtt_topic_fall = "fabacademy/chaihuo/crail/fall"; // MQTT Topic for Fall
const char* mqtt_topic_motor = "fabacademy/chaihuo/crail/motor"; // MQTT Topic for Motor Control

WiFiClient espClient;
PubSubClient client(espClient);

SoftwareSerial mySerial(RX_Pin, TX_Pin);
FallDetection_60GHz radar = FallDetection_60GHz(&mySerial);

Adafruit_NeoPixel strip = Adafruit_NeoPixel(24, LED_PIN, NEO_GRB + NEO_KHZ800);

bool motorSequenceExecuted = false;

void setup() {
  Serial.begin(115200);
  mySerial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(mqttCallback);
  client.subscribe(mqtt_topic_motor);

  strip.begin();
  strip.setBrightness(50);

  // Motor control setup
  pinMode(MOT_A1_PIN, OUTPUT);
  pinMode(MOT_A2_PIN, OUTPUT);

  // Turn off motor - Initial state
  digitalWrite(MOT_A1_PIN, LOW);
  digitalWrite(MOT_A2_PIN, LOW);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  radar.HumanExis_Func();
  if (radar.sensor_report != 0x00) {
    handleRadarReport(radar.sensor_report);
  }
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  Serial.println(message);

  if (String(topic) == mqtt_topic_motor) {
    if (message == "ON") {
      runMotorSequence();
    } else if (message == "OFF") {
      stopMotor();
    }
  }
}

void runMotorSequence() {
  Serial.println("Running motor sequence...");

  // Ramp speed up.
  for (int i = 0; i < 6; i++) {
    spin_and_wait(25 * i, 150);
  }

  // Ramp speed into full reverse.
  for (int i = 0; i < 6 ; i++) {
    spin_and_wait(135 - 25 * i, 150);
  }

  // Stop.
  spin_and_wait(0, 100);

  Serial.println("Motor sequence completed.");
}

void stopMotor() {
  Serial.println("Stopping motor...");

  for (int i = 0; i < 6; i++) {
    spin_and_wait(-25 * i, 150);
  }

  // Ramp speed into full reverse.
  for (int i = 0; i < 6 ; i++) {
    spin_and_wait(-135 + 25 * i, 150);
  }

  Serial.println("Motor stopped.");
}

void handleRadarReport(uint8_t report) {
  String message;
  String message1;
  uint32_t color;
  switch (report) {
    case NOONE:
      message = "Nobody here.";
      color = strip.Color(0, 0, 0); // Off
      publishMQTT(mqtt_topic, message);
      break;
    case SOMEONE:
      message = "Someone is here.";
      color = strip.Color(255, 255, 255); // White
      publishMQTT(mqtt_topic, message);
      break;
    case NONEPSE:
      message = "No human activity messages.";
      color = strip.Color(0, 0, 0); // Off
      publishMQTT(mqtt_topic, message);
      break;
    case STATION:
    case MOVE:
      message = "Someone moving or stopped.";
      color = strip.Color(255, 255, 0); // Yellow
      publishMQTT(mqtt_topic, message);
      break;
    case BODYVAL:
      message1 = String(radar.bodysign_val, DEC);
      color = strip.Color(0, 255, 0); // Green
      publishMQTT(mqtt_topic1, message1);
      break;
    case FALL:
      message = "Someone fell!";
      color = strip.Color(255, 0, 0); // Red
      publishMQTT(mqtt_topic, message);
      publishMQTT(mqtt_topic_fall, message);
      break;
  }

  Serial.println(message);
  if (report == BODYVAL) {
    Serial.println(message1);
  }
  setColor(color); // Set LED color
  delay(200); // Delay for 0.2 seconds to prevent rapid flashing
}

void publishMQTT(const char* topic, String message) {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (client.connected()) {
    client.publish(topic, message.c_str());
  }
}

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String clientId = "XIAO-ESP32-Client-";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str(), mqtt_username, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(mqtt_topic_motor); // Subscribe to the motor control topic
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void setColor(uint32_t color) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
  }
  strip.show();
}

/// Set the current on the motor using PWM and directional logic.
///
/// \param pwm    PWM duty cycle ranging from -255 full reverse to 255 full forward
/// \param IN1_PIN  pin number xIN1 for the given channel
/// \param IN2_PIN  pin number xIN2 for the given channel
void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN) {
  if (pwm < 0) {  // reverse speeds
    analogWrite(IN1_PIN, -pwm);
    digitalWrite(IN2_PIN, LOW);
  } else { // stop or forward
    digitalWrite(IN1_PIN, LOW);
    analogWrite(IN2_PIN, pwm);
  }
}

/// Set the current on the motor.
///
/// \param pwm_A  motor A PWM, -255 to 255
void set_motor_current(int pwm_A) {
  set_motor_pwm(pwm_A, MOT_A1_PIN, MOT_A2_PIN);

  // Print a status message to the console.
  Serial.print("Set motor A PWM = ");
  Serial.println(pwm_A);
}

/// Simple primitive for the motion sequence to set a speed and wait for an interval.
///
/// \param pwm_A  motor A PWM, -255 to 255
/// \param duration delay in milliseconds
void spin_and_wait(int pwm_A, int duration) {
  set_motor_current(pwm_A);
  delay(duration);
}

MQTT Web Clients Dashboards/UI

I saw an open source web dashbaord named mqttiles tool from the mqtt official website, so I registered an account and tried it.
https://mqtttiles.flespi.io/#/

Step 1: Set the mqtt address, username, user password and port number.
Step 2: After successful setting, you can see the words “successful connection” in the upper right corner and the green indicator light of successful connection.
Image Step 3: Set the mqtt address, username, user password and port number.Select the display style of topic data. There are many data display options here. I chose string first. Image Step 4: Enter the corresponding topic field to locate and obtain the corresponding topic data.
Image Step 5: The final result is shown below. However, this software did not achieve the effect I wanted, because I wanted the rawdata to be displayed in a line chart, so that I can more intuitively see the historical monitoring data and status of the sensor. I should try another MQTT Client to see if I can get the results.
Image

MQTT Cellphone Clients Dashboards/UI

Using the same setup method, I downloaded two apps, but the first app, MQTT Dashboard, also encountered problems because there was no way to display my data using charts. Finally I found a suitable app that achieved the final effect I wanted.
This APP is called IoT MQTT Panel, and it is completely free and can also be used on the IOS platform. It really brings me a lot of convenience.
Image Image Image

The following are my settings for several data,
1. For the raw sensor data, I directly display it in the form of a line chart. By seeing a larger value, it is detected that someone is moving.
2. For controlling the opening and closing of the motor, I provide the same publish function as MQTT to ensure that after each opening and closing action is completed, the relevant “on” or “off” information will be printed.
Image 3. Monitor falls, because falls require a certain amount of time. For example, if a person remains motionless in front of the sensor for more than 20 to 30 seconds, the fall will be detected and reported.
4. For ordinary monitoring of people passing/staying, the monitoring information and data will also be printed here.

Image
Image
Image
The function of this software is very easy to use. Not only can you sort the data display boxes up and down and lock the display boxes, but you can also customize the amount of data displayed, the background color and other related information. Perfect for my needs.

Hero Shot about MQTT application

In the video below, you can see that MQTT is continuously printing and reporting sensor data, and the motor can be remotely controlled to complete the opening and closing of the rotating mechanism.