일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- MQTT
- 파이썬
- 배당
- 코스피
- esp32
- 월패드
- matter
- 현대통신
- SK텔레콤
- Python
- Home Assistant
- 오블완
- RS-485
- 애플
- 해외주식
- 티스토리챌린지
- 홈네트워크
- cluster
- 국내주식
- 나스닥
- homebridge
- ConnectedHomeIP
- 힐스테이트 광교산
- Bestin
- 매터
- 미국주식
- Espressif
- raspberry pi
- 공모주
- Apple
- Today
- Total
YOGYUI
광교아이파크::거실 조명 Apple 홈킷 연동 (4) - Final 본문
4. 월패드 장착
월패드를 다시 뜯은 뒤에 제작한 보드를 연결
USB 케이블로 펌웨어를 이리저리 변경하면서 원하는대로 동작하는지 검증
※ 실험하면서 2가지 큰 문제를 발견했다
[1] 터치패드 입력 라인 관련된 커넥터의 입력단과 출력단이 뒤바뀌었다
터치패드의 TS04 출력단은 J2의 6번 핀으로 나와서, J1의 5번 핀으로 들어가서 월패드로 신호가 인가되어야 한다
이 신호를 내가 만든 보드에서는 DAC 출력 신호를 인가할 지, 원래 터치패드의 신호를 인가할 지를 MUX를 통해 선택하고자 설계하려고 했다
그런데 회로 설계할 때 술기운이 남아서 그랬는지 MUX 스위치의 입력과 출력단을 반대로 설계해버렸다
TMUX1237의 Source 1번 (3번 핀)에는 LCMD_IN이 아니라 LCMD_OUT이 와야 하고, Drain (4번 핀)에는 LCMD_IN이 와야 한다 (스위치의 입/출력단)
>> 해결책
다행히도 MUX 핀들에 저항 패키지들(R23, R24)을 배치해뒀기 때문에 (다행...) 다음과 같이 저항을 떼내고 와이어 2개를 치렁치렁 납땜해주면 된다
회로 수정 이후, MUX 출력을 DAC로 설정한 뒤 전압 출력값을 이리저리 바꿔가면서 다음 사실을 발견
-
+4V 수준이면 1번 조명이 On/Off 된다
-
+3V 수준이면 2번 조명이 On/Off 된다
앞서 회로 분석 시에는 2.8V랑 2.2V로 계산했었는데, 아무래도 저항값을 측정할 때 부정확한 값이 읽힌 게 아닌가 의심해본다 (조금만 복잡한 네트워크로 구성된 회로도 납땜된 상태에서 멀티미터만으로는 저항값을 올바르게 읽을 수가 없다...)
[2] 월패드로부터 인가되는 5V의 전력이 부족하다
디버깅을 위해 연결했던 USB 케이블을 제거하고 회로의 전원을 월패드에서 나오는 +5V로 전환하니 바로 ESP-12F의 전원이 꺼졌다 켜졌다를 반복하기 시작했다
무슨 일인가 싶어 멀티미터로 5V 전원단을 측정해보니 2.3V 수준으로 떨어져버린 것을 알 수 있었다
ESP-12F가 와이파이에 연결되면서부터 전류를 많이 끌어다쓰는 바람에 벌어진 문제가 아닌가 추측
(전류계가 따로 없어서 내가 만든 보드의 소모 전력이 얼마인지 알 수 있는 방법이 없다 ㅠ)
이럴 줄 알았으면 그냥 +11V 전원단을 따와서 +5V 레귤레이터를 하나 추가해줄 걸 그랬다...
(전력이 부족할 줄은 몰랐지... 11V는 터치패드 LED를 켜야하니 당연히 전력은 충분하지 않을까?)
>> 해결책
월패드 우측 하단에 사진첩 기능을 위한 메모리스틱을 꽂을 수 있도록 USB-A Type 커넥터가 하나 있는데, 다행히도 +5V가 월패드로부터 인가되고 있다
어차피 따로 쓸일도 없으니 이놈을 회로 전원으로 사용하기로 결정
볼트를 풀어주고 다음과 같이 사용하니, 안정적으로 ESP-12F가 동작했다 (다행...)
이제 회로상의 문제는 해결이 되었다...
딱히 상품화할 일도 없으니 회로를 수정하지는 않기로 한다 ㅋㅋ
펌웨어 업로드
WiFi + MQTT로 조명 제어 및 상태값 전송을 위한 아두이노 코드를 다음과 같이 작성
라이브러리는 #include 구문에서 알 수 있듯이 Adafruit_MCP4725, PubSubClient, ArduinoJson 3개를 사용했다
(ESP8266WiFi는 ESP8266 구동을 위해서는 필수, 보드 매니저에서 알아서 설치해준다)
MQTT Topic 문자열은 기존에 구현했던 Homebridge 악세서리들과 유사한 포맷으로 정했다
#include <ESP8266WiFi.h>
#include <Adafruit_MCP4725.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
char publish_msg[256];
StaticJsonDocument<256> json_doc;
const char* WIFI_SSID = "Your WiFi SSID";
const char* WIFI_PW = "Your WiFi Password";
WiFiClient wifi_client;
const char* MQTT_BROKER_ADDR = "MQTT Broker Address";
const int MQTT_BROKER_PORT = 30003;
const char* MQTT_ID = "MQTT Broker Auth ID";
const char* MQTT_PW = "MQTT Broker Auth Password";
PubSubClient mqtt_client(wifi_client);
const int DAC_RESOLUTION = 12;
const double DAC_VREG = 5.0;
Adafruit_MCP4725 dac;
#define LED_BUILTIN 2
const int MUX_SEL_PIN = 13;
const int LIGHT1_STATE_PIN = 14;
const int LIGHT2_STATE_PIN = 12;
int last_state_light1 = -1;
int last_state_light2 = -1;
const int MONITOR_INTERVAL_MS = 250;
long last_monitor_time = 0;
enum MUXOUT {
WALLPAD = 0,
DACOUT = 1
};
uint16_t convert_dac_value(double voltage) {
return uint16_t( (pow(2, DAC_RESOLUTION) - 1) / DAC_VREG * voltage);
}
void setDacOutVoltage(double voltage) {
uint16_t conv_val = convert_dac_value(voltage);
Serial.printf("Set DAC Output Voltage: %f V\n", voltage);
dac.setVoltage(conv_val, false);
}
void setMuxOut(MUXOUT value) {
if (value == WALLPAD) {
digitalWrite(MUX_SEL_PIN, LOW);
Serial.println("MUX OUT >> WALLPAD");
} else if (value == DACOUT) {
digitalWrite(MUX_SEL_PIN, HIGH);
Serial.println("MUX OUT >> DAC OUT");
}
}
void changeLightState(int index) {
if (index == 1) {
setDacOutVoltage(4.0);
} else if (index == 2) {
setDacOutVoltage(3.0);
}
setMuxOut(DACOUT);
delay(100);
setMuxOut(WALLPAD);
setDacOutVoltage(5.0);
}
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if (!strcmp(topic, "home/ipark/livingroom/light/command/0")) {
changeLightState(1);
} else if(!strcmp(topic, "home/ipark/livingroom/light/command/1")) {
changeLightState(2);
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PW);
Serial.print("\nWiFi Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
mqtt_client.setServer(MQTT_BROKER_ADDR, MQTT_BROKER_PORT);
mqtt_client.setCallback(mqtt_callback);
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
Serial.printf("MAC address = %s\n", WiFi.softAPmacAddress().c_str());
pinMode(LED_BUILTIN, OUTPUT);
pinMode(MUX_SEL_PIN, OUTPUT);
pinMode(LIGHT1_STATE_PIN, INPUT);
pinMode(LIGHT2_STATE_PIN, INPUT);
digitalWrite(LED_BUILTIN, LOW);
dac.begin(0x60);
setDacOutVoltage(5.0);
setMuxOut(WALLPAD);
readLightStateAll();
last_monitor_time = millis();
}
void establish_mqtt_connection() {
if (mqtt_client.connected())
return;
while (!mqtt_client.connected()) {
Serial.println("Try to connect MQTT Broker");
if (mqtt_client.connect("ESP8266_WALLPAD_LIVINGROOM", MQTT_ID, MQTT_PW)) {
Serial.println("Connected");
mqtt_client.subscribe("home/ipark/livingroom/light/command/0");
mqtt_client.subscribe("home/ipark/livingroom/light/command/1");
} else {
Serial.print("failed, rc=");
Serial.print(mqtt_client.state());
delay(2000);
}
}
}
void readLightState(int index) {
int state = -1;
if (index == 1) {
state = digitalRead(LIGHT1_STATE_PIN);
if (state != last_state_light1) {
last_state_light1 = state;
publishLightState(1);
}
} else if (index == 2) {
state = digitalRead(LIGHT2_STATE_PIN);
if (state != last_state_light2) {
last_state_light2 = state;
publishLightState(2);
}
}
}
void readLightStateAll() {
readLightState(1);
readLightState(2);
}
void publishLightState(int index) {
size_t n = 0;
if (index == 1) {
json_doc["state"] = last_state_light1;
n = serializeJson(json_doc, publish_msg);
mqtt_client.publish(
"home/ipark/livingroom/light/state/0",
publish_msg,
n);
Serial.print("Published (home/ipark/livingroom/light/state/0): ");
Serial.println(publish_msg);
} else if (index == 2) {
json_doc["state"] = last_state_light2;
n = serializeJson(json_doc, publish_msg);
mqtt_client.publish(
"home/ipark/livingroom/light/state/1",
publish_msg,
n);
Serial.print("Published (home/ipark/livingroom/light/state/1): ");
Serial.println(publish_msg);
}
}
void loop() {
establish_mqtt_connection();
mqtt_client.loop();
long current = millis();
if (current - last_monitor_time >= MONITOR_INTERVAL_MS) {
last_monitor_time = current;
readLightStateAll();
}
}
파일을 분리하지 않고 하나로만 하려다보니 코드가 좀 길긴 하다 ㅠ
Homebridge 악세서리 설정
{
"accessory": "mqttthing",
"type": "switch",
"name": "Living room Light1 (MQTT)",
"url": "mqtt:://mosquitto address",
"username": "mosquitto ID",
"password": "mosquitto password",
"topics": {
"getOn": {
"topic": "home/ipark/livingroom/light/state/0",
"apply": "return JSON.parse(message).state;"
},
"setOn": {
"topic": "home/ipark/livingroom/light/command/0",
"apply": "return JSON.stringify({state: message});"
}
},
"integerValue": true,
"onValue": 1,
"offValue": 0,
"history": true,
"logMqtt": true
},
{
"accessory": "mqttthing",
"type": "switch",
"name": "Living room Light2 (MQTT)",
"url": "mqtt:://mosquitto address",
"username": "mosquitto ID",
"password": "mosquitto password",
"topics": {
"getOn": {
"topic": "home/ipark/livingroom/light/state/1",
"apply": "return JSON.parse(message).state;"
},
"setOn": {
"topic": "home/ipark/livingroom/light/command/1",
"apply": "return JSON.stringify({state: message});"
}
},
"integerValue": true,
"onValue": 1,
"offValue": 0,
"history": true,
"logMqtt": true
}
동작확인
월패드로 상태 변경 시 악세서리 상태도 빠르게 반영되고, Apple HomeKit으로 제어 시에도 빠른 응답속도를 보인다
완전 만족스럽게 잘된다!!!
(조명 2개는 상호 배타적이다::1번은 형광등 3개 ON, 2번은 형광등 5개 ON)
끝~!
[시리즈 링크]
'홈네트워크(IoT) > 광교아이파크' 카테고리의 다른 글
광교아이파크::난방 온도값 파싱 오류 (0) | 2021.07.21 |
---|---|
광교아이파크::Bestin ↔ Apple HomeKit 연동 Summary (1) (13) | 2021.03.20 |
광교아이파크::거실 조명 Apple 홈킷 연동 (3) (0) | 2021.03.10 |
광교아이파크::거실 조명 Apple 홈킷 연동 (2) (0) | 2021.02.18 |
광교아이파크::거실 조명 Apple 홈킷 연동 (1) (4) | 2021.02.15 |