Try   HackMD

Multi-protocol communication tutorial

tags: ESP8266 ESP32 MQTT Socket I2C TCP

About Project:

This project consist of 4 different Nodes.
Once user Start Node 1 it dose a self test and connect to Wifi.
and print info in UART log and on OLED Screen, Then Connect to MQTT Server, based on info in the code below. Then start to publish NoT Pressed until we Touch the Button ,that run interrupt to toggle the value of control Boolean parameter called (is_pressed)into our example.
So the MCU will send by next loop a "Pressed" to Node 2 over Topic called "Button". and subscribe to Topic " Temp".

Node 2, which is ESP32 DOIT ESP DEVKITV1, at that time ,
subscribe to "Button" Topic and if Get NoT Press , do nothing, just continue looping , BUT if got "Pressed" Then it send '1' over Socket to Node 3,Which is my computer, that Run Python code, and Listen on Port 8888 To generate a random number between (-20,50).then send 'G' (If number bigger than -10), or 'R' (if Number smaller than-10) back on the same socket to Node 2! then disconnect the socket.

Node 2 will take the Read rom socket and send Either :
"Green" over Topic "Temp" if it got 'G' or
"RED " over Topic "Temp" if it got 'R'.

Node 1, is subscribing to "Temp" so in function "callback" will get the Payload and blink the RED or Green according to bytes received Using Function "Blink".

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Executing Sequance over 4 nodes - schema

Each Line of this table describe what happen in each node
I triend to minimise the waiting time of our MCU as well as storage needed for code and dynamic memory.
so in node #1
Sketch uses 292108 bytes (27%) of program storage space. Maximum is 1044464 bytes.
Global variables use 28484 bytes (34%) of dynamic memory,
leaving 53436 bytes for local variables.

and in Node #2 :
Sketch uses 715114 bytes (54%) of program storage space. Maximum is 1310720 bytes.
Global variables use 40200 bytes (12%) of dynamic memory,
leaving 287480 bytes for local variables.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
List of Materials?

Node 1: The Slave or Edge Device:

  • Adafruit Feather HUZZAH with ESP8266, more info Here , and here we find out how to connect to Arduino IDE
  • Adafruit SSD1306 i2C 128X32 , more info Here
  • Touch Button or press button.
  • RED and Green LED
  • Mosquitto Cloud / Local Server , more info Here. More info about Library Here

How connect prephirales to Adafruit Feather HUZZAH:

  • Connect The Interrupt Touch Button to GPIO14, We can connect to any but GPIO16.
  • Connect the Red LED to to GPIO 13
  • Connect the Green LED to to GPIO 12
  • I2C SSD1306 Oled to SCL @GPIO-05 , and SDA@GPIO-04
How about Interrupt:

Interrupts are useful for making things happen automatically in microcontroller programs and can help solve timing problems.

With interrupts you don’t need to constantly check the current pin value. When a change is detected, an event is triggered – a function is called. This function is called interrupt service routine (ISR).

When an interrupt happens, the processor stops the execution of the main program to execute a task, and then gets back to the main program as shown in the figure below

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

This is especially useful to trigger an action whenever motion is detected or whenever a pushbutton is pressed without the need to constantly check its state.

attachInterrupt() Function
To set an interrupt in the Arduino IDE, you use the attachInterrupt() function, that accepts as arguments: the GPIO interrupt pin, the name of the function to be executed, and mode:

attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);
GPIO interrupt pin
The first argument is a GPIO interrupt. You should use digitalPinToInterrupt(GPIO) to set the actual GPIO as an interrupt pin. For example, if you want to use GPIO 14 as an interrupt, use:

digitalPinToInterrupt(14)
The ESP8266 supports interrupts in any GPIO, except GPIO16.

ISR
The second argument of the attachInterrupt() function is the name of the function that will be called every time the interrupt is triggered – the interrupt service routine (ISR).

The ISR function should be as simple as possible, so the processor gets back to the execution of the main program quickly.

The best approach is to signal the main code that the interrupt has happened by using a global variable and within the loop() check and clear that flag, and execute code.

ISRs need to have ICACHE_RAM_ATTR before the function definition to run the interrupt code in RAM.

