...

Group Assignment 11

Group 2

  • Student
  • Student
  • Student

Group 3

  • Student
  • Student
  • Student

Group 1

Evelyn Cuadrado

Jhonatan Cortes

In this project, I teamed up with my partner Jonathan, he from Colombia and I from Peru. Sometimes, the distance seemed like a challenge, but we were able to work efficiently. Especially in this assignment on MQTT, it was very helpful. The technology allowed us to overcome the distance barrier and collaborate seamlessly. This project taught us a lot and showed us how remote connectivity can be used to accomplish complex tasks.


1. FIRST PROJECT


1.1 MDF garage with servomotor application, integrated alarm system, and automated lighting.


Initially, to avoid simply making a connection between boards, I decided to create a mini project using laser cutting on MDF. In this case, Jhonatan designed a small garage where we installed a servomotor. We had doubts about whether a microservo would be sufficient to lift the structure, so we opted for a 25 kg servomotor to have better control. Additionally, Jhonatan had already planned to control the servomotor from his PCB, so he connected everything from Colombia.


Here we can see more closely the PCB and the circuit Jhonatan has, as it includes several output devices with which we interacted in this exercise, such as the buzzer, the RGB LED, and the servomotor.


1.2 MQTT subscription

Since we are in different countries, one of the best ways to interconnect was through the Internet. In this case, we used MQTT as a communication tool. So, we created the subscriber Link in MQTTX. To understand how to install, configure, and create it, we reviewed the documentation Evelyn shared with us.


From this program, we validated the correct creation of the topic through which the messages would be sent. We performed some tests by sending messages from each home and verified that they were received correctly. For example, Evelyn sent data from Peru, and in Colombia, it was received without problems.


1.3 Arduino IDE code


Subscriber


                        #include          // No install, it's ready
                            #include  // Install library PubSubClient
                            #include    // Librería compatible con ESP32 para controlar el servo
                            
                            // Setup your WIFI with SSID/Password
                            const char* ssid = "tatanc";
                            const char* password = "87654321";
                            
                            // Setup your MQTT Protocol
                            const char* mqttServer = "broker.emqx.io";
                            const char* mqttClient = "ESP32C3FacAcademyean007";
                            const char* mqttTopicSub = "fabacademy/grupal";
                            const char* mqttTopicSub2 = "fabacademy/led";
                            WiFiClient espClient;
                            PubSubClient client(espClient);
                            
                            // Setup your process
                            const int servoPin = 14;   // Pin del servo
                            const int buzzerPin = 19;  // Pin del buzzer
                            const int redPin = 5;      // Pin del LED rojo
                            const int greenPin = 4;    // Pin del LED verde
                            const int bluePin = 6;     // Pin del LED azul
                            
                            Servo myServo;  // Crea un objeto servo
                            
                            void setup() {
                              Serial.begin(115200);
                              // Connecting to Wi-Fi
                              Serial.print("Connecting to ");
                              Serial.println(ssid);
                              WiFi.begin(ssid, password);
                              while (WiFi.status() != WL_CONNECTED) {
                                delay(500);
                                Serial.print(".");
                              }
                              Serial.println("");
                              Serial.println("Connected with IP ");
                              Serial.println(WiFi.localIP());
                            
                              // Connecting to MQTT
                              client.setServer(mqttServer, 1883);
                              client.setCallback(callback);
                              connectMQTT();
                            
                              // Setup ESP32 pins
                              pinMode(buzzerPin, OUTPUT);
                              pinMode(redPin, OUTPUT);
                              pinMode(greenPin, OUTPUT);
                              pinMode(bluePin, OUTPUT);
                              
                              // Conectar el servo al pin
                              myServo.attach(servoPin);
                              // Inicializa el LED RGB en azul mientras espera
                              digitalWrite(bluePin, HIGH);
                              digitalWrite(redPin, LOW);  // Apaga el LED rojo
                              digitalWrite(greenPin, LOW); // Apaga el LED verde
                              myServo.write(0);           // Inicia el servo en 0°
                            }
                            
                            void callback(char* topic, byte* message, unsigned int length) {
                              Serial.print("Arrived on ");
                              Serial.print(topic);
                              Serial.print(" with message ");
                              String messageTemp;  
                              for (int i = 0; i < length; i++) {
                                Serial.print((char)message[i]);
                                messageTemp += (char)message[i];
                              }
                              Serial.println();
                              
                              if (String(topic) == mqttTopicSub) {
                                if (messageTemp == "closed") {
                                  closedAction();
                                }
                                else if (messageTemp == "open") {
                                  openAction();
                                }
                              }
                            }
                            
                            void openAction() {
                              // Mover el servo gradualmente a 75 grados
                              for (int pos = 0; pos <= 75; pos++) {
                                myServo.write(pos);   // Mueve el servo a la posición 'pos'
                                delay(50);            // Retraso para movimiento gradual
                              }
                            
                              // Emitir un beep gradualmente
                              beepGradual(5);
                            
                              // Encender el LED verde
                              digitalWrite(greenPin, HIGH);
                              digitalWrite(redPin, LOW);  // Apagar el LED rojo
                              digitalWrite(bluePin, LOW); // Apagar el LED azul
                            }
                            
                            void closedAction() {
                              // Emitir un beep continuo
                             for (int i = 0; i < (7*2); i++) {
                                digitalWrite(buzzerPin, HIGH); // Enciende el buzzer
                                delay(100);                    // Beep por 300ms
                                digitalWrite(buzzerPin, LOW);  // Apaga el buzzer
                                delay(100);                    // Espera entre beeps
                              }
                            
                              // Encender el LED rojo
                              digitalWrite(redPin, LOW);
                              digitalWrite(greenPin, LOW);  // Apagar el LED verde
                              digitalWrite(bluePin, HIGH);   // Apagar el LED azul
                            
                              // Mover el servo de vuelta a 0 grados
                              for (int pos = 75; pos >= 0; pos--) {
                                myServo.write(pos);   // Mueve el servo a la posición 'pos'
                                delay(50);            // Retraso para movimiento gradual
                              }
                            }
                            
                            void beepGradual(int times) {
                              for (int i = 0; i < times; i++) {
                                digitalWrite(buzzerPin, HIGH); // Enciende el buzzer
                                delay(300);                    // Beep por 300ms
                                digitalWrite(buzzerPin, LOW);  // Apaga el buzzer
                                delay(300);                    // Espera entre beeps
                              }
                            }
                            
                            void connectMQTT() {
                              Serial.print("Connecting to MQTT Server ... ");
                              if (client.connect(mqttClient)) {
                                Serial.println("Connected");
                                client.subscribe(mqttTopicSub);  // Subscribe to the topic
                              } else {
                                Serial.print("failed, rc=");
                                Serial.print(client.state());
                                Serial.println(" try again in 5 seconds");
                                delay(5000);
                              }
                            }
                            
                            void loop() {
                              if (!client.connected()) {
                                connectMQTT();
                              }
                              client.loop();
                            }
                            
                    

