Clustered MCUs

Enter Your Electronics & Design Project for Your Chance to Win a Grand Prize for the craziest project or a $100 Shopping Cart!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll

Previous Posts:

tinyMonster AIO Robot (part-1)

tinyMonster AIO Robot (part-2)

 

In This Post I am Sharing ESP code, Adafruit-IO setup, SPIFFS files, IFTTT applet and working GUI and serial communication images.

 

ESP Code

/****************************************************/

#include <ESP8266WiFi.h>
#include <ESPUI.h>
#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>

/****************************************************/

#include <Ticker.h>
Ticker pingger;
bool pingger_status = false;

/********************************* GPIO **************************************/

const int mqtt_status = 2; //Builtin LED indicating MQTT Status

/******************* WiFi Access Point + Station *****************************/

#define AP_SSID         "tinyMonster"
#define AP_PASS         "xxxxxxxxx"

#define WLAN_SSID       "myWifi"
#define WLAN_PASS       "xxxxxxxxx"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    "myRobot"
#define AIO_KEY         "xxxxxxxxxxxxxxxxxxxxxxxxxxx"

/********* Global State (you don't need to change this!) ***********/

WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/*************************** Feeds *********************************/

Adafruit_MQTT_Subscribe IO_data = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/robot-data");

/*********************** Robot Control *****************************/

byte robot_speed = 50;
byte robot_status = 0;
String robot_content = "";
void robot_control(String robot_data);
void speed_control(Control sender, int type);
void main_control(Control sender, int value);

/************************* Sketch Code ******************************/

void MQTT_connect();
const char * wifi_status();

/************************ Enable Ping *******************************/
void enable_ping(){
  pingger_status = true;
}

/************************* Read Serial ******************************/
void serial_read(){
  if (Serial.available() > 0) {
    String incoming = Serial.readString();
    ESPUI.print("Robot data",incoming);
  }
}

/*************************** SETUP **********************************/
void setup() {
  // ticker is used to ping Adafruit IO
  pingger.attach(200, enable_ping);

/************************ GPIO START *******************************/
  pinMode(mqtt_status,OUTPUT);
/************************ GPIO END *********************************/

  Serial.begin(115200);
  delay(500);

  // Connect to WiFi access point.
  WiFi.mode(WIFI_AP_STA); //set mode to WIFI_AP, WIFI_STA, WIFI_AP_STA or WIFI_OFF
  WiFi.hostname(AP_SSID);
  WiFi.softAP(AP_SSID, AP_PASS);
  Serial.print("IP address: ");
  Serial.println(WiFi.softAPIP());
  delay(500);

  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);

  // Waiting to connect WiFi network if it cannot connect to provided wifi network or it is not in range it will move ahead and as soon as it will be in Range it will connect it automatically
  delay(500);
  while (WiFi.status() == WL_DISCONNECTED) {
    Serial.println("WL_DISCONNECTED");
    delay(500);
  }
  
  if (WiFi.status() == WL_NO_SSID_AVAIL) {
    Serial.println("WL_NO_SSID_AVAIL");
    delay(500);
  }
  else {
    if (WiFi.status() == WL_CONNECT_FAILED) {
      Serial.println("WL_CONNECT_FAILED");
      delay(500);
    }
    else {
      while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
      }
      Serial.println("WL_CONNECTED");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
    }
  }
  
  // Setup MQTT subscription for robot feed.
  mqtt.subscribe(&IO_data);

  // Setup ESPUI setup for robot.
  ESPUI.pad("tinyMonster Control", true, &main_control, COLOR_SUNFLOWER);
  ESPUI.label("MQTT Status", COLOR_WETASPHALT, "-");
  ESPUI.label("Wifi Status", COLOR_TURQUOISE, wifi_status());
  ESPUI.label("MQTT data", COLOR_PETERRIVER, "-");
  ESPUI.label("Robot data", COLOR_EMERALD, "-");
  ESPUI.label("Control data", COLOR_CARROT, "-");
  ESPUI.slider("Speed", &speed_control, COLOR_ALIZARIN, "50");