Interrupt modes
The third argument is the mode and there are 3 different modes:

  • CHANGE: to trigger the interrupt whenever the pin changes value – for example from HIGH to LOW or LOW to HIGH;
  • FALLING: for when the pin goes from HIGH to LOW;
  • RISING: to trigger when the pin goes from LOW to HIGH.

The Code of Node 1:

The code is well commeted with all info and links to libraries , for more info don't hesitate to contact me at ammar@dsna.se

// File Name : Node1.ino //ProJect Name : Multi-Protocol data transfering. //(I'm Using MQTT,I2c,Socket over TCP). //About Project: // This project consist of 4 different Nodes, Node One : // Node 1 : This node, that is AdaFruit Feather // HUZZA ESP8266. you an find all about it here : //https://www.adafruit.com/product/2821 // as we see into this code we connect : //// 1- Adafruit SSD1306 i2C 128X32. all info is here : // https://www.adafruit.com/product/931 //// 2- Mosquitto Cloud / Local Server as you like // All info here: https://mosquitto.org/ ////3- LED RED and LED Green for signal. ////4- Touch button with Touch Sensor. ////////////////////////////////////////////////////////////// //RunTime Overview : //Once user Start Node 1 it dose a self test and connect to Wifi //and print info inUART log and on OLED Screen, //Then Connect to MQTT Server,based on info in the code below. // Then start to publish NoT Pressed untlil we Touch the Button , //that run interrupt to toggle the value of control boolean //parameter called (is_pressed)into our example. // So the MCU will send by next loop a "Pressed" to Node 2 //over Topic called "Button". and scubscripe to Topic " Temp". // Node 2, which is ESP32 DOIT ESP DEVKITV1, at that time , //subscribe to "Button" Topic and if // if Get NoT Press , do nothing, just continue loopin , BUT if got //"Pressed" Then it send '1' over Socket to Node 3,Wich is my computer, //that Run Python code, // and Listen on Port 8888 To generate a random number between (-20,50). // then send 'G' (If number bigger than -10), or 'R' (if Number smaller than // -10) back on the same socket to Node 2! then disconnect the socket. // Node 2 will take the Read rom socket and send: // "Green" over Topic "Temp" if it got 'G' or // "RED " over Topic "Temp" if it got 'R'. // Node 1, is subscribing to "Temp" so in function "callback" will //get the Payload and blink the RED or Green according to bytes recived // Using Function "Blink". ////////////////////////////////////////////////////////////////// // I Opmised the code so it takes max //Sketch uses 292108 bytes (27%) of program storage space. Maximum is 1044464 bytes. //Global variables use 28484 bytes (34%) of dynamic memory, //leaving 53436 bytes for local variables. ////////////////////////////////////////////////////////////////// /////Author Ammar Alnahhas //// ammar@dsna.se //// Date : 2021-01-03 //// Lic : free to use. //// Project Video : https://youtu.be/wCLGnwUo1hA //// Project Tutorial Link : https://hackmd.io/@DSNA22/Multi_protocol_communication_tutorial ////////////////////////////////////////////////////////////////// #include <ESP8266WiFi.h> #include <PubSubClient.h> //https://github.com/knolleary/pubsubclient #include <Adafruit_GFX.h> //https://github.com/adafruit/Adafruit-GFX-Library #include <Adafruit_SSD1306.h> //https://github.com/adafruit/Adafruit_SSD1306 #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // Reset pin # (or -1 if sharing Arduino reset pin) in ESP we set LED_BUILTIN #define OLED_RESET LED_BUILTIN // Update these with values suitable for your network. const char* ssid = "*********"; const char* password = "********"; // Mosquitto CLOUD Server Adress and port // Set your comuter IP adress or cloud Broker test.mosquitto.org // Or thier servar IP as 5.196.95.208 const char* mqtt_server = "test.mosquitto.org"; /// cloude MQTT Broker int mqtt_port = 1883; // Instant of Wifi Client class to use in MQTT init. WiFiClient espClient; PubSubClient client(espClient); // Button that cause interrupt & change the status of our Bool Par. //PS. use any but not GPIO 16. const byte interruptPin = 14; //GPIO 14 (Touch Button) bool is_Pressed=false; long lastReconnectAttempt = 0; // init. Adafruit SSD1306 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // LED REd and Green Pins const byte RED_L=13; const byte GREEN_L=12; void Blink (byte led,int dur); void setup() { Serial.begin(115200); // Setup LEDs as Output and blink them to test pinMode(RED_L,OUTPUT); pinMode(GREEN_L,OUTPUT); Blink (RED_L,50); Blink (GREEN_L,50); //set up OLED with I2c on addr0x3C if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } // Printing My Logo My_loop_Flash_text("DSNA" , 35,10,2); display.clearDisplay(); My_loop_Flash_text("Connecting to Wifi" , 0,10,1); display.clearDisplay(); // Call this function to set up Wifi // based on ESP8266WiFi.h setup_wifi(); //Once Connected // Set up MQTT Server client.setServer(mqtt_server, mqtt_port); // Set up MQTT callback function client.setCallback(callback); // Logging Serial.println("Connected "); Serial.print("MQTT Server "); Serial.print(mqtt_server); Serial.print(":"); Serial.println(String(mqtt_port)); Serial.print("Node 1 ESP8266 IP : "); Serial.println(WiFi.localIP()); Serial.println("Modbus RTU Master Online"); // Print on Oled My_loop_Flash_text("Connected to MQTT" , 0,10,1); display.clearDisplay(); // Set up interrupt by touching our button pinMode(interruptPin, INPUT_PULLUP); // Raising interrupt uppon pressing the touch sensor attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING); // have a look for handleInterrupt function at the tail of tese scripts } void loop() { // Optional if follow Basic MQTT Loop sequance /*if (!client.connected()) { reconnect(); }*/ reconnect(); client.loop(); // To reconnect if need once per 10 Sec. delay(10000); } /////////////////////////////////////////////////////////////////// ////////////////////MQTT Functions //////////////////////// /////////////////////////////////////////////////////////////////// void setup_wifi() { delay(10); // We start by connecting to a WiFi network WiFi.mode(WIFI_STA); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // Print on OLED My_loop_Flash_text("Connectd to Wifi" , 0,10,1); String IP_addr = WiFi.localIP().toString(); My_loop_Flash_string( IP_addr, 16,10,1); display.clearDisplay(); } /////////////////////////////////////////////////////////////////// void callback(char* topic, byte* payload, unsigned int length) { // Log in UART Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i< length; i++) { Serial.print((char)payload[i]); } Serial.println(); if ((char)payload[0]=='R'){ //recevide RED from Node 2 Serial.println("RED Recived from Node 2!"); My_loop_Flash_text("RED Rcv." , 0,10,1); display.clearDisplay(); Blink (RED_L,1000); // Switch of the Button is_Pressed=false; }//IF else { if ((char)payload[0]=='G'){ //recevide GREEN from Node 2 Serial.println("GREEN Recived from Node 2!"); My_loop_Flash_text("GREEN Rcv." , 0,10,1); display.clearDisplay(); Blink (GREEN_L,1000); // Switch of the Button is_Pressed=false; } } } /////////////////////////////////////////////////////////////////// void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("DSNA@ESP8266")) { // Make sure to Be Unique once use // Cloud Mosquitto otherwise u maye get rc=-2 error. Serial.println("connected"); if (is_Pressed){ // if pressed then publish "press" Serial.println(" Press is Published on Button topic"); // under "Button" 3 times to garanti delivery for (int i=0;i<3;i++){ client.publish("Button", "Press"); Serial.println(" Press is Published on Button topic"); delay(1000);} // Write to OLED My_loop_Flash_text("Published: Press" , 0,10,1); display.clearDisplay(); // Switch Off Buttons is_Pressed=false; //Subscribe on Topic Temp client.subscribe("Temp"); } else { // Otherwise Publish only No_Press(keep a live) client.publish("Button", "Not_Press"); Serial.println(" NoT_Press is Published on Button topic"); My_loop_Flash_text("Published: NoT Press" , 0,10,1); display.clearDisplay(); } } else { // Logs: Once we coudn't reach the MQTT Server Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } /////////////////////////////////////////////////////////////////// ICACHE_RAM_ATTR void handleInterrupt() { //Interrurp handler // Not too many sub procedures to not cause Processor Overhead Serial.println("Button Pressed"); // Toggle is Pressed (0/1) if (is_Pressed){ is_Pressed=false; Serial.println("Switch OFF"); } // Change the status of isPressed else { is_Pressed=true; Serial.println("Switch ON"); } } ////////////////////////////////////////////////////////////////// void Blink (byte led,int dur){// Blink Function digitalWrite(led,HIGH); delay(dur); digitalWrite(led,LOW); delay(dur); } /////////////////////////////////////////////////////////////////// ////////////////////Oled Screen Function //////////////////////// /////////////////////////////////////////////////////////////////// void My_loop_Flash_text(const char *Text , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.write(Text); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_string(String Text , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font // Length (with one extra character for the null terminator) int str_len = Text.length() + 1; // Prepare the character array (the buffer) char char_array[str_len]; // Copy it over Text.toCharArray(char_array, str_len); display.write(char_array); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_Number(double My_Number , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(My_Number); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_Number(int My_Number , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(My_Number); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_Number_con (int My_Number , int posX, int posY, int Font_Size) { //display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(My_Number); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_text(const char *Text , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.write(Text); display.display(); delay(2000); } /////////////////////////////////////////////////////////////////////////////

