Simple httpd relay (power) controller
Posted: Fri Jul 22, 2016 12:26 pm
Another project I have been working on is using a 4 relay shield to control the main power for my Raspberry Pis using a nodeMcu. I thought I would throw the code out in case anyone might find it useful. I intend at some point to recycle this code to do it with 110v relays to create an AC power strip using the same concept(s).
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
modified Relay/Relay.cpp:
The remaining libraries should be available either from the standard arduino repositories or the ESP8266 arduino code.
Code: Select all
#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
Code: Select all
/*******************************************************************************
* 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:
Code: Select all
/*******************************************************************************
* 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.