Student project, Faculty of Electrical Engineering, University of Belgrade

Dependencies:   SSD1308_128x64_I2C Adafruit_GFX 19E042PIM_MB_PINS

main.cpp

Committer:
oljakovljevic
Date:
2022-07-13
Revision:
2:4c2c7c8d608b
Parent:
1:c994530bdb3d

File content as of revision 2:4c2c7c8d608b:

/*

This code implements MQTT broker for Smart Industry system.
The system sorts plastic caps based on their color (red, green or blue). 
Proximity sensors detect the presence of the cup, color sensor determines the color and
servo motors drive the sorting mechanism.

Faculty of Electrical Engineering, University of Belgrade.
Version (1), July 2022.

*/

// Include the libraries

#include "mbed.h"
#include "mb_pins.h"
#include "platform/mbed_thread.h"
#include "MQTTClientMbedOs.h"
#include "SSD1308.h"
#include "Adafruit_GFX.h"
#include "Adafruit_GFX_Config.h"
#include "Adafruit_SSD1306.h"

// I2C bus pins
#define D_SDA                  PB_14 
#define D_SCL                  PB_13
     
// I2C address, 60d or 0x3c
#define I2C_REAL_ADD                                                        0x3c
#define I2C_ADDRESS                                            I2C_REAL_ADD << 1
#define I2C_FREQUENCY                                                     400000

// Client yield timeout in miliseconds
#define YIELD_TIMEOUT_MS                                                    1000

// Maximum number of networks to scan for
#define MAX_NETWORKS                                                          10

// Small delay for network information printing
#define PRINTF_DELAY_MS                                                       10

// Set OLED width and heigth [pixel]
#define OLED_WIDTH_PX                                                        128
#define OLED_HEIGHT_PX                                                        64

// Initialize I2C for OLED display
I2C i2c(D_SDA, D_SCL);

// Initialize OLED
Adafruit_SSD1306_I2c myOled(i2c,PB_5,I2C_ADDRESS,OLED_HEIGHT_PX,OLED_WIDTH_PX);

// Variables that count the number of caps for every color
int red;
int green;
int blue;

// Variables used in broker decision algorithm
int flagColor = 0;
int flagProx1 = 0;
int flagProx2 = 0;
int flagStage1 = 1;
int flagStage2 = 1;
int notAvailable = 0;
int poximityTreshold1 = 300;
int poximityTreshold2 = 280;
int currentColor = 0;

// Define start button
DigitalIn buttonStart(MB_SW1); 
int flagStart = 0;

// Pointer to a WiFi network object
WiFiInterface *wifi;

// Creating TCP socket
TCPSocket socket;

// Creating MQTT client using the TCP socket
MQTTClient client(&socket);

// Message handler
MQTT::Message message;

// MQTT topics
char* topic_pub_servo1 = "PMK_industry/micro/servo1";
char* topic_pub_servo2 = "PMK_industry/micro/servo2";
char* topic_sub_color = "PMK_industry/micro/color";
char* topic_sub_proximity1 = "PMK_industry/micro/proximity1";
char* topic_sub_proximity2 = "PMK_industry/micro/proximity2";

char* receavedMessage;

// Counter of arrived messages
int arrivedcount = 0;

// HiveMQ broker connectivity information
const char* hostname = "broker.hivemq.com";
int port = 1883;

// Returning a string for a provided network encryption
const char *sec2str(nsapi_security_t sec)
{
    switch (sec) 
    {
        case NSAPI_SECURITY_NONE:
            return "None";
        case NSAPI_SECURITY_WEP:
            return "WEP";
        case NSAPI_SECURITY_WPA:
            return "WPA";
        case NSAPI_SECURITY_WPA2:
            return "WPA2";
        case NSAPI_SECURITY_WPA_WPA2:
            return "WPA/WPA2";
        case NSAPI_SECURITY_UNKNOWN:
        default:
            return "Unknown";
    }
}