Node 2 : the main hub or router

  • DOIT ESP32 DEVKIT V1, more info Here
  • Adafruit SSD1306 i2C 128X32 , more info Here
  • Mosquitto Cloud / Local Server , more info Here. More info about Library Here

How connect prephirales to DOIT ESP32 DEVKIT V1:

  • Connect I2C SSD1306 Oled to SCL @GPIO-22 , and SDA@GPIO-21

Have Look for my other projects with this MCU to get a toturial of how to manage this board with arduino IDE here

The Code of Node 2:

The code is well commeted wit hall info and links to libraries , for more info don't hesitate to contact me at ammar@dsna.se

// File Name : Node_2_ESP32.ino.ino //ProJect Name : Multi-Protocol data transfering. //(I'm Using MQTT,I2c,Socket over TCP). //About Project: // This project consist of 4 different Nodes, Node One : // Node 2 : This node, DOIT ESP32 DEVKIT V1 //More info here : //https://randomnerdtutorials.com/getting-started-with-esp32/ // as we see into this code we connect : //// 1- Adafruit SSD1306 i2C 128X32. all info is here : // https://www.adafruit.com/product/931 //// 2- Mosquitto Cloud / Local Server as you like // All info here: https://mosquitto.org/ // No Extra Libraries ar included for Socket I used these functions //built in i Wifi.h ////////////////////////////////////////////////////////////// //RunTime Overview : //Once user Start Node 1 it dose a self test and connect to Wifi //and print info inUART log and on OLED Screen, //Then Connect to MQTT Server,based on info in the code below. // Then start to publish NoT Pressed untlil we Touch the Button , //that run interrupt to toggle the value of control boolean //parameter called (is_pressed)into our example. // So the MCU will send by next loop a "Pressed" to Node 2 //over Topic called "Button". and scubscripe to Topic " Temp". // Node 2, which is ESP32 DOIT ESP DEVKITV1, at that time , //subscribe to "Button" Topic and if // if Get NoT Press , do nothing, just continue loopin , BUT if got //"Pressed" Then it send '1' over Socket to Node 3,Wich is my computer, //that Run Python code, // and Listen on Port 8888 To generate a random number between (-20,50). // then send 'G' (If number bigger than -10), or 'R' (if Number smaller than // -10) back on the same socket to Node 2! then disconnect the socket. // Node 2 will take the Read rom socket and send: // "Green" over Topic "Temp" if it got 'G' or // "RED " over Topic "Temp" if it got 'R'. // Node 1, is subscribing to "Temp" so in function "callback" will //get the Payload and blink the RED or Green according to bytes recived // Using Function "Blink". ////////////////////////////////////////////////////////////////// // I Opmised the code so it takes max //Sketch uses 715114 bytes (54%) of program storage space. Maximum is 1310720 bytes. //Global variables use 40200 bytes (12%) of dynamic memory, //leaving 287480 bytes for local variables ////////////////////////////////////////////////////////////////// /////Author Ammar Alnahhas //// ammar@dsna.se //// Date : 2021-01-03 //// Lic : free to use. //// Project Video : https://youtu.be/wCLGnwUo1hA //// Project Tutorial Link : https://hackmd.io/@DSNA22/Multi_protocol_communication_tutorial ////////////////////////////////////////////////////////////////// #include <WiFi.h> #include <PubSubClient.h> //https://github.com/knolleary/pubsubclient #include <Adafruit_GFX.h> //https://github.com/adafruit/Adafruit-GFX-Library #include <Adafruit_SSD1306.h> //https://github.com/adafruit/Adafruit_SSD1306 #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // Reset pin # (or -1 if sharing Arduino reset pin) in ESPwe set LED_BUILTIN #define OLED_RESET LED_BUILTIN // Update these with values suitable for your network. const char* ssid = "*********"; // Your Home Network const char* password = "*********"; // Your Home Network Password // Mosquitto CLOUD Server Adress and port // Set your comuter IP adress or cloud Broker test.mosquitto.org // Or thier servar IP as 5.196.95.208 const char* mqtt_server = "test.mosquitto.org"; /// MQTT Broker const int mqtt_port = 1883; // Our socket Server const char * Node_3_IP = "**********"; // Your Socket Listner and replier IP const int socket_port = 8888; // Our Example you can choose yours // Instant of Wifi Client class to use in MQTT init. WiFiClient esp32Client; PubSubClient client(esp32Client); // Inti. Soket Server WiFiServer server(socket_port); //Init Clinet for Socket WiFiClient S_client;// = server.available(); // init. Adafruit SSD1306 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //My_Function bool setup_wifi(void); void callback(char* topic, byte* payload, unsigned int length); void reconnect(void); bool setup_Socket(void); char*My_Socket_reader(); void My_Socket_Writer(char cmd); void My_loop_Flash_text(const char *Text , int posX, int posY, int Font_Size); void My_loop_Flash_string(String Text , int posX, int posY, int Font_Size); void My_Socket(); // Som controllers bits :) bool My_socket_Connected; bool Is_Pressed = false; void setup() { Serial.begin(115200); //set up OLED with I2c on addr0x3C if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } // Printing My Logo My_loop_Flash_text("DSNA" , 45,15,2); display.clearDisplay(); My_loop_Flash_text("Connecting to Wifi" , 0,10,1); display.clearDisplay(); if (setup_wifi()){ // Set up MQTT Server client.setServer(mqtt_server, mqtt_port); // Set up MQTT callback function client.setCallback(callback); Serial.println("Connected "); Serial.print("MQTT Server "); Serial.print(mqtt_server); Serial.print(":"); Serial.println(String(mqtt_port)); Serial.print("Node2 ESP32 IP "); Serial.println(WiFi.localIP()); Serial.println("Modbus RTU Master Online"); // Print on Oled My_loop_Flash_text("Connected to MQTT" , 0,10,1); display.clearDisplay(); My_socket_Connected=setup_Socket(); } } void loop() { // Optional if follow Basic MQTT Loop sequance /*if (!client.connected()) { reconnect(); }*/ reconnect(); //activiate it if you like to control //via Telnet Input from computer // Open Bash or cmd write: //telnet <this ESP IP addr> port 8888 //if(My_socket_Connected){ // My_Socket(); //} client.loop(); delay(10000); } /////////////////////////////////////////////////////////////////// ////////////////////MQTT Functions //////////////////////// /////////////////////////////////////////////////////////////////// bool setup_wifi() { delay(10); // We start by connecting to a WiFi network WiFi.mode(WIFI_STA); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // Print on OLED My_loop_Flash_text("Connected to Wifi" , 0,10,1); String IP_addr = WiFi.localIP().toString(); My_loop_Flash_string( IP_addr, 16,10,1); display.clearDisplay(); return true; } //////////////////////////////////////////////////////////////////// void callback(char* topic, byte* payload, unsigned int length) { // Log in UART // for optmization it is enough to just work with first char/Byte of Payload // Or we can take it all for future us using this variable //char My_Payload[length]; Option 2 if needed Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i< length; i++) { Serial.print((char)payload[i]); //My_Payload[i]=(char)payload[i]; Option 2 if needed } Serial.println(); if ((char)payload[0]=='P'){ //Sending 1 to Node 3 Serial.println("Button pressed in Node 1!"); Serial.println("sending 1 in Socket to Node 3!"); My_Socket_Writer('1'); My_loop_Flash_text("Button Pressed" , 0,10,1); display.clearDisplay(); // Reading the feedback from Node 3 Over SOCKET char S_payload; while (S_client.connected()){ S_payload = (char)S_client.read(); Serial.println(S_payload); Serial.print("Socket Payload : "); Serial.println(S_payload); // If We Got R-RED From Socket if ( S_payload=='R'){ for (int i=0;i<3;i++){ // Publish Red 5 times client.publish("Temp","Red"); Serial.println("Red is Published on TEMP Topic to Node 1"); My_loop_Flash_text("RED Pub" , 0,10,1); display.clearDisplay(); delay(1000); } } else { // If We Got G-GREEN From Socket if ( S_payload=='G') for (int i=0;i<3;i++){ //Publish Red 5 times client.publish("Temp","Green"); Serial.println("Green is Published on TEMP Topic to Node 1"); My_loop_Flash_text("GREEN Pub" , 0,10,1); display.clearDisplay(); delay(1000); }//for }//Else }//While connected } else{ // If e didn't Get P over MQTT Serial.println("Button NOT pressed in Node 1!"); Serial.println("Nothing to send to Node 3!"); My_loop_Flash_text("Button NOT Pressed" , 0,10,1); display.clearDisplay(); delay(10); } } //////////////////////////////////////////////////////////// void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("ESP32Client_DSNA")) {// Make sure to Be Unique once use // Cloud Mosquitto otherwise u maye get rc=-2 error. Serial.println("connected"); My_loop_Flash_text("Sub on Button" , 0,10,1); display.clearDisplay(); client.subscribe("Button"); Serial.println(" Subbscribe button "); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } //////////////////////////////////////////////////////// bool setup_Socket(){ // Set Up Socket Server server.begin(); Serial.print("Socket Server is connected to "); Serial.print(WiFi.localIP()); Serial.print(" on port "); Serial.println(socket_port); // Print on Oled My_loop_Flash_text("Socket Srv is READY" , 0,10,1); display.clearDisplay(); //My_loop_Flash_text("Telnet ip + 8888" , 0,10,1); //display.clearDisplay(); return true; } /////////////////////////////////////////////////////////// void My_Socket_Writer(char cmd){// To Write Data to Socket // Once Socket Connected if(!S_client.connect(Node_3_IP,socket_port)) { Serial.println("Failed to Connect to 8888 socket ");// If Server not started // Write to oled My_loop_Flash_text("Failed Con.8888" , 0,10,1); display.clearDisplay(); } else{ Serial.println("Write->Read Socket Connected"); S_client.print(cmd); // Send the Command ('1') // Write to oled My_loop_Flash_text("1 to Node_3 " , 0,10,1); display.clearDisplay(); // DON'T Stop the Client(DOn't Disconnect the Socket) //until you get the Reply. //S_client.stop(); Serial.println("cmd sent"); } } ///////////////////////////////////////////////////// ////////////Telnet option//////////////////////// void My_Socket(){ WiFiClient client = server.available(); if (client) { if(client.connected()) { Serial.println("read Socket Connected"); //return S_client.read(); } while(client.connected()){ while(client.available()>0){ // read data from the connected client Serial.write(client.read()); //return client.read(); } //Send Data to connected client while(Serial.available()>0) { client.write(Serial.read()); } } client.stop(); Serial.println("socket read"); } } /////////////////////////////////////////////////////////////////// ////////////////////Oled Screen Function //////////////////////// /////////////////////////////////////////////////////////////////// void My_loop_Flash_text(const char *Text , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.write(Text); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_string(String Text , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font // Length (with one extra character for the null terminator) int str_len = Text.length() + 1; // Prepare the character array (the buffer) char char_array[str_len]; // Copy it over Text.toCharArray(char_array, str_len); display.write(char_array); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_Number(double My_Number , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(My_Number); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_Number(int My_Number , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(My_Number); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_loop_Flash_Number_con (int My_Number , int posX, int posY, int Font_Size) { //display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(My_Number); display.display(); delay(2000); display.invertDisplay(true); delay(1000); display.invertDisplay(false); delay(1000); } void My_text(const char *Text , int posX, int posY, int Font_Size) { display.clearDisplay(); display.setTextSize(Font_Size); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(posX, posY); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.write(Text); display.display(); delay(2000); }