//  ESPUI.begin("tinyMonster");
  // Begin ESPUI in SPIFFS mode for robot.
  ESPUI.beginSPIFFS("tinyMonster");
}
/*********************************************************************/
void loop() {
  ESPUI.print("Wifi Status",wifi_status());
  serial_read();

  if (WiFi.status() == WL_CONNECTED){
    MQTT_connect();
    Adafruit_MQTT_Subscribe *subscription;
    while ((subscription = mqtt.readSubscription(5000))) {
      if (subscription == &IO_data) {
        robot_content = (char *)IO_data.lastread;
        robot_control(robot_content);
      }
    }

    if (pingger_status){
      pingger_status = false;
      ESPUI.print("MQTT Status","MQTT is pinged");
      if(! mqtt.ping()) {
        mqtt.disconnect();
        digitalWrite(mqtt_status, LOW);
      }
    }
  }
  else{
    delay(10);
    yield();
  }
}
/********************* Connect to MQTT Server ***********************/
void MQTT_connect() {
  int8_t ret;
  if (mqtt.connected()) {
    return;
  }
  ESPUI.print("MQTT Status","Connecting to MQTT... ");
  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
      ESPUI.print("MQTT Status","Retrying MQTT connection in 5 seconds...");
      mqtt.disconnect();
      delay(5000);  // wait 5 seconds
      retries--;
      if (retries == 0) {
        return;
      }
  }
  ESPUI.print("MQTT Status","MQTT Connected!");
  digitalWrite(mqtt_status, HIGH);
}
/************** Robot Control Cmd from Voice/MQTT Cmd ***************/
void robot_control(String robot_data){
  robot_data.toLowerCase();

  if (robot_data.length()<=3 && robot_data.toInt() <= 100){
    robot_speed = robot_data.toInt();
  }

  if (robot_data.indexOf("stop") >= 0){
    robot_status = 0;
  }
  else{
    if (robot_data.indexOf("forward") >= 0){
      robot_status = 100;
    }
    else if ((robot_data.indexOf("reverse") >= 0) || (robot_data.indexOf("backward") >= 0)){
      robot_status = 200;
    }
    else;
    if (robot_data.indexOf("right") >= 0){
      if(robot_status == 100 || robot_status == 200 || robot_status == 0){
        robot_status += 11;
      }
      else if(robot_status == 122 || robot_status == 222 || robot_status == 22){
        robot_status -= 11;
      }
    }
    else if (robot_data.indexOf("left") >= 0){
      if(robot_status == 100 || robot_status == 200 || robot_status == 0){
        robot_status += 22;
      }
      else if(robot_status == 111 || robot_status == 211 || robot_status == 11){
        robot_status += 11;
      }
    }
    else;
  
    if (robot_data.indexOf("speed") >= 0){
      if ((robot_data.indexOf("slow") >= 0) || (robot_data.indexOf("low") >= 0)){
        robot_speed = 40;
      }
      else if ((robot_data.indexOf("medium") >= 0) || (robot_data.indexOf("normal") >= 0)){
        robot_speed = 70;
      }
      else if ((robot_data.indexOf("fast") >= 0) || (robot_data.indexOf("full") >= 0)){
        robot_speed = 100;
      }
      else;
    }
    else;
  }
  Serial.println("Robot Status = " + (String)robot_status + " Robot Speed = " + (String)robot_speed);
  ESPUI.print("MQTT data", robot_data);
}
/*************************** Wifi Status ****************************/
const char * wifi_status(){
  switch (WiFi.status()) {
    case 0 : return "WL_IDLE_STATUS";
    case 1 : return "WL_NO_SSID_AVAIL";
    case 2 : return "WL_SCAN_COMPLETED";
    case 3 : return "WL_CONNECTED";
    case 4 : return "WL_CONNECT_FAILED";
    case 5 : return "WL_CONNECTION_LOST";
    case 6 : return "WL_DISCONNECTED";
    default: return "";
  }
}
/********************* WLAN GUI Speed Control ***********************/
void speed_control(Control sender, int type) {
  robot_speed = sender.value.toInt();
  Serial.println("Robot Speed = " + (String)robot_speed);
  ESPUI.print("Control data", "Robot Speed = " + (String)robot_speed);
}
/***************** Robot Control Cmd From WLAN GUI ******************/
void main_control(Control sender, int value) {
  switch (value) {
  case P_LEFT_DOWN:
    if(robot_status == 100 || robot_status == 200 || robot_status == 0){
      robot_status += 22;
    }
    else if(robot_status == 111 || robot_status == 211 || robot_status == 11){
      robot_status += 11;
    }
    Serial.println("Robot Status = " + (String)robot_status);
    ESPUI.print("Control data", "Robot Status = " + (String)robot_status);
    break;
  case P_LEFT_UP:
    break;
  case P_RIGHT_DOWN:
    if(robot_status == 100 || robot_status == 200 || robot_status == 0){
      robot_status += 11;
    }
    else if(robot_status == 122 || robot_status == 222 || robot_status == 22){
      robot_status -= 11;
    }
    Serial.println("Robot Status = " + (String)robot_status);
    ESPUI.print("Control data", "Robot Status = " + (String)robot_status);
    break;
  case P_RIGHT_UP:
    break;
  case P_FOR_DOWN:
    robot_status = 100;
    Serial.println("Robot Status = " + (String)robot_status);
    ESPUI.print("Control data", "Robot Status = " + (String)robot_status);
    break;
  case P_FOR_UP:
    break;
  case P_BACK_DOWN:
    robot_status = 200;
    Serial.println("Robot Status = " + (String)robot_status);
    ESPUI.print("Control data", "Robot Status = " + (String)robot_status);
    break;
  case P_BACK_UP:
    break;
  case P_CENTER_DOWN:
    robot_status = 0;
    Serial.println("Robot Status = " + (String)robot_status);
    ESPUI.print("Control data", "Robot Status = " + (String)robot_status);
    break;
  case P_CENTER_UP:
    break;
  }
}

 