Now, we move on to the process of implementing it on the boards. In this exercise, the publisher is located in Peru, and the subscriber is in Colombia. Below, we can see the code used in more detail. It includes the necessary libraries, first configuring the Wi-Fi network to which the board connects, then the MQTT protocol, and finally defining the pins. What the code really does is simple: it reads what is published on the topic. If the message is "open", it opens the door, emits a sound, and turns on the green light. If it is "closed", it lowers the servomotor. In this case, "open" corresponds to a 75° angle, so it will move to 0°, emit a different beep, and turn on another light.


With the code ready, it was uploaded to an ESP32 S3 Devkit located in Bogotá, Colombia.


Publisher


                        #include          // No install, it's ready
                            #include  // Install library PubSubClient
                            
                            // Setup your WIFI with SSID/Password
                            const char* ssid = "CHAYITOS";
                            const char* password = "CHIHUAY123";
                            
                            // Setup your MQTT Protocol
                            //const char* mqtt_server = "test.mosquitto.org";
                            const char* mqttServer = "broker.emqx.io";
                            const char* mqttClient = "evkusi";
                            const char* mqttTopicPub = "fabacademy/grupal";
                            WiFiClient espClient;
                            PubSubClient client(espClient);
                            
                            // Setup your process
                            float varNum = 0;
                            long nowTime, lastTime;
                            
                            void setup() {
                              Serial.begin(115200);
                              // Connecting to Wifi
                              Serial.print("Connecting to ");
                              Serial.println(ssid);
                              WiFi.begin(ssid, password);
                              while (WiFi.status() != WL_CONNECTED) {
                                delay(500);
                                Serial.print(".");
                              }
                              Serial.println("");
                              Serial.println("Connected with IP ");
                              Serial.println(WiFi.localIP());
                              // Connecting to MQTT
                              client.setServer(mqttServer, 1883);
                              connectMQTT();
                            
                            }
                            
                            void connectMQTT() {
                              Serial.print("Connecting to MQTT Server ... ");
                              if (client.connect(mqttClient)) {
                                Serial.println("Connected");
                              } else {
                                Serial.print("failed, rc=");
                                Serial.print(client.state());
                                Serial.println(" try again in 5 seconds");
                                delay(5000);
                              }
                            }
                            void loop() {
                              if (!client.connected()) {
                                connectMQTT();
                              }
                              client.loop();
                            
                              
                                client.publish(mqttTopicPub, "open");
                                delay(5000);
                            
                              client.publish(mqttTopicPub, "closed");
                                delay(5000);
                            }
                            
                            
                    

