MQTT 스마트 스위치 버전3 (서보모터)

반응형
버전2 문제: 정확한 원인은 모르지만 풀업저항 혹은 풀다운 저항을 구성해도 플로팅 현상이 있어서 불이 자동으로 켜지는 문제가 있었다.
해경방안: 스위치는 본래 스위치로 역할을 하도록하고 서보모터로 움직이면서 물리적으로 켜고 끄는 것이 되도록 실을 이용.

설명


실은 유종적이기 때문에 우리가 스위치를 눌러도 서보모터에 영향은 없어서 작동에 문제는 없다.

 

다만, mqtt서버에 접속을 자동으로 다시 하게 되면 메세지를 반복하게 되어서 원하지 않게 불이 켜지거나 서보모터가 움직이는 일이 있는데  이를 해결하기 위해서는 mqtt서버에서 한가지를 더 해주어야한다.

 


아두이노 코드


#include <WiFi.h>
#include <PubSubClient.h>
#include <ESP32_Servo.h>

const char *ssid =  "WiFi SSID";   
const char *password =  "WiFi 비번"; 

const char* ID = "이름";  // Name of our device, must be unique
const char* TOPIC = "room/light/ahn"; 
const char* INTOPIC = "room/light/Switch";
const char* mqttUser = "MQTT 아이디";
const char* mqttPassword = "MQTT 비번";
const char* broker = "MQTT 아이피";

WiFiClient wclient;
PubSubClient client(wclient); 
char messages[50];
int state = 0;
int LState = 0;
static const int servoPin = 4;
Servo servo1;

// Connect to WiFi network
void setup_wifi() {
  Serial.print("\nConnecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password); 
  while (WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Received messages: ");
  Serial.print(INTOPIC);
  for(int i=0; i<length; i++){
    Serial.println((char) payload[i]);
  }
  Serial.println();
  if ((char)payload[0] != LState) {
    if ((char)payload[0] == '1') {
      SwitchOn();
    } else if((char)payload[0] == '0') {
      SwitchOff();
    }
  }
  delay(100);
}
//스위치 켬
void SwitchOn() {
  servo1.write(140); // 빠른 속도로 당기도록
  delay(200); // 딜레이를 주지 않으면 움직이지 않음
  state = 1; // 스위치 상태 변화
  //스위치 중간 위치로 복귀
  for(int posDegrees = 70; posDegrees >= 60; posDegrees--) {
    servo1.write(posDegrees);
    Serial.println(posDegrees);
    delay(20);
  }
}
void SwitchOff() { 
  state = 0;
  servo1.write(0);
  delay(100);
  for(int posDegrees = 50; posDegrees <= 60; posDegrees++) {
    servo1.write(posDegrees);
    Serial.println(posDegrees);
    delay(20);
  }
}


// Reconnect to client
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(ID, mqttUser, mqttPassword)) {
      Serial.println("connected");
      Serial.print("Publishing to: ");
      Serial.println(TOPIC);
      Serial.println('\n');
      client.subscribe(INTOPIC);

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println("\n try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200); 
  servo1.attach(servoPin);
//  pinMode(light, OUTPUT);
  pinMode(5, INPUT);
  delay(100);
  setup_wifi(); // Connect to network
  client.setServer(broker, 1883);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()){
    reconnect();
  }
  client.loop();
  state = digitalRead(5);
  // 스위치 상태 변화하면 서버에 상태를 알려줌
  // 물리적으로 스위치 켬/끔 감지
  if (state != LState){
    snprintf(messages, 75, "%ld", state);
    client.publish(TOPIC, messages);
    delay(100);
    LState = state;
  }
}

 


홈어시스턴트 자동화 


(ESP32에서 전등상태가 변화했다는 메세지가 오면 3이라는 메세지를 보드에 다시 전달하게 되는데 3은 아무런 동작을 주지 않는다. - 보드가 MQTT에 재접속하더라도 3을 전달 받게 되어 불이 켜지는 등의 일이 일어나지 않는다.)

*retain: true로 설정해야 재접속에서도 3을 전달하게 된다.


실은 순간 접착제로 고정했다.

반응형