-->
Page 1 of 1

Stepper Motor controlled via ESP and Homebridge

PostPosted: Sun Feb 23, 2020 2:42 pm
by idna001
Hello,

I am new here, and it would be nice, if somenone can help me in my current Project.
I want to drive a stepper motor remote with an an ESP.
And I wnat to controll it via Homebridge over my raspi.

So first I am unsure if that works with the Hardware I have already:
An ESP8266, an DRV8825 stepper driver and a NEMA 17 stepper motor, a raspi with homebridge already installed (used for steering lights)


A software used in electric shutters or from a height adjustable desk should be similar to my project, or?

But I haven´t found anything so far...

Has anybody solved a similar task?
Or have some hints for my project?


Thanks in advance
idna

Re: Stepper Motor controlled via ESP and Homebridge

PostPosted: Mon Feb 24, 2020 11:06 am
by Barnabybear
Hi, I use this to control roller blinds on my house windows. It’s not quite what you want but it might give you some ideas.

Code: Select all/*
 *  STILL UNDER DEVELOPMENT - mostly works 23/08/16.
 *  V1.0
 *
 *  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.
 *  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 postion
 *  postion with GPIO 2 & then stored as open.
 *  After GPIO 0 first press - inch closed,
 *  after GPIO 0 second press - inch open,
 *  after GPIO 0 third press - exit inch mode &
 *  store in EEPROM as open.
 *  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>
#include <EEPROM.h>

const char* ssid = "<access point name>";
const char* password = "<accesspoint 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 = 35000;
int flag_current = 0;
byte 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.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
 
  EEPROM.begin(1);
  Serial.println("EEPROM value is ");
  Serial.println(EEPROM.read(0));
  Serial.println("flag_last is ");
  Serial.println(flag_last);
}

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.
      flag_last = EEPROM.read(0);
      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("/blind/open") != -1)
    flag_current = 1; // set flag to open blind.
  else if (req.indexOf("/blind/close") != -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 += "The blind is open";
      break;

    case 2:
      s += "The blind is closed";
      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:
    flag_last = EEPROM.read(0);
      open(); // jump to void open().
      break;

    case 2:
    flag_last = EEPROM.read(0);
      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);
  EEPROM.write(0, 1);  // blind in open postion
  EEPROM.commit();
  Serial.println("EEPROM value is ");
  Serial.println(EEPROM.read(0));   
  Serial.println("flag_last is ");
  Serial.println(flag_last);
}

//************ 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.
    EEPROM.write(0, 1); // set current / last postion flag to 1 = open.
    EEPROM.commit();
  }
}
//************ 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.
    EEPROM.write(0, 2);  // set current / last postion flag to 2 = closed.
    EEPROM.commit();
  }
}

//************ 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;
  }
}

Re: Stepper Motor controlled via ESP and Homebridge

PostPosted: Mon Feb 24, 2020 12:36 pm
by idna001
Thanks for the Sketch!
It seems to be similar to what I have in mind....
I have a few Questions about that:
Do you have wiring diagram?
How do you control it? Just by switches and not from Homebridge?

Thanks for help
idna