Node 3 : the Socket Server

  • Any Windows Computer with Python 3 or Rasberry PI.

How to connect :

Just Network or Wifi Ethernet Connection.

The Code of Node 3:

The code is well commeted wit hall info and links to libraries , for more info don't hesitate to contact me at ammar@dsna.se

import socket import random # receive 4096 bytes each time BUFFER_SIZE = 4096 if __name__ == '__main__': # device's IP address SERVER_HOST = "0.0.0.0" SERVER_PORT = 8888 ESP_HOST = "192.168.5.138" Socket_PORT = 8888 # create the server socket # TCP socket s = socket.socket() # bind the socket to our local address s.bind((SERVER_HOST, SERVER_PORT)) # enabling our server to accept connections # 5 here is the number of unaccepted connections that # the system will allow before refusing new connections s.listen(5) #print(f"[*] Listening as {SERVER_HOST}:{SERVER_PORT}") # accept connection if there is any while 1: print(f"[*] Listening as {SERVER_HOST}:{SERVER_PORT}") client_socket, address = s.accept() # if below code is executed, that means the sender is connected print(f"[+] {address} is connected.") # receive using client socket, not server socket while 1: received = client_socket.recv(32).decode() print(received) if received == '1': print(f"Button pressed") print(received) # Generating Random number rand = random.randint(-20, 50) # Print it out print(f"Temp is {rand}") if rand > -10: green = 'G' client_socket.send(green.encode()) client_socket.close() else: red = 'R' client_socket.send(red.encode()) client_socket.close() break else: print(f"Button Not pressed yet")

