Questions with regards to ESP8266 Basic and hardware interfacing and control via Basic commands

Moderator: Mmiscool

User avatar
By Barnabybear
#53122 Hi, yes something like that. My first thoughts are that I would check the API for a sunset time when the blinds were opened (after all if there still closed they don't need closing) and then work this in with some other factors to get an earliest close time:
Is sunset before 10pm (10pm default close time even if sunset is later).
Sleep untill earlist close time - wake and check some other factors:
A daylight sensor attached to the window (if it's still bright have an option to stay open longer if sunset is before 10pm i.e still bright even though sunset is at 6:00pm - stay open for a bit longer & make the most of a good day).
A temperature sensor just outside the window (if it's cold outside an option to close to save energy i.e. if it's -3 deg C dark and raining just close the blinds now and save energy).
Then close the blinds or calculate a sleep time to check again.

Opening is easy as it mostly will be maunual or a set time.
User avatar
By forlotto
#53193 Excellent idea with fall coming in a couple of months adding temp to the equation makes since I would love to have a all black shade on the back side as well makes a difference in heating.

As of now I have black panel curtains black on one side white on the other I flip them around in the spring/summer to reflect light and flip them to black side in the winter this believe it or not on a cold day with some sun will throw off 120+ degrees of heat according to my IR thermometer very useful project for me I wanted to try been doing this for the last few years actually after hearing about jailboxes from an old timer which were black ceramic boxes they used to use for heat back in the days on the south side of your home these boxes would collect heat and through the day they would open a vent and pipe the hot air into the house I guess they worked very well from my understanding but is kind of a lost technology.

Energy efficient heating has always been a goal of mine would be interesting if someone could make a steam generator that burns wood generates electric and heats the home at the same time.
User avatar
By Barnabybear
#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;
  }
}