#include <Bounce2.h>
#include <Relay.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
/* use for non-NodeMCU boards, modifying as needed to translate GPIO pins to constants
const int D0 = 16; // User / Wake
const int D1 = 5;
const int D2 = 4;
const int D3 = 0; // Flash
const int D4 = 2; // TXD1 - on-board led
const int D5 = 14; // HSCLK
const int D6 = 12; // HMISO
const int D7 = 13; // RXD2 / HMOSI
const int D8 = 15; // TXD2 / HCS
const int D9 = 3; // RXD0
const int D10 = 1; // TXD0
const int SD2 = 9; // SDD2
const int SD3 = 10; // SDD3
*/
const char* ssid = "MYSSID";
const char* password = "MYWPAPASSWORD";
MDNSResponder mdns;
ESP8266WebServer server ( 80 );
const int led = D4;
int bPin[] = {D0,D1,D2,D3};
Bounce bounce[] = { Bounce(), Bounce(), Bounce(), Bounce() };
Relay relay[] = {
Relay(D5, LOW),
Relay(D6, LOW),
Relay(D7, LOW),
Relay(D8, LOW),
};
void setupButtons() {
Serial.println("initializing buttons...");
// set up the buttons with internal pull-up
pinMode(bPin[0], INPUT_PULLUP);
pinMode(bPin[1], INPUT_PULLUP);
pinMode(bPin[2], INPUT_PULLUP);
pinMode(bPin[3], INPUT_PULLUP);
Serial.println("attaching buttons to debouncers...");
bounce[0].attach(bPin[0]);
bounce[1].attach(bPin[1]);
bounce[2].attach(bPin[2]);
bounce[3].attach(bPin[3]);
}
void setupRelays() {
Serial.println("initializing relays...");
relay[0].off();
relay[1].off();
relay[2].off();
relay[3].off();
}
void wifiConnect() {
Serial.print("Connecting to wifi: ");
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 setupServer() {
if (mdns.begin("EsPiPower", WiFi.localIP())) {
Serial.println("MDNS responder started");
}
server.on ( "/", handleRoot );
server.on ( "/toggle", handleToggle );
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void setup() {
Serial.begin(115200);
delay(2500);
setupButtons();
delay(500);
setupRelays();
delay(500);
wifiConnect();
delay(500);
setupServer();
delay(500);
}
void loop() {
server.handleClient();
readButtons();
delay(10);
}
/**
* scan buttons for presses
*/
void readButtons() {
// update and read button Bounce instances
for(uint8_t i = 0; i<4; i++) {
if(bounce[i].update()) {
if(bounce[i].read() == LOW) {
toggle(i);
}
}
}
}
/**
* toggle relay state
*/
void toggle(int r) {
if((r >= 0) && (r <= 3)) {
Serial.print("Button ");
Serial.print(r+1);
Serial.print(" state ");
Serial.print(relay[r].state());
relay[r].toggle();
Serial.print(" switch to ");
Serial.print(relay[r].state());
Serial.print(" (");
if (relay[r].isRelayOn()) Serial.print("on");
if (relay[r].isRelayOff()) Serial.print("off");
Serial.println(")");
} else {
Serial.print("relay value '");
Serial.print(r);
Serial.println(" out of range!");
}
}
void handleToggle() {
digitalWrite ( led, 1 );
int r = -1;
for ( uint8_t i = 0; i < server.args(); i++ ) {
if(server.argName(i) == "r") {
r = server.arg(i).toInt();
}
}
toggle(r);
/* server.send ( 200, "text/html", "<html><head><meta http-equiv=\"refresh\" content=\"0;URL='/'\" /></head></html>" ); */
handleRoot();
digitalWrite ( led, 0 );
}
void handleRoot() {
digitalWrite ( led, 1 );
String html =
"<html>\
<head>\
<meta http-equiv='refresh' content=\"5;URL='/'\"/>\
<title>ESP8266 Pi Power Control</title>\
</head>\
<body>\
<h1>Status:</h1>\
<table>";
for(uint8_t i = 0; i<4; i++) {
html += getRelayHTML(i);
}
html +=
" <table>\
</body>\
</html>";
server.send ( 200, "text/html", html );
digitalWrite ( led, 0 );
}
String getRelayHTML(int r) {
String row = "<tr><th>Pi ";
row += r;
row += "</th><td><a href=\"/toggle?r=";
row += r;
row += "\">";
row += (relay[r].state() == 0) ? "On" : "Off";
row += "</a></td></tr>\n";
return row;
}
void handleNotFound() {
digitalWrite ( led, 1 );
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 );
digitalWrite ( led, 0 );
}
The relay code is the Seeeduino relay library by Steven Cogswell
https://github.com/scogswell/ArduinoSeeeduinoRelay
I modified it for my purposes to change the default state of the relays and it seemed to be switching my shield in reverse. (so namely my changes were customizing RELAY#PIN values to make it easier to access the relays by number rather than by pin and changing all sets from HIGH to LOW or LOW to HIGH)
modified Relay/Relay.h
/*******************************************************************************
* relay, a very simple class to control the relays on a Seeedunio Relay board
* Copyright (C) 2011 Steven Cogswell
*
* Version 20110712A
*
* Version History:
* July 11, 2011: Initial version
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
***********************************************************************************/
// Hardware note:
// Note the relay shield needs the 9V power supply on the board hooked up in order to
// actually be able to fire the relays. This 9V on the sheild does not power the UNO board.
// If you power the Arduino board from it's power connector, then the shield is powered
// that way, so you don't need two power connectors. i.e. - you can't run the relays
// with just USB power.
//
// Although this library was written with the Seeedstudio relay shield in mind, it will
// work perfectly line with generic relays. Just change the "RELAYxPIN" definitions below.
//
// Shield details:
// http://www.seeedstudio.com/depot/relay-shield-p-693.html?cPath=132_134
// http://garden.seeedstudio.com/index.php?title=Relay_Shield
//
// Software Note: Seeeduino has THREE e's, not two as you might think. Check that
// first when trying to find unresolved references.
//
#ifndef RELAY_H
#define RELAY_H
// Compatibility with the Arduino 1.0 library standard
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// Class Definition.
class Relay
{
public:
Relay(int rPin, int state); // Constructor
void on(); // Turns relay on
void off(); // Turns relay off
void toggle(); // Toggles state of relay between on and off
int state(); // returns state of relay (LOW/0/off or HIGH/1/on)
int isRelayOn(); // Returns TRUE if the relay is on , false otherwise
int isRelayOff(); // Returns TRUE if the relay is off, false otherwise
private:
int relayState; // Variables holds on/off state of the relay
int relayPin; // Variable holds which Arduino pin connected to relay.
};
#endif // RELAY_H
modified Relay/Relay.cpp:
/*******************************************************************************
* rELAY, a very simple class to control the relays on a Seeedunio Relay board
* Copyright (C) 2011 Steven Cogswell
*
* See SeeduinoRelay.h for version history
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
***********************************************************************************/
// Compatibility with the Arduino 1.0 library standard
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Relay.h"
//
// The constructor sets up a single relay, specified by relayPin
// Which is relay 1,2,3 or 4 as specified on the Seeeduino Relay board
// "state" is the initial state (LOW or HIGH)
//
// Relay Truth Table:
// State NOx NCx
// LOW open closed
// HIGH closed open
//
// The constructor will also properly set the assigned pin to OUTPUT.
//
Relay::Relay(int rPin, int state)
{
relayPin = rPin;
pinMode(relayPin, OUTPUT);
if (state == LOW) {
relayState=LOW;
on();
}
else {
relayState=HIGH;
off();
}
}
// Turns the relay on.
void Relay::on()
{
digitalWrite(relayPin, LOW);
relayState=LOW;
}
// Turns the relay off.
void Relay::off()
{
digitalWrite(relayPin, HIGH);
relayState=HIGH;
}
//Toggles the state of the relay
void Relay::toggle()
{
if (relayState==HIGH) {
on();
}
else {
off();
}
}
// Returns the state of the relay (LOW/0 or HIGH/1)
int Relay::state()
{
return(relayState);
}
// If the relay is on, returns true, otherwise returns false
int Relay::isRelayOn()
{
if (relayState==LOW)
return true;
else
return false;
}
// If the relay is off, returns true, otherwise returns false
int Relay::isRelayOff()
{
if (relayState==HIGH)
return true;
else
return false;
}
The remaining libraries should be available either from the standard arduino repositories or the ESP8266 arduino code.