ARDUINO example code for ESP32R4 controller.

This is the basic simple Arduino code for ESP32R4 controller.

Features:

  • WiFi network credentials;
  • Web interface Relays toggling;
  • Create classes for Relays with function ON(), OFF(), TOGGLE();
  • Create classes for Buttons with function UPDATE(), GETSTATE();
  • Hardware Interrupt function for Buttons activity;
  // Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"

class RELAY {
  public:
    byte pin;       //GPIO
    boolean state;  //state of relay
  private:
    boolean sw_mode; // Relay as Normally Open (NO)=0, Normally Close (NC)=1
  public:
    RELAY(byte pin) {
      // Use 'this->' to make the difference between the
      // 'pin' attribute of the class and the 
      // local variable 'pin' created from the parameter.
      this->pin = pin;
      init();
    }
    void init() {
      pinMode(pin, OUTPUT);
      // Always try to avoid duplicate code.
      // Instead of writing digitalWrite(pin, LOW) here,
      // call the function off() which already does that
      sw_mode=LOW;
      off();
    }

    void on() {
      digitalWrite(pin, HIGH);
      state=HIGH;
    }

    void off() {
      digitalWrite(pin, LOW);
      state=LOW;
    }

    void toggle() {
      if (state==HIGH) {
        digitalWrite(pin, LOW);
        state=LOW;
      }
      else if (state==LOW) {
        digitalWrite(pin, HIGH);
        state=HIGH;
      }
    }

//mode=0 OFF, mode=1 ON, mode=2 toggle
    void rlswitch(byte swmode) {
            if (swmode==0) {
              off();
            }
            if (swmode==1) {
              on();
            }
            if (swmode==2) {
              toggle();
            }
    }
}; // don't forget the semicolon at the end of the class

RELAY Relay1(25);
RELAY Relay2(26);
RELAY Relay3(33);
RELAY Relay4(32);

class BUTTON {
  public:
    byte pin;
    byte state;
  private:  
    byte lastReading;
    unsigned long lastDebounceTime = 0;
    unsigned long debounceDelay = 100;
  public:
    BUTTON(byte pin) {
      this->pin = pin;
      lastReading = LOW;
      init();
    }
    void init() {
      pinMode(pin, INPUT);
      update();
    }
    void update() {
      // You can handle the debounce of the button directly
      // in the class, so you don't have to think about it
      // elsewhere in your code
      byte newReading = digitalRead(pin);
      
      if (newReading != lastReading) {
        lastDebounceTime = millis();
      }
      if (millis() - lastDebounceTime > debounceDelay) {
        // Update the 'state' attribute only if debounce is checked
        state = newReading;
      }
      lastReading = newReading;
    }
    
    byte getState() {
      update();
      return state;
    }
    bool isPressed() {
      return (getState() == HIGH);
    }
}; // don't forget the semicolon at the end of the class

BUTTON button1(34);
BUTTON button2(35);
BUTTON button3(36);
BUTTON button4(39);

// Replace with your network credentials
const char* ssid = "[SSID NETWORK]";
const char* password = "[PASSWORD NETWORK]";

const char* PARAM_INPUT_1 = "relay";  
const char* PARAM_INPUT_2 = "state";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 3.0rem;}
    p {font-size: 3.0rem;}
    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px} 
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
    input:checked+.slider {background-color: #2196F3}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  %BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
  var xhr = new XMLHttpRequest();
  if(element.checked){ xhr.open("GET", "/update?relay="+element.id+"&state=1", true); }
  else { xhr.open("GET", "/update?relay="+element.id+"&state=0", true); }
  xhr.send();
}</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if(var == "BUTTONPLACEHOLDER"){
    String buttons ="";
      String relayStateValue = relayState(Relay1.pin);
      buttons+= "<h4>Relay 1</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=1"+ relayStateValue +"><span class=\"slider\"></span></label>";
      relayStateValue = relayState(Relay2.pin);
      buttons+= "<h4>Relay 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=2"+ relayStateValue +"><span class=\"slider\"></span></label>";
      relayStateValue = relayState(Relay3.pin);
      buttons+= "<h4>Relay 3</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=3"+ relayStateValue +"><span class=\"slider\"></span></label>";
      relayStateValue = relayState(Relay4.pin);
      buttons+= "<h4>Relay 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=4"+ relayStateValue +"><span class=\"slider\"></span></label>";
    return buttons;
  }
  return String();
}

String relayState(int pin_N){
    if(digitalRead(pin_N)){
      return "";
    }
    else {
      return "checked";
    }
 
  return "";
}

void action1() {
  if (digitalRead(button1.pin)==0){
  volatile byte buttonstate=digitalRead(button1.pin);
  delay(100); 
    if(digitalRead(button1.pin)==0){
      Relay1.toggle();
    }
  }
}

void action2() {
  if (digitalRead(button2.pin)==0){
  volatile byte buttonstate=digitalRead(button2.pin);
  delay(100); 
    if(digitalRead(button2.pin)==0){
      Relay2.toggle();
    }
  }
}

void action3() {
  if (digitalRead(button3.pin)==0){
  volatile byte buttonstate=digitalRead(button3.pin);
  delay(100); 
    if(digitalRead(button3.pin)==0){
      Relay3.toggle();
    }
  }
}

void action4() {
  if (digitalRead(button4.pin)==0){
  volatile byte buttonstate=digitalRead(button4.pin);
  delay(100); 
    if(digitalRead(button4.pin)==0){
      Relay4.toggle();
    }
  }
}


void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  // Set all relays to off when the program starts - if set to Normally Open (NO), the relay is off when you set the relay to HIGH
  attachInterrupt(digitalPinToInterrupt(button1.pin),action1,FALLING);
  attachInterrupt(digitalPinToInterrupt(button2.pin),action2,FALLING);
  attachInterrupt(digitalPinToInterrupt(button3.pin),action3,FALLING);
  attachInterrupt(digitalPinToInterrupt(button4.pin),action4,FALLING);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Start server
  server.begin();
}
  
void loop() {

}

Similar Posts