![](/media/cache/profiles/olja.png.50x50_q85.png)
Student project, Faculty of Electrical Engineering, University of Belgrade
Dependencies: SSD1308_128x64_I2C Adafruit_GFX 19E042PIM_MB_PINS
Diff: main.cpp
- Revision:
- 2:4c2c7c8d608b
- Parent:
- 1:c994530bdb3d
--- a/main.cpp Sat Nov 27 20:33:49 2021 +0000 +++ b/main.cpp Wed Jul 13 15:07:00 2022 +0000 @@ -1,58 +1,103 @@ /* - * Program implements MQTT client on a NUCLEO-L476RG board - * using arm mbed-mqtt library and ESP-WROOM-02 WiFi modem. - * - * University of Belgrade - School of Electrical Engineering - * Department of Electronics - * Bulevar Kralja Aleksandra 73, 11120 Belgrade, Serbia - * - * November 2021. - * - */ + +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" -// LED2 blinking rate: -#define BLINKING_RATE_MS 250 -// Scaler to 3v3L -#define VOLTAGE_SCALER 3.3f -// Client yield timeout in miliseconds: +// 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 15 -// Small delay for network information printing: + +// 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 -// Left potentiometer: -AnalogIn pot1(MB_POT1); -// Left button on the motherboard: -InterruptIn sw1(MB_SW1); -// Right LED on the motherboard: -DigitalOut led2(MB_LED2); -// Pointer to a WiFi network object: +// 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: + +// Creating TCP socket TCPSocket socket; -// Creating MQTT client using the TCP socket; + +// Creating MQTT client using the TCP socket MQTTClient client(&socket); -// Message handler: + +// Message handler MQTT::Message message; -char* topic = "mbed-sample-pub"; -char* topic_sub = "mbed-sample-sub"; -// Counter of arrived messages: +// 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; -// Flag indicating that button is not pressed: -int button_pressed=0; -// HiveMQ broker connectivity information: + +// HiveMQ broker connectivity information const char* hostname = "broker.hivemq.com"; int port = 1883; -// Returning a string for a provided network encryption: + +// Returning a string for a provided network encryption const char *sec2str(nsapi_security_t sec) { switch (sec) @@ -73,12 +118,14 @@ } } +// Scan available WiFi networks int scan_networks(WiFiInterface *wifi) { printf("Scan:\n"); - // Scan only for the number of networks, first parameter is NULL: + // 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) { @@ -86,22 +133,23 @@ return 0; } - // Limit number of network arbitrary to some reasonable number: + // 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: + // 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: + + // 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: + // 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: + // 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(), @@ -117,25 +165,45 @@ return count; } -void messageArrived(MQTT::MessageData& md) +// 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; - //printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id); - printf("Message from the browser: %.*s\r\n", message.payloadlen, (char*)message.payload); - ++arrivedcount; + 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 buttonFunction() { +void messageArrivedProximity2(MQTT::MessageData& md) +{ + MQTT::Message &message = md.message; + int receavedMessage = atoi((char*)message.payload); - button_pressed=1; - + if (receavedMessage > poximityTreshold2){ flagProx2 = 1;} + else { flagProx2 = 0;} + printf("Prox2 = %d\t", receavedMessage); + printf("flag = %d\r\n", flagProx2); + } int main() { - // Set the interrupt event: - sw1.fall(&buttonFunction); - // Create a default network interface: wifi = WiFiInterface::get_default_instance(); if (!wifi) { @@ -168,39 +236,192 @@ // 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 = "NUCLEO-L476RG-60"; + data.clientID.cstring = "Broker"; - // Connect the + // Connect to the mqtt broker int rc = 0; if ((rc = client.connect(data)) != 0) printf("rc from MQTT connect is %d\r\n", rc); - if ((rc = client.subscribe(topic_sub, MQTT::QOS2, messageArrived)) != 0) + // 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) { - // Show that the loop is running by switching motherboard LED2: - led2 = !led2; - thread_sleep_for(BLINKING_RATE_MS); - if (button_pressed==1) { - button_pressed=0; - // QoS 0 - char buf[100]; - sprintf(buf, "V(POT1) = %1.2f\r\n", pot1*VOLTAGE_SCALER); - message.qos = MQTT::QOS0; - message.retained = false; - message.dup = false; - message.payload = (void*)buf; - message.payloadlen = strlen(buf)+1; - client.publish(topic, message); + + if (!flagStart){ + flagStart = !buttonStart; + thread_sleep_for(50); + } - // Need to call yield API to maintain connection: - client.yield(YIELD_TIMEOUT_MS); + + 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 + } } } \ No newline at end of file