// Scan available WiFi networks
int scan_networks(WiFiInterface *wifi)
{
    printf("Scan:\n");
    
    // Scan only for the number of networks, first parameter is NULL
    int count = wifi->scan(NULL, 0);
    
    // If there are no networks, count == 0, if there is an error, counter < 0:
    if (count <= 0)
    {
        printf("scan() failed with return value: %d\n", count);
        return 0;
    }

    // Limit number of network arbitrary to some reasonable number
    count = count < MAX_NETWORKS ? count : MAX_NETWORKS;
    
    // Create a local pointer to an object, which is an array of WiFi APs
    WiFiAccessPoint *ap = new WiFiAccessPoint[count];
    
    // Now scan again for 'count' networks and populate the array of APs
    count = wifi->scan(ap, count);
    
    // This time, the number of entries to 'ap' is returned
    if (count <= 0) 
    {
        printf("scan() failed with return value: %d\n", count);
        return 0;
    }
    
    // Print out the parameters of each AP
    for (int i = 0; i < count; i++) 
    {
        printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(),
               sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
               ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5], ap[i].get_rssi(), ap[i].get_channel());
        thread_sleep_for(PRINTF_DELAY_MS);
    }
    printf("%d networks available.\n", count);
    
    // Since 'ap' is dynamically allocated pointer to the array of objects, it
    // needs to be deleted:
    delete[] ap;
    return count;
}

// MQTT message handlers for certain topics
void messageArrivedColor(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;
    receavedMessage = (char*)message.payload;
    
    if (strcmp(receavedMessage,"Red") == 0 ){ flagColor = 1; }
    else if (strcmp(receavedMessage,"Green") == 0 ) { flagColor = 2; }
    else if (strcmp(receavedMessage, "Blue") == 0 ) { flagColor = 3; }
    printf("Color: %.*s\r\n", message.payloadlen, (char*)message.payload);
    
}

void messageArrivedProximity1(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;
    int receavedMessage = atoi((char*)message.payload);

    if (receavedMessage > poximityTreshold1){ flagProx1 = 1;}
    else { flagProx1 = 0;}
    printf("Prox1 = %d\t", receavedMessage);
    printf("flag = %d\r\n", flagProx1);
    
}

void messageArrivedProximity2(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;
    int receavedMessage = atoi((char*)message.payload);
    
    if (receavedMessage > poximityTreshold2){ flagProx2 = 1;}
    else { flagProx2 = 0;}
    printf("Prox2 = %d\t", receavedMessage);
    printf("flag = %d\r\n", flagProx2);
    
}

