How to control eight relays with web server using esp 8266

Hello friends.
This code is for esp control through web server. Currently, you can only turn on and off the ESP led. I want to change this code so that eight relays can be controlled with it. These are the GPIOs that I want to be controlled
GPIO 5 / GPIO 4 / GPIO 0 / GPIO 2 / GPIO 15 / GPIO 16 / GPIO 14 / GPIO 12 / GPIO 13
Thank you for your guidance.

/* ***********************************************************************************************
 * 
 * oldcurmudgeon November 6 2021
 * 
 * This sketch is for an ESP8266 to provide a web interface for blinking an LED
 *
 * The onboard LED is used so no additional hardware is needed
 *
 * It is implemented as 2 state machines. The first has the state defined by the pattern
 * being run. The state is defined by currentPattern. The state transition is done via 
 * a browser request changing newState to define the next state.
 *
 * The second state machine defines the step in the pattern of blinks. The state transition
 * occurs when the current time for the LED state expires. When the time is up the LED toggles
 * to the other state and the time for that state starts. At the end of the pattern it is
 * started over from the beginning. 
 * 
 *************************************************************************************************/ 


#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const char* ssid = "SRV-TSC";
const char* password = "12345678";

ESP8266WebServer server(80);

#include <string.h>
#include <Streaming.h>   //  from "Streaming by Mikal Hart" in library manager

// Pattern selection state machine variables
volatile uint16_t newPattern = 0;  //default to first pattern volatile because it is set asynchronously
uint16_t currentPattern = 0; // default first pattern

// Pattern step state machine variables
byte step = 0;                // current step in pattern default to start
unsigned long currentTime;   // current time for test
unsigned long startTime;     // start time of this step

// led on state - the onboard led is active low (when the pin is low the led
// is on). If you are using some other pin to drive the led so that the led is on when
// the pin is high this should be changed to one.
const byte LED_ON = 0; 
byte ledState = LED_ON;     // current led state default on

// led patterns - this is a series of numbers defining the led on and off times
// This example is 4 patterns of 6 changes. A zero before the end of the pattern
// indicates a short pattern that restarts when it detects a zero.
const byte NUM_PATTERNS = 4;    // number of patterns 
const byte PATTERN_LEN = 6;    // pattern length
const unsigned long pattern[ NUM_PATTERNS][PATTERN_LEN] = 
        {{200,200,200,200,200,200},
        {1500,1500,1500,1500,1500,01500},
        {1500,1500,200,200,0,0},           // short pattern example 
        {1500,1500,1500,1500,200,200}};
/* ***************************************************************************
*
* Handle root web page
*
******************************************************************************/
void handleRoot() {
  if (server.hasArg("pattern")){ // the browser has sent a response
    // Save new value from web page browser response  
    newPattern = server.arg("pattern").toInt();
  }
   /* Build html page
    * 
    * The new lines (\n) are not required by the browser - they are formatting for a human 
    * looking at the page source on the browser
    * 
    * The "String((newPattern == x) ? " checked" : " ")"  construct is used to set the
    * pattern selected as checked when the web page is refreshed. If newPage is equal to
    * the value "checked" is added to the attributes, otherwise a blank is added. You can
    * see the result on the web page by right-click then select "View Page Source".
    * This will show the actual HTML sent to the browser.
   */ 
  String htmlPage =
    String("<!DOCTYPE HTML>\n") 
    + "<html lang='en'>\n"
    + "<head>\n"
    + "<!-- Ignore request for nonexistent favicon -->\n"
    + "<link rel='icon' href='data:,'>\n"
    + " <meta name='viewport' content='width=device-width, initial-scale=1.0'>"
    +"</head>\n"
    + "<body>\n\n"
    + "<h1 style='text-align: center;'>LED Pattern Blinker</h1>\n"
    + "<div>\n"
    + "<form style='font-size: 20px'>\n"
    +   " <input type='radio' name='pattern' value='0' required"
    +  String((newPattern == 0) ? " checked" : " ")        
    +   " > Short blink<br>\n"
    +   " <input type='radio' name='pattern' value='1' required"
    +  String((newPattern == 1) ? " checked" : " ") 
    +   "> Long blink<br>\n"
    +   " <input type='radio' name='pattern' value='2' required"
    +  String((newPattern == 2) ? " checked" : " ") 
    +   "> Long Short blink <br>\n"
    +   " <input type='radio' name='pattern' value='3' required"
    +  String((newPattern == 3) ? " checked" : " ") 
    +   "> Long Long Short blink<br>\n"
    +   "<input type='submit' value='Set Pattern'>\n"
    +   "</div>\n"
    +"</body>\n</html>\n";

  server.send(200, "text/html",htmlPage);
    
}