Adafruit-IO

{gallery} Adafruit IO Dashboard to Control Robot

AdafruitMQTT Robot Data Feed - tinyMonster Robot

IMAGE TITLE: Create Adafruit IO feed at default Location

AdafruitMQTT Robot Data Feed - tinyMonster Robot

IMAGE TITLE: Robot Data Feed

Adafruit IO Create Dashboard - tinyMonster Robot

IMAGE TITLE: Create Dashboard Using Momentary Button and Slider

Adafruit IO Dashboard Block Setting - tinyMonster Robot

IMAGE TITLE: Create Dashboard Using Momentary Button and Slider

Adafruit IO Dashboard - tinyMonster Robot

IMAGE TITLE: Final Robot Dashboard

 

IFTTT applet

{gallery} How to Create IFTTT Applet for Voice Control

IFTTT google assistant for voice control - tinyMonster Robot

IMAGE TITLE: Create IFTTT account and goto menu and select "New Applet"

IFTTT select THIS for voice control - tinyMonster

IMAGE TITLE: Select THIS

IFTTT select google assistant trigger for voice control - tinyMonster Robot

IMAGE TITLE: Search for google assistant, select and link your google account with it if asked

IFTTT select google assistant trigger for voice control - tinyMonster Robot

IMAGE TITLE: Select One of these mentioned trigger

IFTTT select google assistant trigger for voice control and add info - tinyMonster Robot

IMAGE TITLE: Fill it by entering a unique phrase to command the robot

IFTTT select THAT for voice control - tinyMonster

IMAGE TITLE: After creating trigger successfully select THAT

IFTTT select adafruit action for voice control - tinyMonster Robot

IMAGE TITLE: Search and select Adafruit Action service and connect AdafruitIO account (if asked)

IFTTT select adafruit action for voice control - tinyMonster Robot

IMAGE TITLE: Select send data to Adafruit

IFTTT select adafruit action for voice control and add info - tinyMonster Robot

IMAGE TITLE: Select earlier created AdafruitIO feed and also TextField for voice commands

IFTTT finish the applet for voice control - tinyMonster Robot

IMAGE TITLE: Select Finish to complete the Applet. Now repeat the process by selecting other action trigger

IFTTT Applet Info for voice control with speed command - tinyMonster Robot

IMAGE TITLE: Applet I created to control tinyMonster Robot Voice Robot control command with speed info

IFTTT Applet Info for voice speed command in number - tinyMonster Robot

IMAGE TITLE: Applet I created to Set tinyMonster Robot Speed using Numeric Voice command

 

SPIFFS Data

SPIFFS Data tree:

  • DATA
    • css
      • normalize.css
      • style.css
    • js
      • zepto.min.js
      • control.js
      • slider.js
    • index.html

 

 

