Nenad Tepavac 2020/0028

Dependencies:   mbed Adafruit_GFX 19E042PIM_MB_PINS

Committer:
ostoja
Date:
Mon Jan 17 16:01:04 2022 +0000
Revision:
0:981049ce9511
Nenad Tepavac 2020/0028;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ostoja 0:981049ce9511 1 #include "mbed.h"
ostoja 0:981049ce9511 2 #include "Adafruit_GFX.h"
ostoja 0:981049ce9511 3 #include "Adafruit_GFX_Config.h"
ostoja 0:981049ce9511 4 #include "Adafruit_SSD1306.h"
ostoja 0:981049ce9511 5 #include "mb_pins.h"
ostoja 0:981049ce9511 6 #include "platform/mbed_thread.h"
ostoja 0:981049ce9511 7 #include "MQTTClientMbedOs.h"
ostoja 0:981049ce9511 8
ostoja 0:981049ce9511 9 // I2C bus pins:
ostoja 0:981049ce9511 10 #define D_SDA PB_14
ostoja 0:981049ce9511 11 #define D_SCL PB_13
ostoja 0:981049ce9511 12 // I2C address, 60d or 0x3c:
ostoja 0:981049ce9511 13 #define I2C_REAL_ADD 0x3c
ostoja 0:981049ce9511 14 #define I2C_ADDRESS I2C_REAL_ADD << 1
ostoja 0:981049ce9511 15 // Set OLED width and heigth [pixel]:
ostoja 0:981049ce9511 16 #define OLED_WIDTH_PX 128
ostoja 0:981049ce9511 17 #define OLED_HEIGHT_PX 64
ostoja 0:981049ce9511 18 // I2C frequency:
ostoja 0:981049ce9511 19 #define I2C_FREQUENCY 400000
ostoja 0:981049ce9511 20 // Multipliers of POT1 and POT2 for OLED rectangle position:
ostoja 0:981049ce9511 21 #define WIDTH_SCALER 128
ostoja 0:981049ce9511 22 #define HEIGHT_SCALER 64
ostoja 0:981049ce9511 23 // Initial rectangle position:
ostoja 0:981049ce9511 24 #define INITIAL_X_POSITION OLED_WIDTH_PX / 2
ostoja 0:981049ce9511 25 #define INITIAL_Y_POSITION OLED_HEIGHT_PX / 2
ostoja 0:981049ce9511 26 // Refresh rate:
ostoja 0:981049ce9511 27 #define REFRESH_RATE_MS 5
ostoja 0:981049ce9511 28 // Half of the potentiometer return value:
ostoja 0:981049ce9511 29 #define HALF_INTERVAL 0.5f
ostoja 0:981049ce9511 30 // LED2 blinking rate:
ostoja 0:981049ce9511 31 #define BLINKING_RATE_MS 250
ostoja 0:981049ce9511 32 // Scaler to 3v3L
ostoja 0:981049ce9511 33 #define VOLTAGE_SCALER 3.3f
ostoja 0:981049ce9511 34 // Client yield timeout in miliseconds:
ostoja 0:981049ce9511 35 #define YIELD_TIMEOUT_MS 1000
ostoja 0:981049ce9511 36 // Maximum number of networks to scan for:
ostoja 0:981049ce9511 37 #define MAX_NETWORKS 15
ostoja 0:981049ce9511 38 // Small delay for network information printing:
ostoja 0:981049ce9511 39 #define PRINTF_DELAY_MS 10
ostoja 0:981049ce9511 40
ostoja 0:981049ce9511 41 // Initialize I2C:
ostoja 0:981049ce9511 42 I2C i2c(PB_14,PB_13);
ostoja 0:981049ce9511 43
ostoja 0:981049ce9511 44 // Initialize OLED display:
ostoja 0:981049ce9511 45 Adafruit_SSD1306_I2c myOled(i2c,PB_5,I2C_ADDRESS,OLED_HEIGHT_PX,OLED_WIDTH_PX);
ostoja 0:981049ce9511 46
ostoja 0:981049ce9511 47 // Left potentiometer:
ostoja 0:981049ce9511 48 AnalogIn pot1(MB_POT1);
ostoja 0:981049ce9511 49 // Left button on the motherboard:
ostoja 0:981049ce9511 50 InterruptIn sw1(MB_SW1);
ostoja 0:981049ce9511 51 // Right LED on the motherboard:
ostoja 0:981049ce9511 52 DigitalOut led2(MB_LED2);
ostoja 0:981049ce9511 53 DigitalIn sw2(MB_SW2);
ostoja 0:981049ce9511 54 int sw2_state;
ostoja 0:981049ce9511 55 // Pointer to a WiFi network object:
ostoja 0:981049ce9511 56 WiFiInterface *wifi;
ostoja 0:981049ce9511 57 // Creating TCP socket:
ostoja 0:981049ce9511 58 TCPSocket socket;
ostoja 0:981049ce9511 59 // Creating MQTT client using the TCP socket;
ostoja 0:981049ce9511 60 MQTTClient client(&socket);
ostoja 0:981049ce9511 61 // Message handler:
ostoja 0:981049ce9511 62 MQTT::Message message;
ostoja 0:981049ce9511 63
ostoja 0:981049ce9511 64 char* topic = "pubpim";
ostoja 0:981049ce9511 65 char* topic_sub = "subpim";
ostoja 0:981049ce9511 66 // Counter of arrived messages:
ostoja 0:981049ce9511 67 int arrivedcount = 0;
ostoja 0:981049ce9511 68 int send_voltage = 0;
ostoja 0:981049ce9511 69 // Flag indicating that button is not pressed:
ostoja 0:981049ce9511 70 int button_pressed=0;
ostoja 0:981049ce9511 71 // HiveMQ broker connectivity information:
ostoja 0:981049ce9511 72 const char* hostname = "broker.hivemq.com";
ostoja 0:981049ce9511 73 int port = 1883;
ostoja 0:981049ce9511 74 // Returning a string for a provided network encryption:
ostoja 0:981049ce9511 75 const char *sec2str(nsapi_security_t sec)
ostoja 0:981049ce9511 76 {
ostoja 0:981049ce9511 77 switch (sec)
ostoja 0:981049ce9511 78 {
ostoja 0:981049ce9511 79 case NSAPI_SECURITY_NONE:
ostoja 0:981049ce9511 80 return "None";
ostoja 0:981049ce9511 81 case NSAPI_SECURITY_WEP:
ostoja 0:981049ce9511 82 return "WEP";
ostoja 0:981049ce9511 83 case NSAPI_SECURITY_WPA:
ostoja 0:981049ce9511 84 return "WPA";
ostoja 0:981049ce9511 85 case NSAPI_SECURITY_WPA2:
ostoja 0:981049ce9511 86 return "WPA2";
ostoja 0:981049ce9511 87 case NSAPI_SECURITY_WPA_WPA2:
ostoja 0:981049ce9511 88 return "WPA/WPA2";
ostoja 0:981049ce9511 89 case NSAPI_SECURITY_UNKNOWN:
ostoja 0:981049ce9511 90 default:
ostoja 0:981049ce9511 91 return "Unknown";
ostoja 0:981049ce9511 92 }
ostoja 0:981049ce9511 93 }
ostoja 0:981049ce9511 94
ostoja 0:981049ce9511 95 int scan_networks(WiFiInterface *wifi)
ostoja 0:981049ce9511 96 {
ostoja 0:981049ce9511 97 printf("Scan:\n");
ostoja 0:981049ce9511 98
ostoja 0:981049ce9511 99 // Scan only for the number of networks, first parameter is NULL:
ostoja 0:981049ce9511 100 int count = wifi->scan(NULL, 0);
ostoja 0:981049ce9511 101 // If there are no networks, count == 0, if there is an error, counter < 0:
ostoja 0:981049ce9511 102 if (count <= 0)
ostoja 0:981049ce9511 103 {
ostoja 0:981049ce9511 104 printf("scan() failed with return value: %d\n", count);
ostoja 0:981049ce9511 105 return 0;
ostoja 0:981049ce9511 106 }
ostoja 0:981049ce9511 107
ostoja 0:981049ce9511 108 // Limit number of network arbitrary to some reasonable number:
ostoja 0:981049ce9511 109 count = count < MAX_NETWORKS ? count : MAX_NETWORKS;
ostoja 0:981049ce9511 110
ostoja 0:981049ce9511 111 // Create a local pointer to an object, which is an array of WiFi APs:
ostoja 0:981049ce9511 112 WiFiAccessPoint *ap = new WiFiAccessPoint[count];
ostoja 0:981049ce9511 113 // Now scan again for 'count' networks and populate the array of APs:
ostoja 0:981049ce9511 114 count = wifi->scan(ap, count);
ostoja 0:981049ce9511 115
ostoja 0:981049ce9511 116 // This time, the number of entries to 'ap' is returned:
ostoja 0:981049ce9511 117 if (count <= 0)
ostoja 0:981049ce9511 118 {
ostoja 0:981049ce9511 119 printf("scan() failed with return value: %d\n", count);
ostoja 0:981049ce9511 120 return 0;
ostoja 0:981049ce9511 121 }
ostoja 0:981049ce9511 122
ostoja 0:981049ce9511 123 // Print out the parameters of each AP:
ostoja 0:981049ce9511 124 for (int i = 0; i < count; i++)
ostoja 0:981049ce9511 125 {
ostoja 0:981049ce9511 126 printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(),
ostoja 0:981049ce9511 127 sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
ostoja 0:981049ce9511 128 ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5], ap[i].get_rssi(), ap[i].get_channel());
ostoja 0:981049ce9511 129 thread_sleep_for(PRINTF_DELAY_MS);
ostoja 0:981049ce9511 130 }
ostoja 0:981049ce9511 131 printf("%d networks available.\n", count);
ostoja 0:981049ce9511 132
ostoja 0:981049ce9511 133 // Since 'ap' is dynamically allocated pointer to the array of objects, it
ostoja 0:981049ce9511 134 // needs to be deleted:
ostoja 0:981049ce9511 135 delete[] ap;
ostoja 0:981049ce9511 136 return count;
ostoja 0:981049ce9511 137 }
ostoja 0:981049ce9511 138
ostoja 0:981049ce9511 139 void print_text(int len, char buf[100]){
ostoja 0:981049ce9511 140 if(arrivedcount > 5){
ostoja 0:981049ce9511 141 arrivedcount = 0;
ostoja 0:981049ce9511 142 myOled.clearDisplay();
ostoja 0:981049ce9511 143 }
ostoja 0:981049ce9511 144 for(int i = 0;i < len; i++){
ostoja 0:981049ce9511 145 myOled.drawChar(10 + i * 6,1 + 10 * arrivedcount,buf[i],1,0,1);
ostoja 0:981049ce9511 146 }
ostoja 0:981049ce9511 147 myOled.display();
ostoja 0:981049ce9511 148 }
ostoja 0:981049ce9511 149
ostoja 0:981049ce9511 150 void messageArrived(MQTT::MessageData& md)
ostoja 0:981049ce9511 151 {
ostoja 0:981049ce9511 152 MQTT::Message &message = md.message;
ostoja 0:981049ce9511 153 //printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
ostoja 0:981049ce9511 154 printf("Message from the browser: %.*s\r\n", message.payloadlen, (char*)message.payload);
ostoja 0:981049ce9511 155 char buf[100];
ostoja 0:981049ce9511 156 sprintf(buf,"%.*s", message.payloadlen, (char*)message.payload);
ostoja 0:981049ce9511 157
ostoja 0:981049ce9511 158 printf("%s\r\n",buf);
ostoja 0:981049ce9511 159
ostoja 0:981049ce9511 160 ++arrivedcount;
ostoja 0:981049ce9511 161 print_text(message.payloadlen,(char*)message.payload);
ostoja 0:981049ce9511 162
ostoja 0:981049ce9511 163 if(strcmp(buf,"start")==0){
ostoja 0:981049ce9511 164 send_voltage = 1;
ostoja 0:981049ce9511 165 }
ostoja 0:981049ce9511 166
ostoja 0:981049ce9511 167 if(strcmp(buf,"stop")==0){
ostoja 0:981049ce9511 168 send_voltage = 0;
ostoja 0:981049ce9511 169 }
ostoja 0:981049ce9511 170 }
ostoja 0:981049ce9511 171
ostoja 0:981049ce9511 172 void buttonFunction() {
ostoja 0:981049ce9511 173 button_pressed=1;
ostoja 0:981049ce9511 174 }
ostoja 0:981049ce9511 175
ostoja 0:981049ce9511 176 int main()
ostoja 0:981049ce9511 177 {
ostoja 0:981049ce9511 178 myOled.begin();
ostoja 0:981049ce9511 179 i2c.frequency(I2C_FREQUENCY);
ostoja 0:981049ce9511 180 // Set the interrupt event:
ostoja 0:981049ce9511 181 sw1.fall(&buttonFunction);
ostoja 0:981049ce9511 182
ostoja 0:981049ce9511 183 // Create a default network interface:
ostoja 0:981049ce9511 184 wifi = WiFiInterface::get_default_instance();
ostoja 0:981049ce9511 185 if (!wifi) {
ostoja 0:981049ce9511 186 printf("ERROR: No WiFiInterface found.\n");
ostoja 0:981049ce9511 187 return -1;
ostoja 0:981049ce9511 188 }
ostoja 0:981049ce9511 189
ostoja 0:981049ce9511 190 // Scan for available networks and aquire information about Access Points:
ostoja 0:981049ce9511 191 int count = scan_networks(wifi);
ostoja 0:981049ce9511 192 if (count == 0) {
ostoja 0:981049ce9511 193 printf("No WIFI APs found - can't continue further.\n");
ostoja 0:981049ce9511 194 return -1;
ostoja 0:981049ce9511 195 }
ostoja 0:981049ce9511 196
ostoja 0:981049ce9511 197 // Connect to the network with the parameters specified in 'mbed_app.json':
ostoja 0:981049ce9511 198 printf("\nConnecting to %s...\n", MBED_CONF_APP_WIFI_SSID);
ostoja 0:981049ce9511 199 int ret = wifi->connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
ostoja 0:981049ce9511 200 if (ret != 0) {
ostoja 0:981049ce9511 201 printf("\nConnection error: %d\n", ret);
ostoja 0:981049ce9511 202 return -1;
ostoja 0:981049ce9511 203 }
ostoja 0:981049ce9511 204
ostoja 0:981049ce9511 205 // Print out the information aquired:
ostoja 0:981049ce9511 206 printf("Success\n\n");
ostoja 0:981049ce9511 207 printf("MAC: %s\n", wifi->get_mac_address());
ostoja 0:981049ce9511 208 printf("IP: %s\n", wifi->get_ip_address());
ostoja 0:981049ce9511 209 printf("Netmask: %s\n", wifi->get_netmask());
ostoja 0:981049ce9511 210 printf("Gateway: %s\n", wifi->get_gateway());
ostoja 0:981049ce9511 211 printf("RSSI: %d\n\n", wifi->get_rssi());
ostoja 0:981049ce9511 212
ostoja 0:981049ce9511 213 // Open TCP socket using WiFi network interface:
ostoja 0:981049ce9511 214 socket.open(wifi);
ostoja 0:981049ce9511 215 // Connect to the HiveMQ broker:
ostoja 0:981049ce9511 216 socket.connect(hostname, port);
ostoja 0:981049ce9511 217 // Fill connect data with default values:
ostoja 0:981049ce9511 218 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
ostoja 0:981049ce9511 219 // Change only ID and protocol version:
ostoja 0:981049ce9511 220 data.MQTTVersion = 3;
ostoja 0:981049ce9511 221 data.clientID.cstring = "NUCLEO-L476RG-60";
ostoja 0:981049ce9511 222
ostoja 0:981049ce9511 223 // Connect the
ostoja 0:981049ce9511 224 int rc = 0;
ostoja 0:981049ce9511 225 if ((rc = client.connect(data)) != 0)
ostoja 0:981049ce9511 226 printf("rc from MQTT connect is %d\r\n", rc);
ostoja 0:981049ce9511 227
ostoja 0:981049ce9511 228 if ((rc = client.subscribe(topic_sub, MQTT::QOS2, messageArrived)) != 0)
ostoja 0:981049ce9511 229 printf("rc from MQTT subscribe is %d\r\n", rc);
ostoja 0:981049ce9511 230
ostoja 0:981049ce9511 231 while (true) {
ostoja 0:981049ce9511 232
ostoja 0:981049ce9511 233 // Show that the loop is running by switching motherboard LED2:
ostoja 0:981049ce9511 234 led2 = !led2;
ostoja 0:981049ce9511 235 //thread_sleep_for(BLINKING_RATE_MS);
ostoja 0:981049ce9511 236 if (button_pressed==1 && send_voltage == 1) {
ostoja 0:981049ce9511 237 button_pressed=0;
ostoja 0:981049ce9511 238 // QoS 0
ostoja 0:981049ce9511 239 char buf[100];
ostoja 0:981049ce9511 240 sprintf(buf, "V(POT1) = %1.2f\r\n", pot1*VOLTAGE_SCALER);
ostoja 0:981049ce9511 241 message.qos = MQTT::QOS0;
ostoja 0:981049ce9511 242 message.retained = false;
ostoja 0:981049ce9511 243 message.dup = false;
ostoja 0:981049ce9511 244 message.payload = (void*)buf;
ostoja 0:981049ce9511 245 message.payloadlen = strlen(buf)+1;
ostoja 0:981049ce9511 246 client.publish(topic, message);
ostoja 0:981049ce9511 247 ++arrivedcount;
ostoja 0:981049ce9511 248 print_text(14,buf);
ostoja 0:981049ce9511 249
ostoja 0:981049ce9511 250 }
ostoja 0:981049ce9511 251 // Need to call yield API to maintain connection:
ostoja 0:981049ce9511 252 client.yield(YIELD_TIMEOUT_MS);
ostoja 0:981049ce9511 253 }
ostoja 0:981049ce9511 254 }