system
April 23, 2014, 12:35am
1
Hi. I am trying to make a sketch to monitor and manipulate my garage door. I am reusing a common webserver sketch as the basis of the project. I have most of the sketch done but there is one area that has stumped me to this point.
Depending on the placement of the garage door, the webserver can have two buttons, "Open Door" and "Close Door". When I press "Open Door" the URL in the web browser turns to "http://192.168.0.31/?b=1 ", when I click the "Close Door" button, the URL in the web browser turns to "http://192.168.0.31/?b=2 ". I want it to send a half second pulse to the garage door opener via a relay module.
The webserver is set to refresh itself every 5 seconds. After I click the "Open Door" button, the relay pulses every 5 seconds. I only want it to pulse once. I have tried several methods of "resetting" the form (see the "reset form FAILS!" section of the sketch in the next post). Is there a way to reset the form or clear the value of "b" in the URL? Is there a way to change the URL from "http://192.168.0.31/?b=1 " to "http://192.168.0.31/ " on each 5 second reset?
Thanks!
system
April 23, 2014, 12:38am
2
Oops, I missed the "9500 character limit". I will post the sketch in smaller parts.
system
April 23, 2014, 12:40am
3
Part 1 of 3
#include <Time.h>
#include <MemoryFree.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
// ethernet configuration
byte mac[] = {
0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
byte ip[] = {
192, 168, 0, 31 }; // ip in lan
byte gateway[] = {
192, 168, 0, 1 }; // internet access via router
byte subnet[] = {
255, 255, 255, 0 }; //subnet mask
EthernetServer server(80); // port 80 is default for HTTP
// constants
const int AutoDownEnablePin = 6; // enable autodown switch
const int DoorClosedPin = 7; // door open switch
const int DoorOpenPin = 8; // door closed switch
const int OpenCloseRelayPin1 = 9;
const int OpenCloseRelayPin2 = 5;
//const int LED = 9; // led is connected to digital pin 9
const int timeZone = -5; // Central Standard Time (USA)
// NTP Servers:
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov
// variables
boolean DoorOpenState;
boolean DoorClosedState;
int DoorPosition;
boolean RelayEnable1;
String TimeString;
long TempTime;
int SecondsOpen = 0;
int MinutesOpen;
boolean AutoDownSwitch;
boolean AutoDownEnable;
int AutoDownMinutes;
char c = 0; // received data
char command[2] = "\0"; // command
EthernetUDP Udp;
unsigned int localPort = 7777; // local port to listen for UDP packets
void setup()
{
// initialize serial communication:
Serial.begin(9600);
// initialize IOs
pinMode(AutoDownEnablePin, INPUT_PULLUP);
pinMode(DoorOpenPin, INPUT_PULLUP);
pinMode(DoorClosedPin, INPUT_PULLUP);
pinMode(OpenCloseRelayPin1, OUTPUT);
//pinMode(OpenCloseRelayPin2, OUTPUT);
//pinMode(LED, OUTPUT);
// initialize webserver
Ethernet.begin(mac, ip, gateway, gateway, subnet);
server.begin();
// initialize udp for time sync
Udp.begin(localPort);
setSyncProvider(getNtpTime);
}
time_t prevDisplay = 0; // when the digital clock was displayed
void loop()
{
updatetime();
switchstatus();
webserver();
goto skipit;
Serial.print(F("freeMemory()="));
Serial.println(freeMemory());
skipit:
;
}
void switchstatus()
{
// read the state of the pushbutton value:
DoorOpenState = digitalRead(DoorOpenPin);
DoorClosedState = digitalRead(DoorClosedPin);
// calculate door status
if (DoorClosedState == 1 && DoorOpenState == 0){
DoorPosition = 0;
} // door is open
if (DoorClosedState == 0 && DoorOpenState == 0){
DoorPosition = 1;
} // door is in middle position
if (DoorClosedState == 0 && DoorOpenState == 1){
DoorPosition = 2;
} // door is open
if (DoorClosedState == 1 && DoorOpenState == 1){
DoorPosition = 3;
} // ERROR unknown state
goto skipit;
//Print the results
Serial.print(F("Closed="));
Serial.print(DoorClosedState);
Serial.print(F(",Open="));
Serial.print(DoorOpenState);
Serial.print(F(",Door="));
Serial.print(DoorPosition);
Serial.println();
skipit:
;
}
system
April 23, 2014, 12:41am
4
Part 2 of 3
void webserver()
{
EthernetClient client = server.available();
// detect if current is the first line
boolean current_line_is_first = true;
if (client) {
// an http request ends with a blank line
boolean current_line_is_blank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if we've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so we can send a reply
if (c == '\n' && current_line_is_blank) {
// send a standard http response header
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/html"));
client.println();
// auto reload webpage every 5 second
client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=>"));
// background
//client.println(F("<body background=\"http://img256.imageshack.us/img256/5867/52577012.jpg\"</body>");
//webpage background color
client.println(F("<body bgcolor=silver>"));
// webpage title
client.println(F("<title>Garage Monitor</title>"));
// webpage heading
client.println(F("<center><font face='Verdana' color='black' size='8'>Garage Monitor</font></center>"));
client.println(F("
")); // line break
client.println(F("
"));
client.println(F("<hr>")); // horizontal line
client.println(F("
"));
client.println(F("
"));
// reset form FAILS!
//client.println(F("<script>"));
//client.println(F("<document.form.reset()>"));
//client.println(F("</script>"));
//client.println("<body onLoad=javascript:document.forms[0].reset()>");
//client.println(F("<input type=reset value=Reset Form>"));
//client.println(F("<form method=get name=form autocomplete=off>"));
//client.println(F("<body onload=document.form.reset();>"));
//client.println(F("<form autocomplete=off>"));
//client.println(F("<a href=javascript:document.form.reset();>reset</a>"));
//client.println(F("<script>document.form.reset()</script>"));
//client.println(F("<script type=text/javascript>"));
//client.println(F("document.getElementById('b').value ='';"));
//client.println(F("</script>"));
// button functions
client.println(F("<form method=get name=form>"));
if (DoorPosition == 0){
//The door is closed
//client.println(F("<hr><center><a href=http://www.URL.com>URL Link Text</a>
");
//"<button disabled name=b (to disable a button)
//font-size:36;color:grey (changes button font color)
client.println(F("<center><button name=b value=1 type=submit style=height:300px;width:600px;font-size:36;background-color:lightpink>Open Door</button></center>"));
}
if (DoorPosition == 1){
//The door is open
client.println(F("<center><button name=b value=1 type=submit style=height:300px;width:600px;font-size:36;background-color:lightpink>Open Door</button></center>"));
client.println(F("
"));
client.println(F("
"));
client.println(F("<center><button name=b value=2 type=submit style=height:300px;width:600px;font-size:36;background-color:lightgreen>Close Door</button></center>"));
}
if (DoorPosition == 2){
//The door is open
client.println(F("<center><button name=b value=1 type=submit style=height:300px;width:600px;font-size:36;background-color:lightgreen>Close Door</button></center>"));
}
client.println(F("</form>
"));
client.println(F("
"));
client.println(F("<hr>"));
// Status Panel
client.println(F("
"));
client.println(F("<center><font face='Verdana' color='black' size='8'>Status Panel</font></center>"));
client.println(F("
"));
client.println(F("<center><font face='Verdana' color='black' size='6'>"));
// display time
client.println(String(TimeString));
client.println(F("
"));
// display free memory
client.println("Free Memory: " + String(freeMemory()));
client.println(F("
"));
client.println(F("
"));
// door position
switch (DoorPosition){
case 0:
SecondsOpen = 0;
MinutesOpen = 0;
AutoDownEnable = 0;
client.println(F("Door Position: Closed"));
client.println(F("
"));
break;
case 1:
client.println(F("Door Position: Middle"));
client.println(F("
"));
break;
case 2:
if (SecondsOpen == 0){
TempTime = now();
}
MinutesOpen = SecondsOpen / 60;
client.println("Door Position: Open (" + String(MinutesOpen) + " Minutes)");
client.println(F("
"));
delay(1000);
SecondsOpen = now() - TempTime;
break;
case 3:
client.println(F("Door Position: ERROR!"));
client.println(F("
"));
break;
}
// door switch status
if (digitalRead(DoorClosedPin) == HIGH){
client.println(F("Door Closed Switch: High"));
}
else{
client.println(F("Door Closed Switch: Low"));
}
client.println(F("
"));
if (digitalRead(DoorOpenPin) == HIGH){
client.println(F("Door Open Switch: High"));
}
else{
client.println(F("Door Open Switch: Low"));
}
client.println(F("
"));
client.println(F("
"));
// autodown
AutoDownMinutes = 15; // 15 minute auto down
client.println("AutoDown Minutes: " + String(AutoDownMinutes));
client.println(F("
"));
AutoDownSwitch = digitalRead(AutoDownEnablePin);
if (AutoDownSwitch == HIGH){
client.println(F("AutoDown Enabled: True"));
}
else{
client.println(F("AutoDown Enabled: False"));
}
client.println(F("
"));
if ((DoorOpenState == 1 && AutoDownSwitch == HIGH && MinutesOpen >= AutoDownMinutes) || (AutoDownEnable == 1)){
AutoDownEnable = 1;
client.println(F("Close Door: True"));
}
else{
AutoDownEnable = 0;
client.println(F("Close Door: False"));
}
client.println(F("
"));
client.println(F("
"));
client.println(F("<hr>"));
client.println(F("</font></center>"));
break;
}
// read form value of "b"
if (c == '\n') {
// we're starting a new line
current_line_is_first = false;
current_line_is_blank = true;
}
else if (c != '\r') {
// we've gotten a character on the current line
current_line_is_blank = false;
}
// get the first http request
if (current_line_is_first && c == '=') {
for (int i = 0; i < 1; i++) {
c = client.read();
command[i] = c;
}
// Relay control
if (!strcmp(command, "1")){ // && RelayEnable1 == 1) {
// open door
digitalWrite(OpenCloseRelayPin1, HIGH); //LOW for relay module
delay(500);
digitalWrite(OpenCloseRelayPin1, LOW); //HIGH for relay module
//RelayEnable1 = 0;
}
else if (!strcmp(command, "2")) {
//close door
}
}
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}
system
April 23, 2014, 12:45am
5
Part 3 of 3
//***********************************NTP***********************************
void printDigits(int digits){
// utility for digital clock display: prints preceding colon and leading 0
if(digits < 10)
TimeString = TimeString + "0";
TimeString = TimeString + digits;
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
while (Udp.parsePacket() > 0) ; // discard any previously received packets
sendNTPpacket(timeServer);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println(F("No NTP Response :-("));
return 0; // return 0 if unable to get the time
}
void updatetime()
{
if (timeStatus() != timeNotSet){
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay = now();
digitalClockDisplay();
}
}
}
void digitalClockDisplay(){
// digital clock display of the time
TimeString = "";
printDigits(month());
TimeString = TimeString + "/";
printDigits(day());
TimeString = TimeString + "/";
printDigits(year());
TimeString = TimeString + " - ";
printDigits(hour());
TimeString = TimeString + ":";
printDigits(minute());
TimeString = TimeString + ":";
printDigits(second());
goto skipit;
Serial.print(TimeString);
Serial.println();
skipit:
;
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address){
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
Is there a way to change the URL from "http://192.168.0.31/?b=1 " to "http://192.168.0.31/ " on each 5 second reset?
Put a clickable link for "http://192.168.0.31/?b=1 " in the "http://192.168.0.31/ " refreshing page.
system
April 23, 2014, 1:38am
7
Thanks for the quick reply zoomkat!! I just tried clicking "http://192.168.0.31/?b=1 " in your post and it "pulses" on every 5 second refresh. I also tried...
client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=192.168.0.31>"));
and
client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=http://192.168.0.31/>"));
But it didn't change the behavior. I'm not sure I am doing what you suggested.
Web page with clickable links. Put a meta refresh line if needed.
//zoomkat 3-17-12
//simple button GET server code to control servo and arduino pin 5
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
#include <SPI.h>
#include <Ethernet.h>
//#include <Servo.h>
//Servo myservo; // create servo object to control a servo
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = {
192, 168, 1, 102 }; // ip in lan
byte gateway[] = {
192, 168, 1, 1 }; // internet access via router
byte subnet[] = {
255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
String readString;
//////////////////////
void setup(){
pinMode(5, OUTPUT); //pin selected to control
pinMode(6, OUTPUT); //pin selected to control
pinMode(7, OUTPUT); //pin selected to control
//start Ethernet
Ethernet.begin(mac, ip, gateway, gateway, subnet);
server.begin();
//enable serial data print
Serial.begin(9600);
Serial.println("server LED test 1.0"); // so I can keep track of what is loaded
}
void loop(){
// Create a client connection
EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
//Serial.print(c);
}
//if HTTP request has ended
if (c == '\n') {
///////////////
Serial.println(readString); //print to serial monitor for debuging
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println();
client.println("<HTML>");
client.println("<HEAD>");
client.println("<TITLE>Arduino GET test page</TITLE>");
client.println("</HEAD>");
client.println("<BODY>");
client.println("<H1>Zoomkat's simple Arduino button</H1>");
// DIY buttons
client.println("<a href=\"/?on1\"\">ON</a>");
client.println("<a href=\"/?off1\"\">OFF</a>
");
// mousedown buttons
client.println("
<input type=\"button\" value=\"ON\" onmousedown=\"location.href ('/?on2');\"/>");
client.println("<input type=\"button\" value=\"OFF\" onmousedown=\"location.href ('/?off2');\"/>");
// mousedown radio buttons
client.println("
<input type=\"radio\" value=\"ON\" onmousedown=\"location.href ('/?on3');\"\">ON</>");
client.println("<input type=\"radio\" value=\"OFF\" onmousedown=\"location.href ('/?off3');\"\">OFF</>");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
///////////////////// control arduino pin
if(readString.indexOf("on1") >0) {
digitalWrite(5, HIGH);
Serial.println("Led on1");
}
if(readString.indexOf("off1") >0) {
digitalWrite(5, LOW);
Serial.println("Led off1");
}
if(readString.indexOf("on2") >0) {
digitalWrite(6, HIGH);
Serial.println("Led on2");
}
if(readString.indexOf("off2") >0) {
digitalWrite(6, LOW);
Serial.println("Led off2");
}
if(readString.indexOf("on3") >0) {
digitalWrite(7, HIGH);
Serial.println("Led on3");
}
if(readString.indexOf("off3") >0) {
digitalWrite(7, LOW);
Serial.println("Led off3");
}
//clearing string for next read
readString="";
}
}
}
}
}
system
April 23, 2014, 3:30am
9
Crap...
I tried the meta refresh as one of the first attempts to fix it. Unfortunately Mr. Syntax kicked me in the under carriage. I forgot a ";" before "URL". I changed...
client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5 URL=http://192.168.0.31/>"));
to
client.println(F("<META HTTP-EQUIV=REFRESH CONTENT=5;URL=http://192.168.0.31/>"));
Now it's working pretty well. Thanks zoomkat!!