The publisher has a simpler code, with less complexity, as it subscribes to the MQTT topic and, using a millis() process to avoid blocking the board’s execution, sends an "open" or "closed" message every 5 seconds.


Getting into more detail, this publisher was uploaded to a Seeed XIAO ESP32-C3 board, and we can see the Wi-Fi configuration in the first lines of the code.


As mentioned earlier, the millis() function allows background counting, allowing the device to operate without blocking, only performing the task of counting.


In the loop part, we used the MQTT function to publish. It is important to note that only text characters can be sent, as it does not accept numbers. After sending the messages, we wait for some time before continuing.


The process is repeated to send the "closed" message and allow the project in Colombia to open or close the garage door.


In the image below, we can see that the code was uploaded to both the ESP32 S3 and the XIAO ESP32-C3, located in different countries. After uploading the code, we proceeded to view the project’s execution on the screen.


1.4. Results

From Colombia's point of view, we can see on the screen when the "open" message arrives, which opens the door and changes the light, with the same happening for the "closed" message. In both cases, the buzzer emits a completely different beep.



In the next video, we can observe that the actual emitter is a XIAO from another country, sending the instructions. The instructions stop being sent when Evelyn removes the power from the board.



2. SECOND PROJECT


2.1 Neo Pixel Led


For this project, we will use a Neopixel (or a Neopixel strip), which is a type of addressable LED, meaning each LED on the strip can be controlled independently. We will use a board such as the ESP8266 or ESP32 to connect the Neopixel to a WiFi network, allowing it to be controlled remotely over a wireless connection.


2.2 MQTT subscription

To connect, it is necessary to fill in the general data that are essential for establishing a connection via MQTT. One of the most important parameters is the port, which in this case is 1883. This port is crucial, as it allows communication between devices and ensures that both parties can connect properly. It is important that this data remains consistent so that other users can also connect without issues.

Additionally, by generating a username, we are creating a unique identifier for each user. This username will be used to recognize and authenticate each client that connects to the MQTT server. It is essential that the username is unique and well-managed to avoid connection conflicts.


Now, we will subscribe to the topic fabacademy/neopixel. It is crucial that the topic is written correctly, as in MQTT (the messaging protocol), subscribing to the topic is case-sensitive. This means that if we write the topic incorrectly, such as FabAcademy/NeoPixel or FABACADEMY/NEOPIXEL, it will not work properly because the MQTT server expects the topic to be written exactly as it is defined. Therefore, we need to ensure the topic is written correctly: fabacademy/neopixel.


2.3 Arduino IDE code