HTML code of index.html with favicon modification. Anyone can add favicon of his own choice. Rest of these file are same as found in gui example data folder <...\Documents\Arduino\libraries\ESPUI\examples\gui\data> except control.js with little change of STOP for middle button. All the files are attach below. simply extract the zip file in Arduino robot project directory and upload using sketch data uploader.

 

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>tinyMonster Robot</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACx0lEQVQ4jX2RX0hTYRjGn86+oi6M6KabEUkQEYNugu4SRMSTEAkJIhGDYJ4uIsra1ba7YMoWYql0ExUs1wkWaEUi2C7SOOGxkLlxvtbpzzHxIDTdxZac4OmiNaZFHzzwvnzP7+F9eYGGJ4RIhMPhpmg0ejISiZyLRCIXazoXjUZPhsPhJiFEAtuhxjoWi13KZrN6qVT65HneD8/zfpRKpU/ZbFaPxWKXtvvrRTAYPCqESBiG4fz86bFarbJSqbBSqbBardLzPBqG4TR661OoqrpXCJFwXddZWFjg+voGHecbi8XPLBY/8+vXZX7/vk7TXKDruo4QIqGq6t4tq0gpWS6XOTs7R9ddo2V95Pv3eb57l2ehUOTKisvXr2dZLpcppeQWOBAInDdN84tt2zQMg8+eTfHx40k+eJDh/fsZptOTnJh4yTdvDNq2TdM0vwQCgfP1AL/ffyWXy22apsl8vkDLkpRyqyxLMp8v0DRN5nK5Tb/ffwUA4PP5VCHEraUliwMDSe7ctfu/GhhIcmnJohDils/nU6EoSioej7NQsNl85ASbj5zggZ6rbBrM1PumwQwP9Fyt94WCzXg8TkVRUgBwAcDM4qJdOdvTz9ZOjcevjRLzZGunxtZOjZgnj18bZWunxrM9/VxctCsAZmosACCYyUzLsXtT7A0l2XLzKTFP9oaS7A0liXmy5eZT9oaSHLs3xUxmWgIINh7iWFvb6UeWXOND/S214Vc8MzrHy9EnvBx9wjOjc9SGX/Gh/paWXGNb2+lHAI41BuwA0NHerqZ1/fmKlKt0nA0uL/+W42xQylXq+ouV9nY1DaCjxmB7SACA3tfXx1AotEWaphFAuub5CwaAfQCaAdzt6uoqDg0NMZVKcXx8nCMjI+zu7v4AYAzAYQD7/xWwG8BBAKcA3FAU5Y4QIiGESCiKchvA9drfIQB7/kC/AMrWysZnCbshAAAAAElFTkSuQmCC"
  />
  <link rel="stylesheet" href="/css/normalize.css">
  <link rel="stylesheet" href="/css/style.css">

  <script src="/js/zepto.min.js"></script>
  <script src="/js/slider.js"></script>
  <script src="/js/controls.js"></script>
</head>

<body onload="javascript:start();">
  <div>
    <h4><div id="mainHeader">tinyMonster Robot</div> <span id="conStatus">Offline</span></h4></div>
  <hr />
  <div>
    <div id="row">
    </div>
  </div>
</body>

</html>

 

 

ESP Demo

ESP GUI, various conditions and serial commands sent to NUCLEO for various control commands

{gallery} ESP Robot WLAN control

ESP UI WLAN is connected but cant connect to Adafruit IO - tinyMonster Robot

IMAGE TITLE: tinyMonster GUI - WLAN connected but cant connect to Adafruit MQTT

ESP UI Obstacle detected - tinyMonster Robot

IMAGE TITLE: tinyMonster GUI - Obstacle Detected

ESP UI WLAN is connected and also connected to Adafruit IO - tinyMonster Robot

IMAGE TITLE: tinyMonster GUI - WLAN connected And also connected to Adafruit MQTT

ESP UI received voice command from Adafruit IO - tinyMonster Robot

IMAGE TITLE: tinyMonster GUI - received voice command from Google assistant through Adafruit IO using IFTTT

ESP UI received control command from Adafruit IO Dashboard - tinyMonster Robot

IMAGE TITLE: tinyMonster GUI - received control command from Adafruit IO Dashboard

ESP UI Control command from GUI when WLAN not in range - tinyMonster Robot

IMAGE TITLE: tinyMonster GUI - Control command from GUI and WLAN not in range

 

 

{gallery} ESP - NUCLEO Serial Communications

ESP to NUCLEO serial Communication - tinyMonster Robot

IMAGE TITLE: ESP to NUCLEO serial Communication including voice commands with speed info - tinyMonster Robot

ESP to NUCLEO serial Communication - tinyMonster Robot

IMAGE TITLE: ESP to NUCLEO serial Communication If WLAN is out of range and control through Acess Point - tinyMonster Robot

 

 

.

.