int main()
{
    // Create a default network interface:
    wifi = WiFiInterface::get_default_instance();
    if (!wifi) {
        printf("ERROR: No WiFiInterface found.\n");
        return -1;
    }
    
    // Scan for available networks and aquire information about Access Points:
    int count = scan_networks(wifi);
    if (count == 0) {
        printf("No WIFI APs found - can't continue further.\n");
        return -1;
    }
    
    // Connect to the network with the parameters specified in 'mbed_app.json':
    printf("\nConnecting to %s...\n", MBED_CONF_APP_WIFI_SSID);
    int ret = wifi->connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
    if (ret != 0) {
        printf("\nConnection error: %d\n", ret);
        return -1;
    }
    
    // Print out the information aquired:
    printf("Success\n\n");
    printf("MAC: %s\n", wifi->get_mac_address());
    printf("IP: %s\n", wifi->get_ip_address());
    printf("Netmask: %s\n", wifi->get_netmask());
    printf("Gateway: %s\n", wifi->get_gateway());
    printf("RSSI: %d\n\n", wifi->get_rssi());   
    
    // Open TCP socket using WiFi network interface:
    socket.open(wifi);
    
    // Connect to the HiveMQ broker:
    socket.connect(hostname, port);
    
    // Fill connect data with default values:
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    
    // Change only ID and protocol version:
    data.MQTTVersion = 3;
    data.clientID.cstring = "Broker";
    
    // Connect to the mqtt broker
    int rc = 0;
    if ((rc = client.connect(data)) != 0)
        printf("rc from MQTT connect is %d\r\n", rc);

    // Subscribe to topics
    if ((rc = client.subscribe(topic_sub_color, MQTT::QOS2, messageArrivedColor)) != 0)
        printf("rc from MQTT subscribe is %d\r\n", rc);
        
    if ((rc = client.subscribe(topic_sub_proximity1, MQTT::QOS2, messageArrivedProximity1)) != 0)
        printf("rc from MQTT subscribe is %d\r\n", rc);
        
    if ((rc = client.subscribe(topic_sub_proximity2, MQTT::QOS2, messageArrivedProximity2)) != 0)
        printf("rc from MQTT subscribe is %d\r\n", rc);
    
    red = 0;
    green = 0;
    blue = 0;
    
    char bufRed[15];   
    char bufGreen[15];
    char bufBlue[15];
    
    myOled.begin(); 
    myOled.setTextSize(2);
    myOled.setTextColor(WHITE);
    myOled.setTextCursor(25,0);
    myOled.printf("Press");
    myOled.setTextCursor(25,25);
    myOled.printf("START");
    myOled.display();
 
    while (true) {
        
        if (!flagStart){
        flagStart = !buttonStart;
        thread_sleep_for(50);
        
        }
        
        if (flagStart) {
        
        sprintf(bufRed, "%s %d", "Red:", red);
        sprintf(bufGreen, "%s %d", "Green:", green);
        sprintf(bufBlue, "%s %d", "Blue:", blue);
        
        myOled.clearDisplay();
        myOled.setTextSize(2);
        myOled.setTextColor(WHITE);
        myOled.setTextCursor(0,0);
        myOled.printf(bufRed);
        myOled.setTextCursor(0,25);
        myOled.printf(bufGreen);
        myOled.setTextCursor(0,50);
        myOled.printf(bufBlue);
        myOled.display();
        
        // If a cap is detected at the first stage, send a command
        // for servo1 based on the color of the cap
        if(flagStage1 && flagProx1)
        {
            
            if (flagColor == 1)
            {
                char buf[100];
                sprintf(buf, "right");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo1, message);
                flagStage1 = 0;
                red++;
                
                }
                
                else if (flagColor == 2)
            {
                char buf[100];
                sprintf(buf, "left");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo1, message);
                flagStage1 = 0;
                green++;
                
                }
                
                else if (flagColor == 3)
            {
                char buf[100];
                sprintf(buf, "left");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo1, message);
                flagStage1 = 0;
                blue++;
                
                }
                
                currentColor = flagColor;
            }
        
            else if(!flagStage1 && !flagProx1)
            {
                char buf[100];
                sprintf(buf, "zero");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo1, message);
                flagStage1 = 1;
                
                }
        
        // If a cap is detected at the second stage, send a command
        // for servo2 based on the color of the cap
        if(flagStage2 && flagProx2)
        {
            
            if (currentColor == 2)
            {
                char buf[100];
                sprintf(buf, "right");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo2, message);
                flagStage2 = 0;
                
                }
                
                else if (currentColor  == 3)
            {
                char buf[100];
                sprintf(buf, "left");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo2, message);
                flagStage2 = 0;
                
                }
                
            }
        
            else if(!flagStage2 && !flagProx2)
            {
                char buf[100];
                sprintf(buf, "zero");
                message.qos = MQTT::QOS0;
                message.retained = false;
                message.dup = false;
                message.payload = (void*)buf;
                message.payloadlen = strlen(buf)+1;
                client.publish(topic_pub_servo2, message);
                flagStage2 = 1;
                currentColor = 0;
                
                }
                
        client.yield(YIELD_TIMEOUT_MS); // Need to call yield API to maintain connection
    }
    }
}