Note: This is my first post here, and I'm sure there are plenty of bad practices in the code. The code is "functioning," but not exactly how I want it to. Any tips with general improvements to the code are appreciated as well.
I'm working on a project where I have two buttons, one implemented using the Blynk platform and the other using an RF remote control, both controlling the state of a light (which is then used to control the servo to turn the light switch ON/OFF physically). The state of the light is tracked using a shared Boolean variable named LightState. When LightState is false, the light is turned off, and when it's true, the light is turned on.
Hardware used:
- ESP32-S3 N16R8 Dev Board (Board selected in Arduino IDE: ESP32-S3-USB-OTG)
- RXB6 433MHz Wireless Receiver Module
- RF Remote Control 433MHz
- SG90 Servo
Hardware Connections:
- SG90 Servo connected to GPIO 14
- RXB6 433 MHz receiver module connected to GPIO 4
The Problem:
The issue I'm encountering involves the synchronization between these two buttons. I want both buttons to be in perfect sync with each other. In other words, if one button turns the light on, the other button should recognize this change and turn the light off when it's pressed, and vice versa.
Behaviour Description:
- When I press the Blynk button first to turn the light on, it works as expected. The RF remote button in code recognizes that the light is on (as boolean LightState is already set properly by the Blynk button) and can turn it off without (sync) issues.
- However, when I use the RC remote first to turn the light on, the two buttons get out of sync. The Blynk button sometimes seems to be unaware of the current state of the light and attempts to turn it on again, even though it's already on (and vice versa).
Expected issue:
I believe that the issue of sync might be caused by the flow of code, as the Blynk function comes earlier in the code and the RF remote code is in a void loop. So, the Blynk function sets the "LightState" properly, which is used by the RF remote code, in a void loop and works as expected. However, an issue arises when we do it the other way around, where the "LightState" is set in the later part of the code in the void loop by the RF remote code and then used by the Blynk function in the earlier part of the code.
Code explanation (from what I understand):
For the Blynk IoT Button:
When the button from the Blynk IoT App is pressed, the received value (integer 1 or 0) is stored in the "LightState" boolean variable.
Next, I check if the value received is 1 or 0 and use the switch...case accordingly. If the value is 0, then I want the servo position to be set to 20 degrees. If the value is 1, then I want the servo position to be set to 160 degrees.
For the RF remote button:
First I check if the button is pressed.
Since the RF remote sends just a single value "7749524", I use another boolean variable, "buttonPressed," to keep track of the button state and to toggle the "LightState" accordingly.
Next, if the button was pressed, like with the Blynk IoT button, if the "LightState" = 0, then I want the servo position to be set to 20 degrees. If "LightState" = 1, then I want the servo position to be set to 160 degrees.
Complete Code:
#define BLYNK_TEMPLATE_ID "" // Define Blynk template ID
#define BLYNK_TEMPLATE_NAME "" // Define Blynk template name
#define BLYNK_AUTH_TOKEN "" // Define Blynk authentication token
#define BLYNK_PRINT Serial // Use the Serial interface for Blynk
char ssid[] = ""; // Define Wi-Fi SSID
char pass[] = ""; // Define Wi-Fi password
#include <WiFi.h> // Include the WiFi library
#include <WiFiClient.h> // Include the WiFiClient library
#include <BlynkSimpleEsp32.h> // Include the Blynk library for ESP32
#include <ESP32Servo.h> // Include the ESP32Servo library for servo control
#include <RCSwitch.h> // Include the RCSwitch library for remote control
RCSwitch mySwitch = RCSwitch(); // Create an instance of the RCSwitch class for remote control
int Servo_Position; // Variable to hold the servo position
int Default_Servo_Position = 90; // Default servo position
bool LightState = false; // Track the state of the light
bool buttonPressed = false; // Track if the button was pressed
int delay_time = 200; // Delay time in milliseconds
Servo servo; // Create a servo object
BLYNK_WRITE(V5) { // Blynk virtual pin handler
LightState = (param.asInt()); // Read the value from Blynk virtual pin V5
servo.write(Default_Servo_Position); // Set the servo to the default position
switch (LightState) { // Check the state of the light
case false: // If light is off
Servo_Position = 20; // Set servo position to 20 degrees
servo.write(Servo_Position); // Move the servo to the specified position
delay(delay_time); // Delay for a certain time
servo.write(Default_Servo_Position); // Move the servo back to the default position
break;
case true: // If light is on
Servo_Position = 160; // Set servo position to 160 degrees
servo.write(Servo_Position); // Move the servo to the specified position
delay(delay_time); // Delay for a certain time
servo.write(Default_Servo_Position); // Move the servo back to the default position
break;
}
Serial.print("Light state: "); // Print the light state
Serial.print(LightState ? "ON" : "OFF"); // Print "ON" if LightState is true, otherwise "OFF"
Serial.print(" / ");
Serial.print("Servo Position: ");
Serial.println(Servo_Position); // Print the Servo_Position
}
void setup() {
Serial.begin(115200); // Start serial communication
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass); // Initialize Blynk with the authentication token and Wi-Fi credentials
mySwitch.enableReceive(4); // Enable receiving signals on GPIO pin 4
servo.attach(14); // Attach the servo to GPIO pin 14
}
void loop() {
Blynk.run(); // Run Blynk
// Check if a signal has been received
if (mySwitch.available()) {
// Read the received signal
unsigned long rc_code = mySwitch.getReceivedValue();
Serial.print("Received "); // Print "Received"
Serial.print(mySwitch.getReceivedValue()); // Print the received value
Serial.print(" / ");
// Check if the signal is valid and corresponds to the desired button
if (rc_code != 0 && rc_code == 7749524) { // If a valid signal is received
LightState = !LightState; // Toggle the light state
buttonPressed = true; // Set buttonPressed to true
}
delay(100); // Delay to avoid processing multiple times for a single button press
mySwitch.resetAvailable(); // Reset the received value for the next signal
}
// Check if the button was pressed
if (buttonPressed) {
// Toggle the servo position based on the updated state
switch (LightState) {
case false: // If light is off
Servo_Position = 20; // Set servo position to 20 degrees
break;
case true: // If light is on
Servo_Position = 160; // Set servo position to 160 degrees
break;
}
delay(delay_time); // Delay for a certain time
servo.write(Default_Servo_Position); // Move the servo back to the default position
delay(delay_time); // Delay for a certain time
servo.write(Servo_Position); // Move the servo to the specified position
delay(delay_time); // Delay for a certain time
servo.write(Default_Servo_Position); // Move the servo back to the default position
Serial.print("Light state: "); // Print the light state
Serial.print(LightState ? "ON" : "OFF"); // Print "ON" if LightState is true, otherwise "OFF"
Serial.print(" / ");
Serial.print("Servo Position: ");
Serial.println(Servo_Position); // Print the Servo_Position
buttonPressed = false; // Reset the button state
}
}