It used more time and money than I originally anticipated, but here is the current setup:
Hardware:
For opening the house main door I’ll use ESPhome with a Wemos D1 R2 and a 3.3V relay from Aliexpress.
For opening and closing the nesting area sliding door I use an Arduino Uno WiFi triggered by MQTT-messages from homeassistant. The sliding door is built with 3d-Printer hardware (V-Slot profile and a flat piece of wood as door with a matching gantry (1set 3D Drucker teile Openbuilds V gantry plat set spezielle rutsche platte pulley für 2020 /2040 V slot aluminium profile räder|3D Printer Parts & Accessories| - AliExpress)
Here is the Arduino sketch:
#include <Arduino.h>
#include <PubSubClient.h>
#include <WiFiNINA.h>
char *SSID = "IoT";
char *SSID_PW = "XXX";
const char *MQTT_SERVER = "homeassistant.local";
const char *clientId = "huehnerstall_legenest";
const char *USER_NAME = "mqtt_huehnerstall";
const char *PW = "XXX";
const char *SUBSCRIBTION_CHANNEL = "/huehnerhaus/legenest";
const int STATE_OPEN = 1;
const int STATE_CLOSED = 2;
const int STATE_MOVING = 3;
const int COMMAND_OPEN = 1;
const int COMMAND_CLOSE = 2;
const int COMMAND_STOP = 3;
const int COMMAND_MOVE = 4;
const int COMMAND_GET_STATE = 5;
const int PIN_DOOR_CLOSED_SWITCH = 8;
const int PIN_DOOR_OPEN_SWITCH = 7;
const int PIN_PULSE = 3;
const int PIN_DIRECTION = 4;
const int PIN_ENABLE = 5;
const long MAX_DURATION = 7 * 1000;
const int MOVE_DELAY = 700;
const int DIRECTION_CLOSING = HIGH;
const int DIRECTION_OPENING = LOW;
const int STEPS_PER_REVOLUTION = 200;
char cState[1];
WiFiClient arduinoClient;
PubSubClient client(arduinoClient);
void setup_wifi()
{
delay(100);
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(SSID);
WiFi.begin(SSID, SSID_PW);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
//Serial.println("IP address: " + WiFi.localIP());
}
//Umgekehrte Logik, damit interne Pullup-Resistoren verwendet werden können
int get_state()
{
if (digitalRead(PIN_DOOR_CLOSED_SWITCH) == LOW)
{
Serial.println("Door closed");
return STATE_CLOSED;
}
else if (digitalRead(PIN_DOOR_OPEN_SWITCH) == LOW)
{
Serial.println("Door open");
return STATE_OPEN;
}
else
{
Serial.println("Door moving...");
return STATE_MOVING;
}
}
void stop()
{
// digitalWrite(PIN_PULSE, LOW);
// digitalWrite(PIN_DIRECTION, LOW);
// digitalWrite(PIN_ENABLE, LOW);
digitalWrite(PIN_ENABLE, HIGH);
}
void start()
{
digitalWrite(PIN_ENABLE, LOW);
}
void open_door()
{
Serial.println("Opening reached...");
stop();
if (get_state() == STATE_OPEN)
{
return;
}
else
{
Serial.println("Opening door...");
//Darf maximal 7 Sekunden dauern, ansonsten von selber stoppen
long lStart = millis();
start();
digitalWrite(PIN_DIRECTION, DIRECTION_OPENING);
while (get_state() != STATE_OPEN)
// int x = 0;
// while (x < 500)
{
//x++;
digitalWrite(PIN_PULSE, HIGH);
delayMicroseconds(MOVE_DELAY);
digitalWrite(PIN_PULSE, LOW);
delayMicroseconds(MOVE_DELAY);
long lCurrent = millis();
if (lCurrent - lStart >= MAX_DURATION)
{
Serial.println("Door opening takes too long => stop");
return;
}
}
}
}
void close_door()
{
stop();
if (get_state() == STATE_OPEN)
{
return;
}
else
{
long lStart = millis();
start();
digitalWrite(PIN_DIRECTION, DIRECTION_CLOSING);
while (get_state() != STATE_CLOSED)
{
digitalWrite(PIN_PULSE, HIGH);
delayMicroseconds(MOVE_DELAY);
digitalWrite(PIN_PULSE, LOW);
delayMicroseconds(MOVE_DELAY);
long lCurrent = millis();
if (lCurrent - lStart >= MAX_DURATION)
{
Serial.println("Door closing takes too long => stop");
return;
}
}
}
}
void move()
{
start();
if (get_state() == STATE_CLOSED)
{
digitalWrite(PIN_DIRECTION, DIRECTION_OPENING);
}
else if (get_state() == STATE_OPEN)
{
digitalWrite(PIN_DIRECTION, DIRECTION_CLOSING);
}
else
{
Serial.println("Invalid state for this operation. Door must be open or closed in order to test.");
return;
}
for (int i = 0; i < 5 * STEPS_PER_REVOLUTION; i++)
{
digitalWrite(PIN_PULSE, HIGH);
delayMicroseconds(MOVE_DELAY * 4);
digitalWrite(PIN_PULSE, LOW);
delayMicroseconds(MOVE_DELAY * 4);
}
digitalWrite(PIN_DIRECTION, !digitalRead(PIN_DIRECTION));
for (int i = 0; i < 5 * STEPS_PER_REVOLUTION; i++)
{
digitalWrite(PIN_PULSE, HIGH);
delayMicroseconds(MOVE_DELAY * 4);
digitalWrite(PIN_PULSE, LOW);
delayMicroseconds(MOVE_DELAY * 4);
}
}
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.println(payload[0]);
Serial.print("Command from MQTT broker is: [");
Serial.print(topic);
Serial.print(": ");
int iPayload = (char)payload[0] - '0';
Serial.println(iPayload);
Serial.print("]");
switch (iPayload)
{
case COMMAND_OPEN:
open_door();
break;
case COMMAND_CLOSE:
close_door();
break;
case COMMAND_MOVE:
move();
break;
case COMMAND_STOP:
stop();
break;
case COMMAND_GET_STATE:
break;
}
int iState = get_state();
Serial.println(iState);
String sState = String(iState);
sState.toCharArray(cState, sState.length() + 1);
client.publish("/huehnerhaus/legenest/status", cState, true);
}
void reconnect()
{
// Loop until we're reconnected
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(clientId, USER_NAME, PW))
{
Serial.println("connected");
//once connected to MQTT broker, subscribe command if any
client.subscribe(SUBSCRIBTION_CHANNEL);
}
else
{
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 6 seconds before retrying
delay(6000);
}
}
}
void setup()
{
Serial.begin(9600);
Serial.println("Starting up...");
pinMode(PIN_DOOR_CLOSED_SWITCH, INPUT_PULLUP);
pinMode(PIN_DOOR_OPEN_SWITCH, INPUT_PULLUP);
pinMode(PIN_PULSE, OUTPUT);
pinMode(PIN_DIRECTION, OUTPUT);
pinMode(PIN_ENABLE, OUTPUT);
//Serial.begin(9600); //115200
setup_wifi();
client.setServer(MQTT_SERVER, 1883);
client.setCallback(callback);
}
void loop()
{
if (!client.connected())
{
reconnect();
}
client.loop();
}
Currently I am waiting for the electrical installation material to arrive. I’ll post some pictures once I can start installing everything.