void handleNotFound() {
    // no clue what they sent
    String message = "File Not Found\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET) ? "GET" : "POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";

    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }

    server.send(404, "text/plain", message);

}

void setup() {
  pinMode(LED_BUILTIN,OUTPUT);

  Serial.begin(19200);
   

  // Set up WiFi network
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Set up mDNS responder:
  // - first argument is the domain name, in this example
  //   the fully-qualified domain name is "esp8266.local"
  // - second argument is the IP address to advertise
  //   we send our IP address on the WiFi network
  if (!MDNS.begin("esp8266")) {
    Serial.println("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");

  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  
  // Start the server
  server.begin();
  Serial.println("TCP server started");

  // Add service to MDNS-SD
  MDNS.addService("http", "tcp", 80);
  
  startTime = millis();      // get current time for start of pattern
}

void checkPattern() {
    if (newPattern != currentPattern){     // browser has sent a new pattern
        // switch to new pattern
        ledState = LED_ON;  // start with led on
        digitalWrite(LED_BUILTIN,ledState);  // start with led on
        step = 0;   // start at beginning of pattern
        currentPattern = newPattern;  // switch to new pattern
        startTime = millis();      // get current time for start of pattern
    } 
};    

void loop() {
    
  MDNS.update();
     
  server.handleClient();      // check for connection request
  
  // Check to see if there is a new pattern request. If the check is done here
  // the new pattern starts immediately. If you want the new pattern to start 
  // after the current pattern has completed, comment out the line below and uncomment
  // the one in the end of pattern processing
  checkPattern();
  
  currentTime = millis();      // get current time for compare
  if (currentTime  - startTime > pattern[currentPattern][step]) {
     // done with this step 
     ledState ^= 1;  // toggle led state
     digitalWrite(LED_BUILTIN,ledState);  // change led state       
     step++;             // next step
     startTime = currentTime;  // start next led pattern step time
     if ((step >= PATTERN_LEN)                    // end of pattern
         || (pattern[currentPattern][step]==0)){  // or short pattern
        // end of pattern processing     
        step = 0;   //restart pattern
        
        // Check to see if there is a new pattern request. If the check 
        // is done here the new pattern starts after the current pattern
        // has completed. (Remember to comment out the call above.)
       // checkPattern();        
     }
  }     
}

are you sure there are enough GPIOs available on the ESP8266? The ESP8266 Pinout Reference suggests there are only 7 that can be used as OUTPUTs

an MCP23017 provides 16 additional I/Os and can easily be connected to an esp32 and i assume esp8266 thru 2 pins and a couple pullup resistors.

1 Like

If you draw a schematic you will see that you ran out of pins. Posting an annotated schematic always helps us and you. I find most of my mistooks at the schematic stage.

This is my circuit schematic

Although the problem is not related to the schematic. I am weak in html coding. I just want to turn this base off and on by web server. I want you to guide me in coding it. I want the on and off button to be in the form of a switch. Thankful

lotta wants

look at one of these links -- esp32 using html server to control output to control a single relay then expand it to control 8 (if the hardware is capable)

Per "gcjr" that is all you have to do, however if you do not have the GPIOs available you can use an I2C port expander such as PCA9555 which will give you 15 outputs that can sink or source about 50mA, just be careful of the chips maximum capacity, I would not expect it to be the sum of all of the outputs. There are others such as the PCF8574 and other 8 bit expanders.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.