controlling blinds with mqtt and send some sensor datas
Posted: Tue Jul 21, 2020 12:15 pm
Hı,
I was working on that for some time. As a newbie it was very hard for me. I am posting my code here for others to use. And if someone can optimize it i will be glad.
- It get step no from mqtt for blinds.
- Send temperatur humidity and lux values. Lux value is used in home assitant to automate,
- It has a reset sensor it step is lost.
- Write last step to EEPROM
I was working on that for some time. As a newbie it was very hard for me. I am posting my code here for others to use. And if someone can optimize it i will be glad.
- It get step no from mqtt for blinds.
- Send temperatur humidity and lux values. Lux value is used in home assitant to automate,
- It has a reset sensor it step is lost.
- Write last step to EEPROM
Code: Select all
// This code is for controlling blinds via MQTT, getting lux value (to automate blinds with home assistant), getting temp and humidity and reset with a sensor of your choice. Also record last value to EEPROM.
// Platform used is esp8266
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <AccelStepper.h>
#include <ESP_EEPROM.h>
#include <DHT.h>
#define Motor1_Dir 5
#define Motor1_Step 4
#define Motor1_En 15
#define DHTPIN 14
#define DHTTYPE DHT11
#define hall 12 // reset sensor
const char* ssid = "xxx";
const char* password = "xxx";
const char* mqtt_server = "xxx";
const char* mqttUser = "xxx";
const char* mqttPassword = "xxx";
int rec_value; // recieved value from mqtt
int eep_value; // value to write EEPROM
int hall_value; // for sensor reset
bool flag1; // to prevent unnecessary loop
bool flag_res; // for reset loop
DHT dht(DHTPIN, DHTTYPE);
AccelStepper stepper(1, Motor1_Step, Motor1_Dir);
WiFiClient espClient;
PubSubClient client(espClient);
// to connect wifi
void setup_wifi()
{
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// to recieve values from mqtt
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
rec_value = 0;
int tensValue = 1;
for (int i = length - 1; i >=0; i--) // iterate backwards
{
rec_value += (payload[i] - '0') * tensValue ;
tensValue = tensValue * 10;
}
flag1 = true; // to use in if fonction in loop
}
void reconnect()
{
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
if (client.connect("alkan")) // mqtt user
{
Serial.println("connected");
client.subscribe("Alkan/perde"); // mqtt subject to subscribe
}
else
{
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 3 seconds");
delay(3000);
}
}
}
void setup()
{
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
dht.begin();
pinMode(hall, INPUT);
hall_value = digitalRead(hall); // for reset
flag_res = false; // for reset
pinMode (Motor1_En, OUTPUT); // for disable motor to prevent heating
digitalWrite(Motor1_En, HIGH); // for disable motor to prevent heating
EEPROM.begin(512);
stepper.setMaxSpeed(200);
stepper.setAcceleration(100);
eep_value = int (EEPROM.read(0)); // get last saved value from EEPROM
rec_value = eep_value * 25; // convert to orjinal value. its divided to 25 below
stepper.setCurrentPosition(rec_value);
Serial.print(rec_value);
Serial.println();
}
void loop()
{
if (!client.connected())
{
reconnect();
}
client.loop();
{
if( flag1 == true and rec_value < 3001 ) // go for the recieved value value is between 0 - 3000
{
digitalWrite(Motor1_En, LOW);
stepper.moveTo(rec_value);
stepper.run();
Serial.print(stepper.currentPosition());
Serial.println();
}
if( flag1 == true and rec_value == 4000 and hall_value == 1 ) // if value 4000 it means reset. it go stupidly up until sensor activate below
{
digitalWrite(Motor1_En, LOW);
stepper.moveTo(-3500);
stepper.run();
Serial.println("Reseting");
hall_value = digitalRead(hall);
}
if (hall_value == 0 and flag_res == false ) // yes sensor activated. no need for analog value. digital is good for that. the sensor is up than my "0" point.
{
stepper.stop();
stepper.setCurrentPosition(-250);
flag_res = true;
}
if (flag_res == true) // so lets go to "0" after sensor read
{
stepper.moveTo(0);
stepper.run();
Serial.print(stepper.currentPosition());
Serial.println();
}
if( flag_res == true and stepper.currentPosition() == 0 ) // when we reach "0" then it s time to stop and finish reset process
{
stepper.stop();
flag_res = false;
flag1 = false;
hall_value = digitalRead(hall);
rec_value = 0;
EEPROM.put(0, 0); // save new position to EEPROM
EEPROM.commit();
Serial.println("Reset Completed");
digitalWrite(Motor1_En, HIGH);
}
if( flag1 == true and stepper.currentPosition() == rec_value ) // in normal case when blinds reach desired position write that to EEPROM and disable motor
{
flag1 = false;
eep_value = rec_value / 25;
EEPROM.put(0, eep_value);
EEPROM.commit();
Serial.println("Stop");
digitalWrite(Motor1_En, HIGH);
}
if( flag1 == false) // if not blinds moving we are getting temp, humidity, lux values
{
float temp = dht.readTemperature();
float humi = dht.readHumidity();
float isik = analogRead(A0);
float dist = digitalRead(hall);
Serial.println("Sıcaklık");
Serial.println(temp);
Serial.println("Nem");
Serial.println(humi);
Serial.println("Isik");
Serial.println(isik);
Serial.println("Reset");
Serial.println(dist);
client.publish("alkan/temp", String(temp).c_str());
client.publish("alkan/humi", String(humi).c_str());
client.publish("alkan/isik", String(isik).c_str());
client.publish("alkan/many", String(dist).c_str());
delay(5000);
}
}
}