- Mon Aug 22, 2016 11:05 am
#53587
Hi, ok a little progress. Some code to perform the basic functions.
Manual open, manual close, remote open, remote close, inch open & inch close.
On the to do list:
3D print housing.
A must is to save the current state in flash to safegard against power fails.
Needs a warning for remote open / close that the opperation could not be completed as the blind was already in that state.
It would be good to be able to set the number of steps needed for open / close from a test run rather than a value in setup.
Insert API to check real time.
Insert API to check for sunset and auto close.
Possably some sensors.
Anyway here it is:
Code: Select all/*
/*
* STILL UNDER DEVELOPMENT - all thats here works 22/08/16.
*
* This sketch will drive a 28BYJ-48 stepper motor
* with ULN2003 to open & close a roller blind,
* or anything realy.
* The coils A,B,C & D are on GPIO's 12, 13, 14 & 15
* (with 4.7K pull down resistors) Edit - not needed,
* the ULN2003 has built in pull downs that work fine.
* GPIO's 0 & 2 are used as manual control,
* LOW active with 10K pull ups.
* GPIO 2 toggles the blind open & closed,
* dependant on it's current state.
* GPIO 0 will enter inch mode, the blind
* can be inched to a known open or closed
* postion with GPIO 2.
* After GPIO 0 first press - inch closed,
* after GPIO 0 second press - inch open,
* after GPIO 0 third press - exit inch mode.
* Remote access is via the following commands:
* http://server_ip/gpio/0 will open the blinds,
* http://server_ip/gpio/1 will close the blinds.
*
* 'open_length' sets the number of steps required
* to open or close the blind.
*/
#include <ESP8266WiFi.h>
const char* ssid = "<SSID>";
const char* password = "<PASSWORD>";
int coilA = 12;
int coilB = 13;
int coilC = 14;
int coilD = 15;
int manual_operate = 2;
int manual_inch = 0;
int step_number = 1;
int step_delay = 2000;
long open_length = 2000;
int flag_current = 0;
int flag_last = 1;
int flag_adjust = 0;
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(10);
// set outputs.
pinMode(coilA, OUTPUT);
pinMode(coilB, OUTPUT);
pinMode(coilC, OUTPUT);
pinMode(coilD, OUTPUT);
pinMode(manual_operate, INPUT);
pinMode(manual_inch, INPUT);
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
//WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.print("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// Check if a client has connected or
// manual opperation required.
// Check for remote request.
WiFiClient client = server.available();
if (!client) { // if no remote request check manual buttons.
delay(100);
// Check for GPIO 0 low - enter inch mode.
if (!digitalRead(manual_inch)) { // if GPIO 0 low.
manual_adjust(); // jump to void manual_adjust.
}
// Check for GPIO 2 low reverse blind postion.
// if open, close if closed, open.
if (!digitalRead(manual_operate)) { // if GPIO 2 low.
switch (flag_last) { // select dependant on blind currently open or closed.
case 1: // blind currently open.
close(); // jump to void close().
break;
case 2: // blind currently closed.
open(); // jump to void open().
break;
}
}
return;
}
// If remote request.
// Read the first line of the request.
String req = client.readStringUntil('\r');
Serial.println(req);
client.flush();
// Match the request
int val;
if (req.indexOf("/gpio/0") != -1)
flag_current = 1; // set flag to open blind.
else if (req.indexOf("/gpio/1") != -1)
flag_current = 2; // set flag to close blind.
else {
Serial.println("invalid request");
client.print("HTTP/1.1 404\r\n");
client.stop();
return;
}
client.flush();
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n";
switch (flag_current) { // select dependant on request.
case 1:
s += "Opening the blind";
break;
case 2:
s += "Closing the blind";
break;
}
s += "</html>\n";
// Send the response to the client
client.print(s);
delay(100);
Serial.println("Client disonnected");
switch (flag_current) { // select dependant on request.
case 1:
open(); // jump to void open().
break;
case 2:
close(); // jump to void close().
break;
}
}
//************ Manual adjust (inch mode)************
void manual_adjust() {
Serial.println("Enter inch mode");
flag_adjust = 2; // set flag to close.
delay(1000);
yield();
while (flag_adjust > 0) { // adjust flag set to open or close (1 or 2).
if (!digitalRead(manual_inch)) { // GPIO 0 low.
flag_adjust = flag_adjust - 1; // reduce flag by 1 (step through options).
if (flag_adjust < 0) { // check flag for negative value.
flag_adjust = 0; // set flag to 0 if negative.
}
delay(1000);
}
switch (flag_adjust) { // inch open or closed dependant on adjust flag (set above).
case 1: // open
while (!digitalRead(manual_operate)) { // if GPIO 2 low.
for (step_number = 1; step_number < 9; step_number++) {
output_write(); // move stepper one set of moves in open direction.
delayMicroseconds(step_delay);
yield();
}
}
case 2: // close
while (!digitalRead(manual_operate)) { // if GPIO 2 low.
for (step_number = 8; step_number > 0; step_number--) {
output_write(); // move stepper one set of moves in closed direction.
delayMicroseconds(step_delay);
yield();
}
}
yield();
}
}
// adjust flag is 0, turn off outputs & drop out of loop.
Serial.println("Exit inch mode, outputs off");
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
}
//************ Open Loop ************
void open() {
if (flag_last == 0 || flag_last == 2) { // check for power up or blind closed.
Serial.println("opening blind");
for (long dist_loop = 0; dist_loop < open_length; dist_loop++) { // number of steps to open blind.
++step_number;
if (step_number > 8) step_number = 1;
output_write(); // jump to void output write().
delayMicroseconds(step_delay);
yield();
}
// final write to turn all outputs off.
Serial.println("move complete, outputs off");
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
flag_current = 0; // set current move flag to 0 = none.
flag_last = 1; // set current postion flag to 1 = open.
}
}
//************ Close Loop ************
void close() {
if (flag_last == 0 || flag_last == 1) { // check for power up or blind open.
Serial.println("closing blind");
for (long dist_loop = 0; dist_loop < open_length; dist_loop++) { // number of steps to close blind.
--step_number;
if (step_number < 1) step_number = 8;
output_write(); // jump to void output write().
delayMicroseconds(step_delay);
yield();
}
// final write to turn all outputs off.
Serial.println("move complete, outputs off");
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
flag_current = 0; // set current move flag to 0 = none.
flag_last = 2; // set current postion flag to 2 = closed.
}
}
//************ Output write ************
void output_write() {
switch (step_number) {
case 1:
digitalWrite(coilA, HIGH);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
break;
case 2:
digitalWrite(coilA, HIGH);
digitalWrite(coilB, HIGH);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
break;
case 3:
digitalWrite(coilA, LOW);
digitalWrite(coilB, HIGH);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
break;
case 4:
digitalWrite(coilA, LOW);
digitalWrite(coilB, HIGH);
digitalWrite(coilC, HIGH);
digitalWrite(coilD, LOW);
break;
case 5:
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, HIGH);
digitalWrite(coilD, LOW);
break;
case 6:
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, HIGH);
digitalWrite(coilD, HIGH);
break;
case 7:
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, HIGH);
break;
case 8:
digitalWrite(coilA, HIGH);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, HIGH);
break;
default:
digitalWrite(coilA, LOW);
digitalWrite(coilB, LOW);
digitalWrite(coilC, LOW);
digitalWrite(coilD, LOW);
break;
}
}