How it gonna Work :

Here come a guid of using this setup:
Filmed by DSNA!
https://youtu.be/wCLGnwUo1hA

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Some Output of project:

Node #1

Node#2
Fullscreen with Pyton NOde 3 Output

Node#3
The Socket Server output example from PYCharm :

DSNA22 OTHER Projects :

Thanks :

Thanks for Haithem S for all knowledge and experience that looks clearly in backscenes of this project!

More info about ESP32 DEVKIT V1 30 Pins

Introduction to ESP32 chip

  • ESP32-WROOM-32 is a very popular chip used for the internet of things applications. The main part of this module is ESP32-D0WDQ6 chip.
  • It has 48 pins but all pins are not available to use in devkit. You will see more information about it in the later part of this tutorial.
  • It consists of an on-chipWiFi module, Bluetooth low energy module, and Bluetooth module. So if you are working on an embedded systems project, where you need all these modules, you can simply use this board instead of using off the shelf all components one by one. Due to these features, it can be used for many embedded systems applications.
  • It is a very low-cost board and can be purchased around 10-15$.
  • It consists of two cores and each core can be controlled separately.
  • It can operate at the variablefrequency range from 80 MHz to 240 MHz.
  • It has a special ultra-low power co-processor. A user can power off processors and can use a low power coprocessor to monitor peripherals at low power like GPIO pins.

for more info Download this Complete Datasheet

And so looks mine after once connected to 2 small size Bredboard :

In Arduino IDE : we can add it by adding this Link :
https://dl.espressif.com/dl/package_esp32_index.json
Ps. use ',' if you have other boars as well!
Under :
FILE > Preferences Ctrl+Comma

After adding it we need to choose it under tools the write board and then the right port:


Thanks , for more info drop to my inbox : ammar@dsna.se.