Subscriber


                        #include          // No install, it's ready
                            #include  // Install library PubSubClient
                            #include  // Install Adafruit NeoPixel library
                            
                            // Setup your WIFI with SSID/Password
                            const char* ssid = "CHAYITOPOWER";
                            const char* password = "CHIHUAY123";
                            
                            // Setup your MQTT Protocol
                            const char* mqttServer = "broker.emqx.io";
                            const char* mqttClient = "evkusi";
                            const char* mqttTopicSub = "fabacademy/neopixel";
                            WiFiClient espClient;
                            PubSubClient client(espClient);
                            
                            // Setup NeoPixel Pin
                            #define PIN            A0  // Pin de datos al que está conectada la tira NeoPixel
                            #define NUM_PIXELS     30 // Número de LEDs en la tira (ajústalo a tus necesidades)
                            #define BRILLO         255 // Brillo máximo (puedes ajustar este valor)
                            Adafruit_NeoPixel strip(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
                            
                            // Variable to handle MQTT messages
                            String mqttMessage = "";
                            
                            void setup() {
                              Serial.begin(115200);
                              
                              // Connecting to Wifi
                              Serial.print("Connecting to ");
                              Serial.println(ssid);
                              WiFi.begin(ssid, password);
                              while (WiFi.status() != WL_CONNECTED) {
                                delay(500);
                                Serial.print(".");
                              }
                              Serial.println("");
                              Serial.println("Connected with IP ");
                              Serial.println(WiFi.localIP());
                              
                              // Setup MQTT
                              client.setServer(mqttServer, 1883);
                              client.setCallback(callback);
                              
                              // Initial connection to MQTT
                              connectMQTT();
                            
                              // Setup NeoPixel
                              strip.begin();
                              strip.show();  // Apaga todos los LEDs al inicio
                            }
                            
                            void callback(char* topic, byte* message, unsigned int length) {
                              String messageTemp = "";
                              for (int i = 0; i < length; i++) {
                                messageTemp += (char)message[i];
                              }
                              
                              Serial.print("Arrived on ");
                              Serial.print(topic);
                              Serial.print(" the message ");
                              Serial.println(messageTemp);
                            
                              // Store the message to process in the loop
                              mqttMessage = messageTemp;
                            
                              // Create algorithm for controlling LEDs
                              if (String(topic) == mqttTopicSub) {
                                if (mqttMessage == "on") {
                                  strip.fill(strip.Color(0, 255, 0)); // Verde
                                  strip.show();
                                }
                                else if (mqttMessage == "off") {
                                  strip.fill(strip.Color(0, 0, 0));  // Apagar
                                  strip.show();
                                }
                                else if (mqttMessage == "random") {
                                  cambiarColorAleatorio();
                                }
                              }
                            }
                            
                            void connectMQTT() {
                              while (!client.connected()) {
                                Serial.print("Connecting to MQTT Server... ");
                                if (client.connect(mqttClient)) {
                                  Serial.println("Connected");
                                  // Subscribe to the MQTT topic
                                  client.subscribe(mqttTopicSub);
                                } else {
                                  Serial.print("Failed, rc=");
                                  Serial.print(client.state());
                                  Serial.println(" Try again in 5 seconds");
                                  delay(5000);
                                }
                              }
                            }
                            
                            void loop() {
                              if (!client.connected()) {
                                connectMQTT();
                              }
                              client.loop();
                            }
                            
                            // Function to set a random color to all NeoPixels
                            void cambiarColorAleatorio() {
                              for (int i = 0; i < strip.numPixels(); i++) {
                                // Generate random values for red, green, and blue (from 0 to 255)
                                int rojo = random(0, 256);
                                int verde = random(0, 256);
                                int azul = random(0, 256);
                                
                                // Set the color of each LED with the random values
                                strip.setPixelColor(i, strip.Color(rojo, verde, azul));
                              }
                              strip.show(); // Update the strip with the new colors
                            }
                            
                    

As a subscriber, you need to have a code that allows you to connect to the MQTT server and receive messages from the desired topic. A crucial aspect of this process is the connection to the local network, as we need to be connected to a WiFi network in order to interact with the MQTT server. To do this, you must provide the network password to gain access.

As a subscriber, you need to have a code that allows you to connect to the MQTT server and receive messages from the desired topic. A crucial aspect of this process is the connection to the local network, as we need to be connected to a WiFi network in order to interact with the MQTT server. To do this, you must provide the network password to gain access.

As an MQTT client, the device (in this case, the EVKUSI) will connect to the server with the necessary credentials (such as username and password), and then subscribe to the specific topic, in this case, fablab/neopixel. By subscribing to this topic, the client will be able to receive messages published under that topic.


In the Arduino IDE, after preparing the code to connect the device to the MQTT server, you need to perform key configurations:

  1. Select the correct board in Tools > Board.
  2. Select the correct port in Tools > Port.
  3. Install the necessary libraries such as PubSubClient for MQTT and WiFi.h (for ESP32C3)
  4. Configure the WiFi network by entering the SSID and password in the code.
  5. Configure the MQTT server with the address broker.emqx.io and the topic fablab/neopixel.
  6. Upload the code to the board by clicking the Upload button in the IDE.

Publisher


                        #include           // Librería WiFi
                            #include   // Librería para el protocolo MQTT
                            #include  // Librería NeoPixel
                            
                            // Configuración WiFi
                            const char* ssid = "tatanc";
                            const char* password = "87654321";
                            
                            // Configuración MQTT
                            const char* mqttServer = "broker.emqx.io";
                            const char* mqttClient = "ESP32C3FacAcademyean007";
                            const char* mqttTopicPub = "fabacademy/neopixel"; // Tema de publicación
                            WiFiClient espClient;
                            PubSubClient client(espClient);
                            
                            // Configuración de NeoPixel
                            #define TOUCH_PIN 2    // Pin del sensor táctil
                            #define NEOPIXEL_PIN 4 // Pin de datos para el NeoPixel (ajustado al pin 4)
                            #define NUM_PIXELS 1   // Solo un LED
                            #define BRILLO 255     // Brillo máximo
                            
                            Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
                            
                            // Variables para el control de tiempo y estados
                            int varNum = 0;
                            long nowTime, lastTime;
                            String status = "off";  // Estado inicial del LED
                            bool lastTouchState = LOW; // Estado anterior del sensor táctil
                            bool currentTouchState = LOW; // Estado actual del sensor táctil
                            
                            void setup() {
                              Serial.begin(115200);
                              
                              // Conectar a WiFi
                              Serial.print("Conectando a WiFi ");
                              WiFi.begin(ssid, password);
                              while (WiFi.status() != WL_CONNECTED) {
                                delay(500);
                                Serial.print(".");
                              }
                              Serial.println(" Conectado");
                              Serial.println("IP: " + WiFi.localIP().toString());
                              
                              // Conectar a MQTT
                              client.setServer(mqttServer, 1883);
                              connectMQTT();
                              
                              // Inicializar el NeoPixel
                              strip.begin();
                              strip.show();  // Apagar el LED al inicio
                            
                              // Configurar pin del sensor táctil
                              pinMode(TOUCH_PIN, INPUT);
                            }
                            
                            void connectMQTT() {
                              Serial.print("Conectando a servidor MQTT ... ");
                              while (!client.connected()) {
                                if (client.connect(mqttClient)) {
                                  Serial.println("Conectado");
                                } else {
                                  Serial.print("fallo, rc=");
                                  Serial.print(client.state());
                                  Serial.println(" Reintentando en 5 segundos");
                                  delay(5000);
                                }
                              }
                              client.subscribe(mqttTopicPub); // Suscribirse al tema (si es necesario)
                            }
                            
                            void loop() {
                              if (!client.connected()) {
                                connectMQTT();
                              }
                              client.loop();
                            
                              // Leer el valor del sensor táctil
                              currentTouchState = digitalRead(TOUCH_PIN);
                            
                              // Detectar si el sensor táctil ha cambiado de estado
                              if (currentTouchState == HIGH && lastTouchState == LOW) {
                                // Si el sensor táctil fue presionado
                                if (status == "off") {
                                  // Si el LED está apagado, encenderlo
                                  strip.setPixelColor(0, strip.Color(255, 0, 0));  // LED rojo
                                  strip.show();
                                  client.publish(mqttTopicPub, "on");  // Publicar estado "on"
                                  status = "on";  // Cambiar el estado a "on"
                                } else {
                                  // Si el LED está encendido, apagarlo
                                  strip.setPixelColor(0, strip.Color(0, 0, 0));  // Apagar LED
                                  strip.show();
                                  client.publish(mqttTopicPub, "off");  // Publicar estado "off"
                                  status = "off";  // Cambiar el estado a "off"
                                }
                                delay(500);  // Esperar medio segundo para evitar lecturas múltiples por un solo toque
                              }
                            
                              lastTouchState = currentTouchState;  // Guardar el estado actual del sensor táctil
                            
                              delay(100);  // Espera de 100 ms para el siguiente ciclo
                            }
                            
                    

Now, for the publisher, a similar configuration was done as for the subscriber, with the difference that key parameters, such as the WiFi settings and the MQTT client, were modified. These changes are essential for the device to publish messages instead of receiving them via MQTT.


2.4. Results


In the results, we can see the successful connection via MQTT, even though my partner is kilometers away, specifically in Colombia, while I am in Peru. However, this challenge can be carried out without complications. As a publisher, he can send his sensor data and control the turning on and off of the LED remotely.

In this result, another function of the NeoPixel can be verified, which allows the colors of the LED strip to change dynamically. By using the random keyword, the colors were generated randomly. Every time the random function was called again, the colors would change unpredictably, creating surprising visual effects.

Fab Lab Lima - Creative Commons Attribution Non Commercial

Source code hosted at Fab Lab Lima 2025

|