This week's assignment was:
- Send a message between two projects.
- design, build, and connect wired or wireless node(s) with network or bus addresses and local input &/or output device(s).
ORGANIZATION
Here I show how I organized myself for this week.
Wednesday 24th: | Fab Academy classes, organization for the week and review of all materials and supplies available for the assignment. |
---|---|
Thursday 25Th: | Review and investigation of previous documentation to understand the individual assignment. Design and milling of board for assignment. |
Friday 26th: | Build, welding and first attempt to connect wired or wireless nodes. |
Saturday 27th: | Enter GLOBAL OPEN TIME to show my errors and ask some questions about the assignment and develop the group assignment with my colleagues. |
Sunday: 28th: | Carry out documentation of everything developed. |
Monday 29th: | Review and correction of documentation. Update and changes for last commit. |
Tuesday 30th: | Documentation and last commit of the week. |
GROUP ASSIGNMENT
Here I leave the link to go to the group assignments page.
Clic here to visit the WEEK 13 GROUP ASSIGNMENT PAGE
TESTING THE MQTTX PROGRAM
INSTALLING MQTTX
For group assignment we carried out many tests of how we could send messages between projects. We first researched the ways in which we could achieve this and the one that was most recommended to us was MQTTX. Which is a platform with servers where we can send messages from our board and it communicates through a channel that allows messages to be sent between microcontrollers or boards. Here the development process.
First, we download the MQTTX provided by the server page and download. We can use it on a PC or cell phone.
After downloading and installing the program. We open it and the following window will appear, here we have to click on NEW CONNECTION.
A new window will appear where we begin to write information about the server we are creating. We only need to fill in the NAME part since the rest does not need to be changed but we must take into account the information we have. Finally, we just click on CONNECT.
Here all the information about the created server will appear. Here we just click on NEW SUBSCRIPTION, as the image shows. Here a pop-up window will appear to fill in information. We only need to fill out the TOPIC, which in our case will be "HANS/LED" and click confirm.
Finally, a window will appear where the hans/led server will appear, here, we go to the bottom of the window, we change the TOPIC to the name of the server and we can send messages. In table No. 3 we can see how we send and receive the message we send. From here we are ready to start programming with this information.
Here is a screenshot of my meeting with my colleague Maryori to do the group assignment where we were configuring the MQTTX.
PROGRAMMING ARDUINO IDE
In order to connect our XIAO ESP32-C3 with the server that we created, we have to put all that information in the programming, remember to put our server data, our WIFI and we upload to the microcontroller.
#include WiFi.h
#include PubSubClient.h
// Replace the next variables with your SSID/Password combination
const char* ssid = "HBP WIRELES";
const char* password = "923279923";
// Add your MQTT Broker IP address, example:
//const char* mqtt_server = "192.168.1.144";
const char* mqtt_server = "broker.emqx.io";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
float numero = 0;
// LED Pin
const int ledPin = D3;
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pinMode(ledPin,OUTPUT);
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
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());
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTopic;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTopic += (char)message[i];
}
Serial.println();
if (String(topic) == "hans/led") {
Serial.print("Changing output to ");
if(messageTopic == "a"){
Serial.println("on");
digitalWrite(ledPin, HIGH);
}
else if(messageTopic == "b"){
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("hdmsclient1025")) {
Serial.println("connected");
// Subscribe
client.subscribe("hans/led");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
RESULT
As a result we can see that from the place where my friend Maryori is, we can send the message to turn on or off and the LED in my house turns on and off through the internet. We were surprised to achieve this.
SENDING A MESSAGE BETWEEN TWO PROJECTS
For the next section of my documentation that we develop as a group. I will show how a message was sent between 2 projects by cables and by wifi. We developed the first one through I2C communication, which is what we were able to achieve success with between wired communication and for Wi-Fi, we will use MQTTX so that both boards can communicate. Below is the process of each of them.
MESSAGE BETWEEN SILVANA BOARD AND MINE - WIRES I2C
To develop communication, we decided to use the Motion Sensor input that is connected to my board and a neopixel that we connect to Silvana's board. Before starting the communication between the 2 boards, we had to carry out a test on each board to see if it worked and whether the input and output were working correctly. Here is a screenshot of the neopixel on Silvana's board.
After checking that both the sensor and the neopixel were working normally. We now connect both boards via I2C wiring. Where we use jammers for communication.
PROGRAMMING
For programming, I2C communication was taken into account so that both can work via cables. The XIAO ESP32 C3 was used on my board and a XIAO RP2040 was used on Silvana's board. Here the programming of both boards.
HANS'S BOARD
#include Wire.h
const int sensorPin = D10; // PIN OF XIAO ESP32 C3
void setup() {
Wire.begin(); // Start I2C communication
pinMode(sensorPin, INPUT);
}
void loop() {
int sensorValue = digitalRead(sensorPin);
Wire.beginTransmission(9); // Slave address
Wire.write(sensorValue);
Wire.endTransmission();
delay(1000); // Wait for 1 second before reading the sensor again
}
SILVANA'S BOARD
#include Wire.h
#include Adafruit_NeoPixel.h
#define PIN 10 // PIN XIAO RP2040
#define NUMPIXELS 1
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
pixels.begin();
Wire.begin(9); // Slave address
Wire.onReceive(receiveEvent);
}
void loop() {
// There's no need to do anything in the slave's loop
}
void receiveEvent(int bytes) {
if (Wire.available()) {
int sensorValue = Wire.read();
if (sensorValue == 1) {
// If motion is detected, set Neopixel color to red
pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Red
pixels.show();
} else {
// If no motion is detected, set Neopixel color to green
pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Green
pixels.show();
}
}
}
RESULT
Here I show you the result of the connection between the 2 plates. We can see that when the motion sensor detects movement, it changes the color of the neopixel from green to red. Here are some videos of the results.
MESSAGE BETWEEN SILVANA BOARD AND MINE - WIFI + MQTTX
To achieve the message between the 2 boards via WIFI, we decided to communicate between 2 XIAO ESP32 C3 microcontrollers, where Silvana's board worked as a subscriber, since it contained the neopixel as output and my board worked as a publisher, with a switch that I have. on the board to send messages via MQTTX.
To achieve communication we use MQTTX, where we must have a publisher (my board) and a subscriber (silvana's board), where the latter receives information from the publisher, processes and performs the action that was programmed. Here I leave the work process between both plates.
First we connect both boards to a different computer and begin to program it so that they have communication between them via MQTTX.
PROGRAMMING
For programming, both boards have the XIAO ESP32 C3, where we previously carried out tests on the input and output that we were going to communicate. From there we created a TOPIC in the MQTTX to be able to read the message sent by the publisher and the subscriber read those messages and performed an action.
HANS'S BOARD
#include
#include
const char* ssid = "YourSSID";
const char* password = "YourPassword";
const char* mqtt_server = "broker.emqx.io";
const char* topic = "week13/wifi"; // Topic
const int switchPin = D2; // Switch Pin
WiFiClient espClient;
PubSubClient client(espClient);
int lastSwitchState = HIGH; // Previous switch state
void setup() {
Serial.begin(115200);
pinMode(switchPin, INPUT_PULLUP);
setup_wifi();
client.setServer(mqtt_server, 1883);
}
void setup_wifi() {
delay(10);
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());
}
void reconnect() {
while (!client.connected()) {
Serial.print("Connecting to MQTT server...");
if (client.connect("switchClient")) {
Serial.println("Connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" trying again in 5 seconds");
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
int switchState = digitalRead(switchPin);
if (switchState != lastSwitchState) { // If there's a change in switch state
if (switchState == LOW) {
client.publish(topic, "a");
Serial.println("Switch pressed");
} else {
client.publish(topic, "b");
Serial.println("Switch released");
}
lastSwitchState = switchState;
}
delay(100); // Small delay to avoid switch bounce
}
SILVANA'S BOARD
#include
#include
#include
const char* ssid = "YourSSID";
const char* password = "YourPassword";
const char* mqtt_server = "broker.emqx.io";
const char* topic = "week13/wifi"; // same topic to publisher
#define NEOPIXEL_PIN D10
#define NUM_PIXELS 1
WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pixels.begin();
}
void setup_wifi() {
delay(10);
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());
}
void callback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("Message received from topic ");
Serial.print(topic);
Serial.print(": ");
Serial.println(message);
if (message == "a") {
pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Red
pixels.show();
} else {
pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Green
pixels.show();
}
}
void reconnect() {
while (!client.connected()) {
Serial.print("Connecting to MQTT server...");
if (client.connect("neopixelClient")) {
Serial.println("Connected");
client.subscribe(topic);
} else {
Serial.print("Failed, rc=");
Serial.print(client.state());
Serial.println(" trying again in 5 seconds");
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
RESULT
Here I show you the result of the connection between the 2 plates. We can see that when the motion sensor detects movement, it changes the color of the neopixel from green to red. Here are some videos of the results.
SUPPORT AND FEEDBACK
GLOBAL OPEN TIME
On Saturday I joined the GLOBAL OPEN TIME group as always with Adrián, Rico, Pablo and the other colleagues. They supported me a lot about the assignment and understanding what the requirements were and we even played a small virtual game with Pablo to see if we were paying attention to class on Wednesday. You're going to excuse me but this time I don't have a screenshot and that's why I had to format my PC because it had a lot of information and it was slow. There went the photos from that day. I was sad to realize that I deleted them. Thank you teachers for your support.
MEETING WITH INSTRUCTOR
To achieve this week's assignment I also had support from my Instructor Ulysses, the truth is that he supported me a lot to understand communication and how I could work. Thank you very much teacher for the support.
INDIVIDUAL ASSIGNMENT
REDESIGN HM BOARD
To carry out the individual assignment, I redesigned my development board that I was working on in the past weeks because it did not have I2C communication or UART. Therefore, I designed 2 new boards from the HM board and designed a MASTER board and a NODE board. Here the process.
HM MASTER BOARD
For my HM MASTER board I wanted it to have the connections to be able to transmit I2C and UART on it since the previous one did not contain it. So I added these pins, where I took into account the RX and TX pins for the UART connection between boards.
Here is a 3D capture of what my board will look like and you can see at the bottom the new 6-pin connectors to achieve the I2C and UART connection. You may wonder why 6 pins was the only connector I had in the FAB LAB this week and to achieve this assignment I figured out how to develop it and it worked.
After reviewing all the connections, I went on to export the traces and the interior of the board for milling in MODS.CE. In the FILES part of my documentation you can find my HM MASTER file.
Finally, after obtaining the milled board I began to solder all the electronic components that I considered important for the board and here is a photograph of how the HM MASTER turned out.
HM NODO BOARD
For the NODE BOARD I had the same design as my master board but what changes is the connection for the UART protocol. Let's remember that this type of connection has RX AND TX, which means receiver and transmitter. It is important to keep in mind that to achieve this connection the pins must be exchanged so that it can be RX (master board) with TX of (node 1) and TX (master board) with RX of (node). It is important to take this into account, for the I2C protocol if there are no problems.
Here is a screenshot of how the traces and the interior turned out, which I also exported to the mods for their respective milling. Here are some screenshots of the process.
Finally, after milling and soldering all the components that I placed on the board, here is the result of my node board. For this board I will use the XIAO RP2040 for the assignment.
PROGRAMMING XIAO ESP32-C3
It is the first time that I am going to program the XIAO ESP32-C3 because I had not used it previously. Here I show you how to configure the ARDUINO IDE to be able to obtain the microcontroller libraries and to be able to carry out the programming.
First we open the ARDUINO IDE program, and we go to the FILE tab until we find the PREFERENCES tab and we click on it.
A window will open where we have to go to the button that is inside the red rectangle and click on it.
Here we have to paste the link that I will leave below. This is to import all the documents and information about the XIAO ESP32 - C3 that we need for programming. Here the link:
Finally, after giving ok to the previous step, we have to go to the BOARDS MANAGER tab that we find on the left side of the program and it is also in the TOOLS/BOARS/BOARDS MANAGER tab. Here we have to write only "ESP 32" and click on install the ESPRESSIF SYSTEMS option.
To start programming, we have to find the microcontroller in the program. In the following photograph we can see where we find the XIAO ESP32-C3 and we click on it and we are ready for programming.
WIRED I2C
SYNCING OF LEDS
To begin the communication between boards and microcontrollers I wanted to start with a simple one, which is LED synchronization, since each board has an LED, the idea is that these LEDs turn on in order, from the master board to the last node and turn on again. repeat. Here the process.
To achieve LED communication, we have to program the 3 boards first. Here I leave the programming codes for the ARDUINO IDE of the MASTER and the NODES.
PROGRAMMING
MASTER BOARD - LED
#include Wire.h
#define LED_PIN D3
#define SLAVE2_ADDRESS 10
#define SLAVE3_ADDRESS 11
void setup() {
Wire.begin();
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// Turn on the LED on the master board
digitalWrite(LED_PIN, HIGH);
delay(3000); // Wait for 3 seconds
digitalWrite(LED_PIN, LOW);
// Send signal to board 2 (first slave board)
Wire.beginTransmission(SLAVE2_ADDRESS);
Wire.write(1); // Any value representing turning on the LED
Wire.endTransmission();
delay(3000); // Wait for 3 seconds
Wire.beginTransmission(SLAVE2_ADDRESS);
Wire.write(0); // Any value representing turning off the LED
Wire.endTransmission();
// Send signal to board 3 (second slave board)
Wire.beginTransmission(SLAVE3_ADDRESS);
Wire.write(1); // Any value representing turning on the LED
Wire.endTransmission();
delay(3000); // Wait for 3 seconds
Wire.beginTransmission(SLAVE3_ADDRESS);
Wire.write(0); // Any value representing turning off the LED
Wire.endTransmission();
}
NODE BOARD 1 - LED
#include Wire.h
#define LED_PIN 29
void setup() {
Wire.begin(10); // Address of board 3 (second slave board)
Wire.onReceive(receiveEvent);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
delay(100);
}
void receiveEvent(int bytes) {
while (Wire.available()) {
int command = Wire.read();
if (command == 1) {
digitalWrite(LED_PIN, HIGH); // Turn on LED
delay(3000); // Wait for 3 seconds
digitalWrite(LED_PIN, LOW); // Turn off LED
}
}
}
NODE BOARD 2 - LED
#include Wire.h
#define LED_PIN 29
void setup() {
Wire.begin(11); // Address of board 3 (second slave board)
Wire.onReceive(receiveEvent);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
delay(100);
}
void receiveEvent(int bytes) {
while (Wire.available()) {
int command = Wire.read();
if (command == 1) {
digitalWrite(LED_PIN, HIGH); // Turn on LED
delay(3000); // Wait for 3 seconds
digitalWrite(LED_PIN, LOW); // Turn off LED
}
}
}
RESULT
As a result we can see that the LEDs do have synchronization on the master board and the nodes. Each LED turns on when the previous one turns off. First I2C communication test achieved.
SWITCH + LEDS
For the second communication test, the idea is to try to turn on the LEDS of the nodes from the SWITCH that I have on the master. The idea is that the SWITCH functions as INPUT and the LEDs have the characteristic of being OUTPUT. Here the process.
To achieve the following process, we have to program both the master board and we can repeat the programming for node 1 and node 2 since they will only turn on this time. Here I leave the programming code for ARDUINO IDE.
PROGRAMMING
MASTER BOARD - SWITCH
#include Wire.h
#define BUTTON_PIN 2
#define LED_PIN 3
#define SLAVE2_ADDRESS 10
#define SLAVE3_ADDRESS 11
void setup() {
Wire.begin();
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
bool buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW) {
// Turn on the LED on the master board
digitalWrite(LED_PIN, HIGH);
// Send signal to turn on the LEDs on the slave boards
Wire.beginTransmission(SLAVE2_ADDRESS);
Wire.write(1); // Turn on LED
Wire.endTransmission();
Wire.beginTransmission(SLAVE3_ADDRESS);
Wire.write(1); // Turn on LED
Wire.endTransmission();
} else {
// Turn off the LED on the master board
digitalWrite(LED_PIN, LOW);
// Send signal to turn off the LEDs on the slave boards
Wire.beginTransmission(SLAVE2_ADDRESS);
Wire.write(0); // Turn off LED
Wire.endTransmission();
Wire.beginTransmission(SLAVE3_ADDRESS);
Wire.write(0); // Turn off LED
Wire.endTransmission();
}
// Wait briefly to avoid rapid repetitions due to button bounce
delay(50);
}
NODE BOARD 1 AND 2 - LED
#include Wire.h
#define LED_PIN 29
void setup() {
Wire.begin(); // Start I2C communication
Wire.onReceive(receiveEvent); // Set up data reception function
pinMode(LED_PIN, OUTPUT); // Configure LED pin as output
}
void loop() {
delay(100); // Small pause to stabilize the loop
}
void receiveEvent(int bytes) {
while (Wire.available()) {
int command = Wire.read(); // Read the command sent by the master
if (command == 1) {
digitalWrite(LED_PIN, HIGH); // Turn on the LED
} else {
digitalWrite(LED_PIN, LOW); // Turn off the LED
}
}
}
RESULT
As a result, the programming for the switch to turn on the LEDs of the nodes works. Here is a video of the result.
MOTION SENSOR + LEDS
Now I carried out a test with a motion sensor, the idea is to ensure that when the sensor reads motion detection, the LEDs turn on and when it does not detect movement, the LEDs turn off. Here the development with a sensor.
To achieve the next challenge, we will do the programming for the master board and each node since it is necessary for everyone to communicate to know when the sensor detects movement and when it does not, so the LEDs that function as OUTPUTS can know when moment to catch on and not according to the information.
PROGRAMMING
MASTER BOARD - MOTION SENSOR
#include Wire.h
#define MOTION_SENSOR_PIN 10
#define SLAVE2_ADDRESS 10
#define SLAVE3_ADDRESS 11
bool motionDetected = false;
void setup() {
Wire.begin();
Serial.begin(9600); // Start serial communication to monitor the sensor's status
pinMode(MOTION_SENSOR_PIN, INPUT);
}
void loop() {
// Read the state of the motion sensor
motionDetected = digitalRead(MOTION_SENSOR_PIN);
// Print the sensor state to the serial monitor
Serial.print("Motion sensor state: ");
Serial.println(motionDetected ? "DETECTED" : "NOT DETECTED");
// Send signal to slave boards according to motion sensor state
if (motionDetected) {
// If motion is detected, send command to turn on LEDs on slave boards
Wire.beginTransmission(SLAVE2_ADDRESS);
Wire.write(1); // Turn on LED
Wire.endTransmission();
Wire.beginTransmission(SLAVE3_ADDRESS);
Wire.write(1); // Turn on LED
Wire.endTransmission();
} else {
// If no motion is detected, send command to turn off LEDs on slave boards
Wire.beginTransmission(SLAVE2_ADDRESS);
Wire.write(0); // Turn off LED
Wire.endTransmission();
Wire.beginTransmission(SLAVE3_ADDRESS);
Wire.write(0); // Turn off LED
Wire.endTransmission();
}
// Wait for a brief period before repeating the sensor reading
delay(100);
}
BOARD NODE 1 - LED
#include Wire.h
#define LED_PIN 29
void setup() {
Wire.begin(10); // Dirección de la placa 2
Wire.onReceive(receiveEvent);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// No se necesita lógica adicional en el bucle principal
}
void receiveEvent(int bytes) {
while (Wire.available()) {
int command = Wire.read();
if (command == 1) {
// Si se recibe un comando 1, encender el LED
digitalWrite(LED_PIN, HIGH);
} else {
// Si se recibe otro valor, apagar el LED
digitalWrite(LED_PIN, LOW);
}
}
}
BOARD NODE 2 - LED
#include Wire.h
#define LED_PIN 29
void setup() {
Wire.begin(11); // Dirección de la placa 3
Wire.onReceive(receiveEvent);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// No se necesita lógica adicional en el bucle principal
}
void receiveEvent(int bytes) {
while (Wire.available()) {
int command = Wire.read();
if (command == 1) {
// Si se recibe un comando 1, encender el LED
digitalWrite(LED_PIN, HIGH);
} else {
// Si se recibe otro valor, apagar el LED
digitalWrite(LED_PIN, LOW);
}
}
}
RESULT
As a result we can see that when the sensor detects movement, the LEDs of the nodes turn on and if it does not detect movement, they turn off.
MOTION SENSOR + NEOPIXEL
Now we will carry out the test with a motion sensor as input on the master board and a neopixel on a node as output. Communication is via I2C and when the motion detector detects movement it turns the neopixel red and if it does not detect movement it turns green. Here are some screenshots and the process.
Only by having 2 boards, we will program each of them so that it can work according to what was mentioned above, now the programming.
PROGRAMMING
MASTER BOARD - MOTION SENSOR
#include Wire.h
#define SENSOR_PIN 26 // Pin where the motion sensor is connected
void setup() {
Serial.begin(9600); // Start serial communication
Wire.begin(); // Initialize I2C communication
pinMode(SENSOR_PIN, INPUT); // Set motion sensor pin as input
}
void loop() {
// Read the state of the motion sensor
int motionState = digitalRead(SENSOR_PIN);
// Send the motion sensor state over serial port
if (motionState == HIGH) {
Serial.println("Motion detected");
} else {
Serial.println("No motion detected");
}
// Send the motion sensor state to the second board via I2C
Wire.beginTransmission(8); // Address of the second board on the I2C bus
Wire.write(motionState); // Send the motion sensor state
Wire.endTransmission();
delay(100); // Small delay before reading the motion sensor state again
}
BOARD NODE 1 - NEOPIXEL
#include Wire.h
#include Adafruit_NeoPixel.h
#define NEOPIXEL_PIN 3 // Pin donde está conectado el NeoPixel
#define NUM_PIXELS 1 // Número de NeoPixels en la tira
Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Wire.begin(8); // Inicializa la comunicación I2C con dirección 8
Wire.onReceive(receiveEvent); // Configura la función de recepción de datos I2C
pixels.begin(); // Inicializa el objeto NeoPixel
pixels.clear(); // Apaga todos los NeoPixels
pixels.show(); // Muestra los cambios
}
void loop() {
// No es necesario implementar código en el loop de la segunda placa
}
void receiveEvent(int bytes) {
// Lee el estado del sensor de movimiento enviado por la primera placa
int motionState = Wire.read();
// Enciende o apaga el NeoPixel según el estado del sensor de movimiento
if (motionState == HIGH) {
// Si se detecta movimiento, establece el color del NeoPixel a rojo
pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Rojo
} else {
// Si no se detecta movimiento, establece el color del NeoPixel a verde
pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Verde
}
pixels.show(); // Muestra los cambios en el NeoPixel
}
RESULT
As a result we can see that both boards work in communication where the master board sends the signal to the node and it changes color in the neopixel.
WIRELESS
LED ON AND OFF
To make the WIRELESS connection I will use the XIAO ESP32 C3 that has WIFI and BLUETOOTH and I will start programming to know how it works with an LED that my board has. The idea is to turn on the LED both manually and via WIFI. Here the process and the programming of the process.
PROGRAMMING
Since it is a single board, we will only have one programming code to ensure that via WiFi we can turn the LED on the board on and off. Here is the programming code for ARDUINO IDE, remember to increase < > in the libraries.
#include WiFi.h
#include WebServer.h
const char* ssid = "HBP WIRELES";
const char* password = "923279923";
const int ledPin = D6;
const int switchPin = D3;
bool ledState = false;
bool prevSwitchState = false;
unsigned long switchPressTime = 0;
const unsigned long switchDebounceTime = 50;
WebServer server(80);
void handleRoot() {
String html = "LED Control ";
html += "h1>LED CONTROL";
html += "form action=\"/led\" method=\"get\">";
html += "button name=\"state\" value=\"on\" type=\"submit\">TURN ON LED";
html += "/form>";
html += "form action=\"/led\" method=\"get\">";
html += "button name=\"state\" value=\"off\" type=\"submit\">TURN OFF LED";
html += "/form>";
html += "/body>";
server.send(200, "text/html", html);
}
void handleLED() {
String state = server.arg("state");
if (state == "on") {
digitalWrite(ledPin, LOW);
ledState = true;
Serial.println("LED turned ON");
} else if (state == "off") {
digitalWrite(ledPin, HIGH);
ledState = false;
Serial.println("LED turned OFF");
}
handleRoot();
}
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(switchPin, INPUT_PULLUP); // Configure D3 as input with internal pull-up resistor
digitalWrite(ledPin, HIGH);
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to Wi-Fi network...");
}
Serial.println("Connection successful");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, handleRoot);
server.on("/led", HTTP_GET, handleLED);
server.begin();
}
void loop() {
server.handleClient();
// Check if the physical switch is pressed and toggle the LED accordingly
bool switchState = digitalRead(switchPin);
if (switchState != prevSwitchState) {
if (switchState == LOW) {
switchPressTime = millis();
} else {
unsigned long switchReleaseTime = millis();
if (switchReleaseTime - switchPressTime >= switchDebounceTime) {
digitalWrite(ledPin, !ledState);
ledState = !ledState;
if (ledState) {
Serial.println("LED turned ON");
} else {
Serial.println("LED turned OFF");
}
}
}
prevSwitchState = switchState;
}
}
WIFI + SERVO MOTOR + NEOPIXEL
The last test I did is trying to synchronize a servo motor with a neopixel, where according to the angle that the servo motor moved, the neopixel took on a different color. All this controlled via WIFI where by pressing buttons on the computer, it changed color and angle. Here the process.
PROGRAMMING
For this case we need to program the 3 boards, the master where the XIAO ESP32 C3 is, which is the one that will connect via WIFI. Then NODE 1, which is where the Servo motor is located, and in node 2, the neopixel. Don't forget the < > signs for libraries.
MASTER BOARD
#include WiFi.h>
#include WebServer.h>
#include Wire.h>
const char* ssid = "HBP WIRELES";
const char* password = "923279923";
const int RP2040_Servo_Address = 0x08; // Address of RP2040 slave for servo
const int RP2040_Neopixel_Address = 0x09; // Address of RP2040 slave for Neopixel
WebServer server(80);
void handleRoot() {
String html = "";
html += "h1>SERVO CONTROL";
html += "form action=\"/servo\" method=\"get\">";
html += "button name=\"angle\" value=\"0\" type=\"submit\">0 degrees";
html += "button name=\"angle\" value=\"90\" type=\"submit\">90 degrees";
html += "button name=\"angle\" value=\"180\" type=\"submit\">180 degrees";
html += "/form>";
server.send(200, "text/html", html);
}
void handleServo() {
int angle = server.arg("angle").toInt();
Wire.beginTransmission(RP2040_Servo_Address);
Wire.write(angle);
Wire.endTransmission();
Wire.beginTransmission(RP2040_Neopixel_Address);
Wire.write(angle);
Wire.endTransmission();
delay(500); // Wait to allow the servo to fully move
handleRoot();
}
void setup() {
Serial.begin(115200);
Wire.begin(); // Start I2C communication as master
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to Wi-Fi network...");
}
Serial.println("Connection successful");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, handleRoot);
server.on("/servo", HTTP_GET, handleServo);
server.begin();
}
void loop() {
server.handleClient();
}
BOARD NODE 1 - SERVO MOTOR
#include Wire.h
#include Servo.h
const int SERVO_PIN = 2; // Pin connected to the servo
Servo servo;
void receiveEvent(int byteCount) {
int angle = Wire.read();
servo.write(angle);
}
void setup() {
Wire.begin(0x08); // Address of RP2040 slave in I2C communication
Wire.onReceive(receiveEvent); // Set up the data reception function
servo.attach(SERVO_PIN); // Assign the pin to the servo
}
void loop() {
// There's no need to do anything in the main loop
}
BOARD NODE 2 - NEOPIXEL
#include Wire.h
#include Adafruit_NeoPixel.h
const int NEOPIXEL_PIN = 3; // Pin connected to the Neopixel
const int NUM_PIXELS = 1; // Number of pixels in the Neopixel
Adafruit_NeoPixel pixels(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
void receiveEvent(int byteCount) {
int angle = Wire.read();
uint32_t color = getColor(angle);
pixels.clear();
pixels.setPixelColor(0, color);
pixels.show();
}
uint32_t getColor(int angle) {
if (angle == 0) {
return pixels.Color(255, 0, 0); // Red
} else if (angle == 90) {
return pixels.Color(0, 255, 0); // Green
} else if (angle == 180) {
return pixels.Color(0, 0, 255); // Blue
} else {
return pixels.Color(255, 255, 255); // White if angle is not defined
}
}
void setup() {
Wire.begin(0x09); // Address of RP2040 slave in I2C communication
Wire.onReceive(receiveEvent); // Set up the data reception function
pixels.begin(); // Initialize Neopixel
pixels.clear();
pixels.show(); // Turn off all pixels
}
void loop() {
// There's no need to do anything in the main loop
}
RESULT
First we look at the IP that the microcontroller gives us to be able to change the angle of the servomotor. Here is a screenshot of the programming and the buttons generated for the movement.
As a result we can see that the angle and color synchronization work. The red color of the neopixel means 0°, the green color means 90° and finally the blue color means 180°. Here are some photographs and video
CONCLUSIONS
This week's assignment has been very difficult for me because at first it was complicated and I didn't understand where to start and how to achieve the assignment. OPEN GLOBAL TIME and my advisor Ulysses helped me a lot and I thank him for supporting me in this assignment. In conclusion I can say that I2C programming seems better to me, it is easier than doing it through UART. I tried to do this last communication protocol but it didn't work for me. But it is a week where you learn much more and the truth is that it was difficult and challenging for me. In the end, here I show you what I achieved.
REVIEW OF THE CLASS
During the review of this class I volunteered in the minute 1:23:30
Clic here to 20240424 review from Academany on Vimeo.
FILES
Here you can download all the files that I have made for the following assignment: