19E042PIM 2021/22 T3 Key
Dependencies: Adafruit_GFX 19E042PIM_MB_PINS
Diff: main.cpp
- Revision:
- 0:e60b621e14a5
diff -r 000000000000 -r e60b621e14a5 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 15 22:31:26 2021 +0000 @@ -0,0 +1,230 @@ +/* + * Upon receiving 'start' mcu starts sending voltage values stampled from POT1. + * When 'stop' is received, sending is stopped, while after receving 'oled', + * message transaction is displayed on OLED display. + * + * University of Belgrade - School of Electrical Engineering + * Department of Electronics + * Bulevar Kralja Aleksandra 73, 11120 Belgrade, Serbia + * + * December 2021. + * + */ + +/* + * Includes: + */ +#include "mbed.h" +#include "mb_pins.h" +#include "platform/mbed_thread.h" +#include "MQTTClientMbedOs.h" +#include "Adafruit_GFX.h" +#include "Adafruit_GFX_Config.h" +#include "Adafruit_SSD1306.h" + +/* + * User defines: + */ +// Scaler to 3v3L +#define VOLTAGE_SCALER 3.3f +// Client yield timeout in miliseconds: +#define YIELD_TIMEOUT_MS 500 +// MQTT message buffer length: +#define BUFF_LEN 15 +// Sampling period: +#define SAMPLE_PERIOD 10 +// Sampling period scaler: +#define SAMPLE_SCALER SAMPLE_PERIOD*1000/YIELD_TIMEOUT_MS +// 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 +// Set OLED width and heigth [pixel]: +#define OLED_WIDTH_PX 128 +#define OLED_HEIGHT_PX 64 +// State machine conditions (list of commands): +#define START_COND "start" +#define STOP_COND "stop" +#define OLED_COND "oled" + + +/* + * Global user variables/objects: + */ +// Left potentiometer: +AnalogIn pot1(MB_POT1); +// Right LED on the motherboard: +DigitalOut led2(MB_LED2); +// Pointer to a WiFi network object: +WiFiInterface *wifi; +// Creating TCP socket: +TCPSocket socket; +// Creating MQTT client using the TCP socket; +MQTTClient client(&socket); +// Sent message handler: +MQTT::Message message_sent; +// Received message handler: +MQTT::Message message_received; +// Initialize I2C: +I2C i2c(D_SDA,D_SCL); +// Initialize OLED display: +Adafruit_SSD1306_I2c myOled(i2c,PB_5,I2C_ADDRESS,OLED_HEIGHT_PX,OLED_WIDTH_PX); +// MQTT topics: +char* topic_pub = "pubpim"; +char* topic_sub = "subpim"; +// HiveMQ broker connectivity information: +const char* hostname = "broker.hivemq.com"; +int port = 1883; +// Flag indicating that pot values should be sent: +char sending_allowed = 0; +// Flag indicating that OLED display preview is enabled: +char oled_allowed = 0; +//Pseudo-timer for avoiding long CPU idle periods: +int pseudo_timer = 0; +// Message buffer to be sent: +char buf[BUFF_LEN]; +// Message processing status: +char msgrcv = 0; + +/* + * Publish pot value: + */ +void publishPot() +{ + sprintf(buf, "V = %1.2f\r\n", pot1*VOLTAGE_SCALER); + message_sent.qos = MQTT::QOS0; + message_sent.retained = false; + message_sent.dup = false; + message_sent.payload = (void*)buf; + message_sent.payloadlen = strlen(buf); + client.publish(topic_pub, message_sent); +} + +/* + * MQTT traffic previewed on OLED: + */ +void oledPreview() +{ + myOled.clearDisplay(); + myOled.setTextCursor(0, 0); + myOled.printf("Sent: %.*s\n", strlen(buf), buf); + myOled.printf("Received: %.*s\n", message_received.payloadlen, (char*)message_received.payload); + myOled.display(); +} + +/* + * Check if payload satisfies any of the state machine conditions: + */ +int checkCondition (char* payload, int payloadlen, char* condition) +{ + char not_satisfied = 0; + char cnt = 0; + while(cnt != payloadlen) + { + if (payload[cnt] != condition[cnt]) + not_satisfied = 1; + cnt++; + } + return not_satisfied; +} + +/* + * MQTT message received function: + */ +void messageArrived(MQTT::MessageData& md) +{ + MQTT::Message &message = md.message; + message_received = md.message; + msgrcv = 1; + printf("Message from the browser: %.*s\r\n", message.payloadlen, (char*)message.payload); +} + +/* + * State machine update upon receiving a message: + */ +void stateCheck() +{ + char message_buff[BUFF_LEN]; + + // Copy payload into a char arrray: + sprintf(message_buff, "%.*s",message_received.payloadlen, (char*)message_received.payload); + + // State machine: + if(!checkCondition(message_buff, strlen(message_buff), START_COND)) + { + sending_allowed = 1; + } + else if (!checkCondition(message_buff, strlen(message_buff), STOP_COND)) + { + sending_allowed = 0; + } + else if (!checkCondition(message_buff, strlen(message_buff), OLED_COND)) + { + oled_allowed = 1; + myOled.begin(); + oledPreview(); + } + // Mark the end of message processing: + msgrcv = 0; +} + + +/* + * Main: + */ +int main() +{ + // Create a default network interface: + wifi = WiFiInterface::get_default_instance(); + + // Connect to the network with the parameters specified in 'mbed_app.json': + printf("\nConnecting to %s...\n", MBED_CONF_APP_WIFI_SSID); + wifi->connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2); + // Mark connection done: + printf("\nConnected.\r\n"); + + // Open TCP socket using WiFi network interface: + socket.open(wifi); + // Connect to the HiveMQ broker over the internet: + 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 = "pim-60"; + + // Establish MQTT connection: + client.connect(data); + // Subscribe to the topic specified by topic_sub: + client.subscribe(topic_sub, MQTT::QOS2, messageArrived); + + while (true) + { + // Show that the loop is running by switching motherboard LED2: + led2 = !led2; + + // If the message is received, check state machine current state: + if (msgrcv) + stateCheck(); + + // If 'oled' was received: + if (oled_allowed) + oledPreview(); + + // If the pseudo-timer has counted 10s: + if( pseudo_timer == (SAMPLE_SCALER)) + { + // If 'start' was received: + if(sending_allowed == 1) + publishPot(); + // Reset pseudo-timer: + pseudo_timer = 0; + } + //Increment pseudo-timer: + pseudo_timer++; + // Need to call yield API to maintain connection: + client.yield(YIELD_TIMEOUT_MS); + } +} \ No newline at end of file