์๋ ์๋ ํ ์คํ ๋ฉ์ด์ ์์คํ , ์ฆ ํํ "์ค๋งํธ ํ"์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ์์คํ ์ ๊ฐ๊ฒฉ์ด ๋๋ฌด ๋น์ธ์ ๋ถ์๋ค๋ง์ด ๊ฐ๋นํ ์ ์์์ต๋๋ค. ์ค๋๋ ์์ฅ์์๋ ์กฐ๋ช , ์์ผ, ํ๊ธฐ, ๋ฌผ ๊ณต๊ธ ๋ฐ ๊ธฐํ ์๋น์๋ฅผ ์ ์ดํ๊ธฐ ์ํ ์ผ์, ๋ฒํผ/์ค์์น ๋ฐ ์ก์ถ์์ดํฐ๊ฐ ํฌํจ๋ ์๋นํ ์ ๋ ดํ ํคํธ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ๋น๋ค์ด์ง DIY ์ฌ๋์ด๋ผ๋ ์ ๋ ดํ ๊ฐ๊ฒฉ์ผ๋ก ๋ฏธ์ฉ์ ์ฐธ์ฌํ๊ณ ์ค๋งํธ ํ์ฉ ์ฅ์น๋ฅผ ์กฐ๋ฆฝํ ์ ์์ต๋๋ค.

์ผ๋ฐ์ ์ผ๋ก ์ ์๋ ์ฅ์น๋ ์ผ์ ๋๋ ์ก์ถ์์ดํฐ์
๋๋ค. "๋ชจ์
์ผ์๊ฐ ์๋ํ๋ฉด ์กฐ๋ช
์ ์ผ์ธ์" ๋๋ "์ถ๊ตฌ ๊ทผ์ฒ์ ์ค์์น๋ฅผ ๋๋ฅด๋ฉด ์ํํธ ์ ์ฒด์ ์กฐ๋ช
์ด ๊บผ์ง๋๋ค"์ ๊ฐ์ ์๋๋ฆฌ์ค๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. ํ์ง๋ง ์๊ฒฉ ์ธก์ ์ผ๋ก๋ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์ง ์์์ต๋๋ค. ๊ธฐ๊ปํด์ผ ์จ๋์ ์ต๋ ๋๋ ํน์ ์ฝ์ผํธ์ ์๊ฐ ์ ๋ ฅ ๊ทธ๋ํ์
๋๋ค.
์ต๊ทผ์ ํ์ค ์ถ๋ ฅ์ด ์๋ ์๋๊ณ๋ฅผ ์ค์นํ์ต๋๋ค. ๋ฏธํฐ๋ฅผ ํต๊ณผํ๋ ๋ชจ๋ ๋ฆฌํฐ์ ๋ํด ๋ฆฌ๋ ์ค์์น๊ฐ ํ์ฑํ๋๊ณ ์ ์ ์ด ๋ซํ๋๋ค. ๋จ์ ์ ์ผํ ์ผ์ ์ ์ ์ ๋งค๋ฌ๋ ค ๊ทธ๊ฒ์ผ๋ก๋ถํฐ ์ด์ต์ ์ป์ผ๋ ค๊ณ ๋ ธ๋ ฅํ๋ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ์๊ฐ๋ณ, ์์ผ๋ณ๋ก ๋ฌผ ์๋น๋์ ๋ถ์ํฉ๋๋ค. ๊ธ์, ์ํํธ์ ๋ฌผ ๋ผ์ด์ ๊ฐ ์ฌ๋ฌ ๊ฐ ์์ผ๋ฉด ์์ ๋ฑ์ ์ฌ์ฉํ์ฌ ์ ๊ทผํ๊ธฐ ์ด๋ ค์ด ํ์๋ก ์ฌ๋ผ๊ฐ๋ ๊ฒ๋ณด๋ค ํ ํ๋ฉด์์ ๋ชจ๋ ํ์ฌ ํ์๊ธฐ๋ฅผ ๋ณด๋ ๊ฒ์ด ๋ ํธ๋ฆฌํฉ๋๋ค.
์ปท ์๋์๋ ์๋๊ณ์ ํ์ค๋ฅผ ๊ณ์ฐํ๊ณ MQTT๋ฅผ ํตํด ํ๋
๊ฐ์ ์ค๋งํธ ํ ์๋ฒ๋ก ๋ณด๋ด๋ ESP8266 ๊ธฐ๋ฐ ์ฅ์น์ ๋ด ๋ฒ์ ์ด ์์ต๋๋ค. uasyncio ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ micropython์ผ๋ก ํ๋ก๊ทธ๋๋ฐํ๊ฒ ์ต๋๋ค. ํ์จ์ด๋ฅผ ๋ง๋ค ๋ ๋ช ๊ฐ์ง ํฅ๋ฏธ๋ก์ด ์ด๋ ค์์ ์ง๋ฉดํ์ผ๋ฉฐ ์ด ๊ธฐ์ฌ์์๋ ์ด์ ๋ํด ๋
ผ์ํ๊ฒ ์ต๋๋ค. ๊ฐ๋ค!
๊ณํ

์ ์ฒด ํ๋ก์ ํต์ฌ์ ESP8266 ๋ง์ดํฌ๋ก์ปจํธ๋กค๋ฌ์ ๋ชจ๋์
๋๋ค. ESP-12๋ ์๋ ๊ณํ๋์์ผ๋ ๊ฒฐํจ์ด ์๋ ๊ฒ์ผ๋ก ํ๋ช
๋์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฌ์ฉ ๊ฐ๋ฅํ ESP-07 ๋ชจ๋์ ๋ง์กฑํด์ผ ํ์ต๋๋ค. ๋คํ์ค๋ฝ๊ฒ๋ ํ๊ณผ ๊ธฐ๋ฅ๋ฉด์์ ๋์ผํ๋ฉฐ ์ ์ผํ ์ฐจ์ด์ ์ ์ํ
๋์
๋๋ค. ESP-12์๋ ๋ด์ฅํ์ด ์๊ณ ESP-07์๋ ์ธ๋ถ ์ํ
๋๊ฐ ์์ต๋๋ค. ํ์ง๋ง WiFi ์ํ
๋๊ฐ ์์ด๋ ์์ค์์๋ ์ ํธ๊ฐ ์ ์์ ์ผ๋ก ์์ ๋ฉ๋๋ค.
ํ์ค ๋ชจ๋ ๋ฐฐ์ :
- ํ์ ๋ฐ ์ปคํจ์ํฐ๊ฐ ์๋ ์ฌ์ค์ ๋ฒํผ(๋ ๋ค ์ด๋ฏธ ๋ชจ๋ ๋ด๋ถ์ ์์)
- ํ์ฑํ ์ ํธ(CH_PD)๊ฐ ์ ์์ผ๋ก ํ์ ๋ฉ๋๋ค.
- GPIO15๊ฐ ๋ ์ผ๋ก ๋น๊ฒจ์ง๋๋ค. ์ด๊ฒ์ ์ฒ์์๋ง ํ์ํ์ง๋ง ์์ง ์ด ๋ค๋ฆฌ์ ์ฐ๊ฒฐํ ๊ฒ์ด ์์ต๋๋ค. ๋ ์ด์ ํ์ํ์ง ์์ต๋๋ค.
๋ชจ๋์ ํ์จ์ด ๋ชจ๋๋ก ์ ํํ๋ ค๋ฉด GPIO2๋ฅผ ์ ์ง๋ก ๋จ๋ฝ์์ผ์ผ ํ๋ฉฐ, ์ด๋ฅผ ๋ณด๋ค ํธ๋ฆฌํ๊ฒ ํ๊ธฐ ์ํด ๋ถํ ๋ฒํผ์ ์ ๊ณตํ์ต๋๋ค. ์ ์์ ์ธ ์กฐ๊ฑด์์๋ ์ด ํ์ด ๋น๊ฒจ์ ธ ์ ์์ด ๊ณต๊ธ๋ฉ๋๋ค.
GPIO2 ๋ผ์ธ์ ์ํ๋ ์๋ ์์ ์, ์ฆ ์ ์์ด ๊ณต๊ธ๋ ๋ ๋๋ ์ฌ์ค์ ์งํ์๋ง ํ์ธ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋ชจ๋์ ํ์๋๋ก ๋ถํ ๋๊ฑฐ๋ ํ์จ์ด ๋ชจ๋๋ก ์ ํ๋ฉ๋๋ค. ๋ก๋๋๋ฉด ์ด ํ์ ์ผ๋ฐ GPIO๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ธ์, ์ด๋ฏธ ๋ฒํผ์ด ์๊ธฐ ๋๋ฌธ์ ์ ์ฉํ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
ํ๋ก๊ทธ๋๋ฐ๊ณผ ๋๋ฒ๊น ์ ์ํด ๋น์ผ๋ก ์ถ๋ ฅ๋๋ UART๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ์ํ ๊ฒฝ์ฐ USB-UART ์ด๋ํฐ๋ฅผ ์ฐ๊ฒฐํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ๋ชจ๋์ 3.3V๋ก ์ ์์ด ๊ณต๊ธ๋๋ค๋ ์ ๋ง ๊ธฐ์ตํ๋ฉด ๋ฉ๋๋ค. ์ด๋ํฐ๋ฅผ ์ด ์ ์์ผ๋ก ์ ํํ๊ณ 5V๋ฅผ ๊ณต๊ธํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆฌ๋ฉด ๋ชจ๋์ด ์์ง๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.
์์ค์ ์ ๊ธฐ์๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ฝ์ผํธ๋ ๋ฏธํฐ์์ ์ฝ 220m ๋จ์ด์ ธ ์์ผ๋ฏ๋ก XNUMXV๋ก ์ ์์ ๊ณต๊ธ๋ฐ์ต๋๋ค. ์ ์์ผ๋ก์ ๋๋ ์์ ๊ฒ์ ๊ฐ์ง ๊ฒ์ ๋๋ค ํ ์คํ ๋ก๋ด์ ์ํด. ๊ฐ์ธ์ ์ผ๋ก ์๋ ๋ก๊ทธ์ ์ ๋ ฅ์ ์์ ์ด๋ ค์์ ๊ฒช๊ณ ์๋๋ฐ ์ฌ๊ธฐ ์์ ์ผ์ด์ค์ ๊ธฐ์ฑํ ์ ์ ๊ณต๊ธ ์ฅ์น๊ฐ ๋ค์ด์์ต๋๋ค.
์๋ ๋ชจ๋๋ฅผ ์๋ฆฌ๊ธฐ ์ํด GPIO2์ ์ฐ๊ฒฐ๋ LED๋ฅผ ์ ๊ณตํ์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ฉ๋์ ์ ํ์ผ๋... ESP-07 ๋ชจ๋์๋ ์ด๋ฏธ LED๊ฐ ์์ผ๋ฉฐ GPIO2์๋ ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค. ํ์ง๋ง ์ด LED๋ฅผ ์ผ์ด์ค์ ์ถ๋ ฅํ๊ณ ์ถ๋ค๋ฉด ๋ณด๋์ ๋์ธ์.
๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๋ถ๋ถ์ผ๋ก ๋์ด๊ฐ๊ฒ ์ต๋๋ค. ์๋๊ณ์๋ ๋ ผ๋ฆฌ๊ฐ ์์ต๋๋ค. ํ์ฌ ์์น๋ฅผ ์์ฒญํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ์ ์๋ ์ ์ผํ ๊ฒ์ ์ถฉ๋์ ๋๋ค. ๋งค ๋ฆฌํฐ๋ง๋ค ๋ฆฌ๋ ์ค์์น์ ์ ์ ์ ๋ซ๋ ๊ฒ์ ๋๋ค. ๋ด ๋ฆฌ๋ ์ค์์น ์ถ๋ ฅ์ด GPIO12/GPIO13์ ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค. ๋ชจ๋ ๋ด๋ถ์์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ํ์ ์ ํญ์ ํ์ฑํํ๊ฒ ์ต๋๋ค.
์ฒ์์๋ ์ ํญ R8 ๋ฐ R9๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ์์๊ณ ๋ด ๋ฒ์ ์ ๋ณด๋์๋ ์ ํญ์ด ์์ต๋๋ค. ํ์ง๋ง ์ด๋ฏธ ๋ชจ๋ ์ฌ๋์ด ๋ณผ ์ ์๋๋ก ๋ค์ด์ด๊ทธ๋จ์ ๊ฒ์ํ๊ณ ์์ผ๋ฏ๋ก ์ด๋ฌํ ์ค์๋ฅผ ๋ฐ๋ก์ก์ ๊ฐ์น๊ฐ ์์ต๋๋ค. ํ์จ์ด ๊ฒฐํจ์ผ๋ก ์ธํด ํ์ด 3.3๋ก ์ค์ ๋๊ณ ๋ฆฌ๋ ์ค์์น๊ฐ ์ด ๋ผ์ธ์ ์ ์ง๋ก ๋จ๋ฝ์ํค๋ ๊ฒฝ์ฐ ํฌํธ๊ฐ ํ์ง ์๋๋ก ์ ํญ์ด ํ์ํฉ๋๋ค(์ ํญ์ ๊ฒฝ์ฐ ์ต๋ 1000V/3.3Ohm = XNUMXmA๊ฐ ํ๋ฆ ๋๋ค).
์ ์ ์ด ๋๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ์ง ์๊ฐํด ๋ณผ ๋์ ๋๋ค. ์ฒซ ๋ฒ์งธ ์ต์ ์ ์์ ์ ์๋ฒ์ ์ด๊ธฐ ์นด์ดํฐ ๊ฐ์ ์์ฒญํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฅผ ์ํด์๋ ๊ตํ ํ๋กํ ์ฝ์ด ์๋นํ ๋ณต์กํด์ ธ์ผ ํฉ๋๋ค. ๋ํ ์ด ๊ฒฝ์ฐ ์ฅ์น์ ์ฑ๋ฅ์ ์๋ฒ ์ํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ์ ์์ ๋ ํ(๋๋ ๋์ค์ ์์ํ ํ) ์๋ฒ๊ฐ ์์๋์ง ์์ผ๋ฉด ์๋๊ณ๊ฐ ์ด๊ธฐ๊ฐ์ ์์ฒญํ ์ ์์ด ์ ๋๋ก ์๋ํ์ง ์๊ฒ ๋ฉ๋๋ค.
๊ทธ๋์ I2C๋ฅผ ํตํด ์ฐ๊ฒฐ๋ ๋ฉ๋ชจ๋ฆฌ ์นฉ์ ์นด์ดํฐ ๊ฐ ์ ์ฅ์ ๊ตฌํํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ํ๋์ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ์ ๋ํ ํน๋ณํ ์๊ตฌ ์ฌํญ์ ์์ต๋๋ค. 2๊ฐ์ ์ซ์(์จ์ ๋ฐ ๋์ ๊ณ๋๊ธฐ์ ๋ฐ๋ฅธ ๋ฆฌํฐ ์)๋ง ์ ์ฅํ๋ฉด ๋ฉ๋๋ค. ๊ฐ์ฅ ์์ ๋ชจ๋์ด๋ผ๋ ๊ฐ๋ฅํฉ๋๋ค. ํ์ง๋ง ๋ นํ ์ฃผ๊ธฐ ์์ ์ฃผ์ํด์ผ ํฉ๋๋ค. ๋๋ถ๋ถ์ ๋ชจ๋์์ ์ด๋ 100๋ง ์ฃผ๊ธฐ์ด๊ณ ์ผ๋ถ ๋ชจ๋์์๋ ์ต๋ XNUMX๋ง ์ฃผ๊ธฐ์ ๋๋ค.
๋ฐฑ๋ง์ ๋ง์ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ง๋ง ์ํํธ์ ์ฌ๋ 4๋ ๋์ ์ ๋ 500์ ๋ฐฉ๋ฏธํฐ๊ฐ ์กฐ๊ธ ๋๋ ๋ฌผ์ ์๋นํ์ต๋๋ค. ์ฆ 500๋ง ๋ฆฌํฐ์ ๋ฌํ๋ ๋ฌผ์ ๋๋ค! ํ๋์์๋ 500๋ง ๊ฐ์ ๋ ์ฝ๋๊ฐ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ๋จ์ง ์ฐจ๊ฐ์ด ๋ฌผ์ ๋๋ค. ๋ฌผ๋ก ๋ช ๋ ์ ํ ๋ฒ์ฉ ์นฉ์ ์ฌ๋ฉ๋ํ ์ ์์ง๋ง FRAM ์นฉ์ด ์๋ค๋ ๊ฒ์ด ๋ฐํ์ก์ต๋๋ค. ํ๋ก๊ทธ๋๋ฐ ๊ด์ ์์ ๋ณผ ๋ ์ด๋ ๋งค์ฐ ๋ง์ ์ฌ์์ฑ ์ฃผ๊ธฐ(์์ต)๋ง ํฌํจํ๋ ๋์ผํ I2C EEPROM์ ๋๋ค. ์์ง ๊ทธ๋ฐ ์ด์ํ ํ๋ก๋ฅผ ๊ฐ์ง๊ณ ๋งค์ฅ์ ๊ฐ ์ ์๊ธฐ ๋๋ฌธ์ ์ง๊ธ์ ์ผ๋ฐ์ ์ธ 24LC512๊ฐ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค.
์ธ์ ํ๋ก ๊ธฐํ
์ฒ์์๋ ์ง์์ ๋ณด๋๋ฅผ ๋ง๋ค ๊ณํ์ด์์ต๋๋ค. ๋ฐ๋ผ์ ๋ณด๋๋ ๋จ๋ฉด์ผ๋ก ์ค๊ณ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ์ด์ ๋ค๋ฆฌ๋ฏธ์ ์๋ ๋ง์คํฌ๋ฅผ ์ฌ์ฉํ์ฌ ํ ์๊ฐ์ ๋ณด๋ธ ํ์๋(๊ทธ๊ฒ์ด ์์ผ๋ฉด ์ ํ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค), ์ ๋ ์ฌ์ ํ ์ค๊ตญ์ฐ ๋ณด๋๋ฅผ ์ฃผ๋ฌธํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.

๋ณด๋๋ฅผ ์ฃผ๋ฌธํ๊ธฐ ๊ฑฐ์ ์ ์ ํ๋์ ๋ฉ๋ชจ๋ฆฌ ์นฉ ์ธ์๋ ๋์คํ๋ ์ด์ ๊ฐ์ด I2C ๋ฒ์ค์ ์ ์ฉํ ๋ค๋ฅธ ๊ฒ์ ์ฐ๊ฒฐํ ์ ์๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค. ์ ํํ ๋ฌด์์ ์ถ๋ ฅํ ์ง๋ ์ฌ์ ํ ์๋ฌธ์ด์ง๋ง ๋ณด๋์์ ๋ผ์ฐํ
ํด์ผ ํฉ๋๋ค. ๊ธ์, ๊ณต์ฅ์์ ๋ณด๋๋ฅผ ์ฃผ๋ฌธํ ์์ ์ด์๊ธฐ ๋๋ฌธ์ ๋จ๋ฉด ๋ณด๋์๋ง ๊ตญํํ ํ์๊ฐ ์์์ผ๋ฏ๋ก I2C ๋ผ์ธ์ ๋ณด๋ ๋ท๋ฉด์ ์๋ ์ ์ผํ ๋ผ์ธ์
๋๋ค.
์ผ๋ฐฉํฅ ๋ฐฐ์ ์๋ ํฐ ๋ฌธ์ ๊ฐ ํ๋ ์์์ต๋๋ค. ์๋ํ๋ฉด ๋ณด๋๊ฐ ๋จ๋ฉด์ผ๋ก ๊ทธ๋ ค์ ธ ํธ๋๊ณผ SMD ๋ถํ์ด ํ์ชฝ์ ๋ฐฐ์น๋๊ณ ์ถ๋ ฅ ๋ถํ, ์ปค๋ฅํฐ, ์ ์ ๊ณต๊ธ ์ฅ์น๊ฐ ๋ค๋ฅธ์ชฝ์ ๋ฐฐ์น๋๋๋ก ๊ณํ๋์์ต๋๋ค. ํ ๋ฌ ํ ๋ณด๋๋ฅผ ๋ฐ์์ ๋ ์๋ ๊ณํ์ ์์ด๋ฒ๋ฆฌ๊ณ ์ ๋ฉด์ ๋ชจ๋ ๊ตฌ์ฑ ์์๋ฅผ ๋ฉ๋ํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ์ ๊ณต๊ธ ์ฅ์น๋ฅผ ๋ฉ๋ํ ๋๋ง ํ๋ฌ์ค์ ๋ง์ด๋์ค๊ฐ ๋ฐ๋๋ก ๋ฐฐ์ ๋ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ์ ํผ๋ฅผ ๊ฐ์ง๊ณ ๋์ฌ๋ฅผ ์ง์ด์ผ ํ์ด์. ์ ๊ทธ๋ฆผ์์๋ ์ด๋ฏธ ๋ฐฐ์ ์ ๋ณ๊ฒฝํ์ง๋ง Boot ๋ฒํผ์ ํ์ ํตํด ๋ณด๋์ ํ ๋ถ๋ถ์์ ๋ค๋ฅธ ๋ถ๋ถ์ผ๋ก ์ ์ง๊ฐ ์ ์ก๋์์ต๋๋ค(๋ ๋ฒ์งธ ๋ ์ด์ด์ ํธ๋์ ๊ทธ๋ฆฌ๋ ๊ฒ์ด ๊ฐ๋ฅํ์ง๋ง).
์ด๋ ๊ฒ ๋์ด์

ะะพัะฟัั
๋ค์ ๋จ๊ณ๋ ์ ์ฒด์ ๋๋ค. 3D ํ๋ฆฐํฐ๊ฐ ์๋ค๋ฉด ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ๋ณ๋ก ์ ๊ฒฝ ์ฐ์ง ์๊ณ ์ ๋นํ ํฌ๊ธฐ์ ์์๋ฅผ ๊ทธ๋ฆฌ๊ณ ์ ๋นํ ์์น์ ์ปท์์์ ๋ง๋ค์์ต๋๋ค. ๋ฎ๊ฐ๋ ์์ ์ ํ ํํ ๋์ฌ๋ก ๋ณธ์ฒด์ ๋ถ์ฐฉ๋ฉ๋๋ค.

Boot ๋ฒํผ์ ๋ฒ์ฉ ๋ฒํผ์ผ๋ก ์ฌ์ฉ๋ ์ ์๋ค๊ณ ์ด๋ฏธ ์ธ๊ธํ์ผ๋ฏ๋ก ์ ๋ฉด ํจ๋์ ํ์ํ๊ฒ ์ต๋๋ค. ์ด๋ฅผ ์ํด ๋ฒํผ์ด ์๋ ๊ณณ์ ํน๋ณํ "์ฐ๋ฌผ"์ ๊ทธ๋ ธ์ต๋๋ค.

์ผ์ด์ค ๋ด๋ถ์๋ ๋ณด๋๊ฐ ์ค์น๋๊ณ ๋จ์ผ M3 ๋์ฌ๋ก ๊ณ ์ ๋๋ ์คํฐ๋๋ ์์ต๋๋ค(๋ณด๋์ ๋ ์ด์ ๊ณต๊ฐ์ด ์์).
์ ๋ ์ผ์ด์ค์ ์ฒซ ๋ฒ์งธ ์ํ ๋ฒ์ ์ ์ธ์ํ ๋ ์ด๋ฏธ ๋์คํ๋ ์ด๋ฅผ ์ ํํ์ต๋๋ค. ํ์ค 1306์ค ๋ฆฌ๋๊ธฐ๋ ์ด ์ผ์ด์ค์ ๋ง์ง ์์์ง๋ง ํ๋จ์๋ OLED ๋์คํ๋ ์ด SSD128 32รXNUMX๊ฐ ์์์ต๋๋ค. ์กฐ๊ธ ์์ง๋ง ๋งค์ผ ์ณ๋ค๋ณผ ํ์๋ ์๊ณ ๋์๊ฒ๋ ๋๋ฌด ๊ณผ์คํ๋ค.
์ด๋ฐ ์์ผ๋ก ์ ์ ์ด ์ด๋ป๊ฒ ์ฐ๊ฒฐ๋ ์ง ํ์ ํ๊ณ ๋์คํ๋ ์ด๋ฅผ ์ผ์ด์ค ์ค์์ ๋ถ์ด๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ๋ฌผ๋ก ์ธ์ฒด ๊ณตํ์ ๋๋ฑ ์ดํ์ ๋๋ค. ๋ฒํผ์ ์๋จ์ ์๊ณ ๋์คํ๋ ์ด๋ ํ๋จ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ฏธ ๋์คํ๋ ์ด๋ฅผ ๋ถ์ฐฉํ๋ ค๋ ์์ด๋์ด๊ฐ ๋๋ฌด ๋ฆ๊ฒ ๋์๊ณ ๋ฒํผ์ ์ด๋ํ๊ธฐ ์ํด ๋ณด๋๋ฅผ ๋ค์ ๋ฐฐ์ ํ๊ธฐ์๋ ๋๋ฌด ๊ฒ์ผ๋ฅด๋ค๊ณ ๋งํ์ต๋๋ค.
์ฅ์น๊ฐ ์กฐ๋ฆฝ๋์์ต๋๋ค. ๋์คํ๋ ์ด ๋ชจ๋์ ๋จ๊ฑฐ์ด ์ ์ฐฉ์ ๋ก ์ฝง๋ฌผ์ ์ ์ฐฉ๋ฉ๋๋ค.


์ต์ข
๊ฒฐ๊ณผ๋ KDPV์์ ๋ณผ ์ ์์ต๋๋ค.
ํ์จ์ด
์ํํธ์จ์ด ๋ถ๋ถ์ผ๋ก ๋์ด ๊ฐ์๋ค. ์ด์ ๊ฐ์ ์์ ๊ณต์์ ๊ฒฝ์ฐ ์ ๋ Python์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ๋ง ์ข์ํฉ๋๋ค() - ์ฝ๋๋ ๋งค์ฐ ๊ฐ๊ฒฐํ๊ณ ์ดํดํ๊ธฐ ์ฌ์ด ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ๋คํ์ค๋ฝ๊ฒ๋ ๋ง์ดํฌ๋ก์ด๋ฅผ ๋จ์ถํ๊ธฐ ์ํด ๋ ์ง์คํฐ ์์ค์ผ๋ก ๋ด๋ ค๊ฐ ํ์๊ฐ ์์ต๋๋ค. ๋ชจ๋ ๊ฒ์ด Python์์ ์ํ๋ ์ ์์ต๋๋ค.
๋ชจ๋ ๊ฒ์ด ๋จ์ํด ๋ณด์ด์ง๋ง ๊ทธ๋ค์ง ๋จ์ํ์ง๋ ์์ต๋๋ค. ์ด ์ฅ์น์๋ ์ฌ๋ฌ ๊ฐ์ง ๋ ๋ฆฝ์ ์ธ ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
- ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ๋๋ฅด๊ณ ๋์คํ๋ ์ด๋ฅผ ๋ด ๋๋ค.
- ํ๋์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฆฌํฐ ํฑ ๋ฐ ์ ๋ฐ์ดํธ ๊ฐ
- ๋ชจ๋์ WiFi ์ ํธ๋ฅผ ๋ชจ๋ํฐ๋งํ๊ณ ํ์ํ ๊ฒฝ์ฐ ๋ค์ ์ฐ๊ฒฐํฉ๋๋ค.
- ๊ธ์, ๊น๋ฐ์ด๋ ์ ๊ตฌ ์์ด๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค
์ด๋ค ์ด์ ๋ก ๋ค๋ฅธ ๊ธฐ๋ฅ์ด ์๋ํ์ง ์๋ ๊ฒฝ์ฐ ํ ๊ธฐ๋ฅ์ด ์๋ํ์ง ์๋๋ค๊ณ ๊ฐ์ ํ ์ ์์ต๋๋ค. ๋๋ ์ด๋ฏธ ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ ์ธ์ฅ์ ๊ฐ๋ ์ฑ์ ๊ณ ์ง๊ธ๋ "๋์คํ๋ ์ด๊ฐ ๊ทธ ์๊ฐ ์ ๋ฐ์ดํธ๋๊ณ ์์๊ธฐ ๋๋ฌธ์ ๋ ๋ค๋ฅธ ๋ฆฌํฐ๋ฅผ ๋์ณค์ต๋๋ค" ๋๋ "๋ชจ๋์ด ์ฐ๊ฒฐ๋๋ ๋์ ์ฌ์ฉ์๋ ์๋ฌด๊ฒ๋ ํ ์ ์์ต๋๋ค"์ ๊ฐ์ ์คํ์ผ์ ๊ฒฐํจ์ด ์ฌ์ ํ ๋ณด์ ๋๋ค. ์์ดํ์ด." ๋ฌผ๋ก ์ผ๋ถ ์์ ์ ์ธํฐ๋ฝํธ๋ฅผ ํตํด ์ํํ ์ ์์ง๋ง ๊ธฐ๊ฐ, ํธ์ถ ์ค์ฒฉ ๋๋ ๋ณ์์ ๋ํ ๋น์์์ ๋ณ๊ฒฝ์ ๋ํ ์ ํ์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ๊ธ์, ๋ชจ๋ ์์ ์ ์ํํ๋ ์ฝ๋๋ ๋น ๋ฅด๊ฒ ์์ฑํด์ง๋๋ค.
ะ ์ ๋ ํด๋์ ์ ์ ํ ๋ฉํฐํ์คํน๊ณผ FreeRTOS๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ด ๊ฒฝ์ฐ ๋ชจ๋ธ์ด ํจ์ฌ ๋ ์ ํฉํ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. . ๋์ฑ์ด Python์ ์ฝ๋ฃจํด ๊ตฌํ์ ์ ๋ง ๋๋์ต๋๋ค. ํ๋ก๊ทธ๋๋จธ๋ฅผ ์ํด ๋ชจ๋ ๊ฒ์ด ๊ฐ๋จํ๊ณ ํธ๋ฆฌํ๊ฒ ์ํ๋ฉ๋๋ค. ์์ ๋ง์ ๋ ผ๋ฆฌ๋ฅผ ์์ฑํ๊ณ ์คํธ๋ฆผ ๊ฐ์ ์ ํํ ์ ์๋ ์์น๋ฅผ ์๋ ค์ฃผ์ธ์.
์ ์ ์ ๋ฉํฐํ์คํน๊ณผ ๊ฒฝ์์ ๋ฉํฐํ์คํน์ ์ฐจ์ด์ ์ ์ ํ ๊ณผ๋ชฉ์ผ๋ก ๊ณต๋ถํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด์ ๋ง์ง๋ง์ผ๋ก ์ฝ๋๋ก ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
#####################################
# Counter class - implements a single water counter on specified pin
#####################################
class Counter():
debounce_ms = const(25)
def __init__(self, pin_num, value_storage):
self._value_storage = value_storage
self._value = self._value_storage.read()
self._value_changed = False
self._pin = Pin(pin_num, Pin.IN, Pin.PULL_UP)
loop = asyncio.get_event_loop()
loop.create_task(self._switchcheck()) # Thread runs forever
๊ฐ ์นด์ดํฐ๋ Counter ํด๋์ค์ ์ธ์คํด์ค์ ์ํด ์ฒ๋ฆฌ๋ฉ๋๋ค. ๋จผ์ EEPROM(value_storage)์์ ์ด๊ธฐ ์นด์ดํฐ ๊ฐ์ ๋บ๋๋ค. ์ด๊ฒ์ด ์ ์ ํ ๋ณต๊ตฌ๊ฐ ๊ตฌํ๋๋ ๋ฐฉ๋ฒ์ ๋๋ค.
ํ์ ์ ์ ๊ณต๊ธ ์ฅ์น์ ๋ด์ฅ๋ ํ์ ์ผ๋ก ์ด๊ธฐํ๋ฉ๋๋ค. ๋ฆฌ๋ ์ค์์น๊ฐ ๋ซํ ์์ผ๋ฉด ๋ผ์ธ์ด 0์ด๊ณ , ๋ผ์ธ์ด ์ด๋ ค ์์ผ๋ฉด ์ ์ ๊ณต๊ธ ์ฅ์น๋ก ํ์ ๋๊ณ ์ปจํธ๋กค๋ฌ๊ฐ 1์ ์ฝ์ต๋๋ค.
ํ์ ํด๋งํ๋ ๋ณ๋์ ์์ ๋ ์ฌ๊ธฐ์์ ์์๋ฉ๋๋ค. ๊ฐ ์นด์ดํฐ๋ ์์ฒด ์์ ์ ์คํํฉ๋๋ค. ๊ทธ๋ ์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
""" Poll pin and advance value when another litre passed """
async def _switchcheck(self):
last_checked_pin_state = self._pin.value() # Get initial state
# Poll for a pin change
while True:
state = self._pin.value()
if state != last_checked_pin_state:
# State has changed: act on it now.
last_checked_pin_state = state
if state == 0:
self._another_litre_passed()
# Ignore further state changes until switch has settled
await asyncio.sleep_ms(Counter.debounce_ms)
์ ์ด ๋ฐ์ด์ค๋ฅผ ํํฐ๋งํ๋ ค๋ฉด 25ms์ ์ง์ฐ์ด ํ์ํ๋ฉฐ ๋์์ ์์ ์ด ๊นจ์ด๋๋ ๋น๋๋ฅผ ์กฐ์ ํฉ๋๋ค(์ด ์์ ์ด ์ ์ ๋ชจ๋์ธ ๋์ ๋ค๋ฅธ ์์ ์ด ์คํ ์ค์). 25ms๋ง๋ค ๊ธฐ๋ฅ์ด ํ์ฑํ๋์ด ํ์ ํ์ธํ๊ณ ๋ฆฌ๋ ์ค์์น ์ ์ ์ด ๋ซํ ์์ผ๋ฉด ๋ ๋ค๋ฅธ ๋ฆฌํฐ๊ฐ ๋ฏธํฐ๋ฅผ ํต๊ณผํ๋ฏ๋ก ์ด๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
def _another_litre_passed(self):
self._value += 1
self._value_changed = True
self._value_storage.write(self._value)
๋ค์ ๋ฆฌํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๊ฐ๋จํฉ๋๋ค. ์นด์ดํฐ๋ ๋จ์ํ ์ฆ๊ฐํฉ๋๋ค. ๊ธ์, ์๋ก์ด ๊ฐ์ ํ๋์ ๋๋ผ์ด๋ธ์ ์ฐ๋ ๊ฒ์ด ์ข์ ๊ฒ์ ๋๋ค.
์ฌ์ฉ์ ํธ์๋ฅผ ์ํด "์ ์์"๊ฐ ์ ๊ณต๋ฉ๋๋ค.
def value(self):
self._value_changed = False
return self._value
def set_value(self, value):
self._value = value
self._value_changed = False
์, ์ด์ Python๊ณผ uasync ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฅ์ ์ ํ์ฉํ๊ณ ๋๊ธฐ ๊ฐ๋ฅํ ์นด์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. (์ด๊ฒ์ ๋ฌ์์์ด๋ก ์ด๋ป๊ฒ ๋ฒ์ญํ ์ ์์ต๋๊น? ๊ธฐ๋ํ ์ ์๋ ๊ฐ์ฒด์ ๋๊น?)
def __await__(self):
while not self._value_changed:
yield from asyncio.sleep(0)
return self.value()
__iter__ = __await__
์ด๊ฒ์ ์นด์ดํฐ ๊ฐ์ด ์ ๋ฐ์ดํธ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋งค์ฐ ํธ๋ฆฌํ ํจ์์ ๋๋ค. ํจ์๋ ๋๋๋ก ๊นจ์ด๋์ _value_changed ํ๋๊ทธ๋ฅผ ํ์ธํฉ๋๋ค. ์ด ํจ์์ ๋ฉ์ง ์ ์ ํธ์ถ ์ฝ๋๊ฐ ์ด ํจ์๋ฅผ ํธ์ถํ๋ ๋์ ์ ๋ค๊ณ ์ ๊ฐ์ด ์์ ๋ ๋๊น์ง ์ ๋ค ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
๋ฐฉํด๋ ์ด๋ป๊ฒ ๋๋์?์, ์ด ์์ ์์ ๋น์ ์ ๋ฐฉํด์ ๋ํด ์ค์ค๋ก ๋งํ๋ค๊ณ ๋งํ๋ฉด์ ๋๋ฅผ ํธ๋กค๋งํ ์ ์์ง๋ง ์ค์ ๋ก๋ ์ด๋ฆฌ์์ ํ ํฌํ๋ฅผ ํ์ต๋๋ค. ์ค์ ๋ก ์ธํฐ๋ฝํธ๋ ์ ๊ฐ ์ฒ์ ์๋ํ ๊ฒ์ ๋๋ค. ESP8266์์๋ ์์ง ์ธํฐ๋ฝํธ๋ฅผ ๊ตฌ์ฑํ๊ณ Python์์ ์ด ์ธํฐ๋ฝํธ์ ๋ํ ํธ๋ค๋ฌ๋ฅผ ์์ฑํ ์๋ ์์ต๋๋ค. ์ด ์ธํฐ๋ฝํธ์์๋ ๋ณ์ ๊ฐ์ด ์ ๋ฐ์ดํธ๋ ์ ์์ต๋๋ค. ์๋ง๋ ์นด์ดํฐ๊ฐ ์ด ๊ฐ์ ์์ฒญํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ์ฌ๋ ์ด๋ธ ์ฅ์น๋ผ๋ฉด ์ด ์ ๋๋ฉด ์ถฉ๋ถํ ๊ฒ์ ๋๋ค.
๋ถํํ๊ฒ๋(ํน์ ๋คํ์ค๋ฝ๊ฒ๋) ๋ด ์ฅ์น๊ฐ ํ์ฑ ์ํ์ด๋ฏ๋ก ์์ฒด์ ์ผ๋ก MQTT ํ๋กํ ์ฝ์ ํตํด ๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ณ EEPROM์ ๋ฐ์ดํฐ๋ฅผ ์จ์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์์ ์ ํ ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค. ์ธํฐ๋ฝํธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ณ ํฐ ์คํ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฆ, ๋คํธ์ํฌ๋ฅผ ํตํด ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ๊ฒ์ ์์ ์ ์์ต๋๋ค. "๊ฐ๋ฅํ ํ ๋นจ๋ฆฌ" ์ผ๋ถ ๊ธฐ๋ฅ์ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ micropython.schedule()๊ณผ ๊ฐ์ ๋นต์ด ์์ง๋ง "๋ฌด์์ด ์ค์ํ๊ฐ?"๋ผ๋ ์ง๋ฌธ์ด ์๊น๋๋ค. ์ง๊ธ ์ด๋ค ์ข ๋ฅ์ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ณ ์๋๋ฐ ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ์ฌ ๋ณ์์ ๊ฐ์ ๋ง์น๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ๋๋ ์๋ฅผ ๋ค์ด ์ด์ ๊ฐ์ ์์ง ๊ธฐ๋กํ์ง ์์ ์ํ์์ ์๋ฒ์์ ์ ์นด์ดํฐ ๊ฐ์ด ๋์ฐฉํ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋๊ธฐํ๋ฅผ ์ฐจ๋จํ๊ฑฐ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ๋น ์ ธ๋์์ผ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋๋ก RuntimeError: ์ค์ผ์ค ์คํ ์ ์ฒด ์ถฉ๋์ด ๋ฐ์ํ๋๋ฐ ๊ทธ ์ด์ ๋ฅผ ๋๊ฐ ์๊ฒ ์ต๋๊น?
๋ช ์์ ํด๋ง๊ณผ uasync๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ๊ฒฝ์ฐ ์ด๋ป๊ฒ๋ ๋ ์๋ฆ๋ต๊ณ ์ ๋ขฐํ ์ ์๋ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค.
EEPROM์ ์ฌ์ฉํ ์์ ์ ์๊ท๋ชจ ์์ ์ ๊ฐ์ ธ์์ต๋๋ค.
class EEPROM():
i2c_addr = const(80)
def __init__(self, i2c):
self.i2c = i2c
self.i2c_buf = bytearray(4) # Avoid creation/destruction of the buffer on each call
def read(self, eeprom_addr):
self.i2c.readfrom_mem_into(self.i2c_addr, eeprom_addr, self.i2c_buf, addrsize=16)
return ustruct.unpack_from("<I", self.i2c_buf)[0]
def write(self, eeprom_addr, value):
ustruct.pack_into("<I", self.i2c_buf, 0, value)
self.i2c.writeto_mem(self.i2c_addr, eeprom_addr, self.i2c_buf, addrsize=16)
Python์์๋ ๋ฐ์ดํธ๋ก ์ง์ ์์ ํ๊ธฐ๊ฐ ์ด๋ ต์ง๋ง ๋ฉ๋ชจ๋ฆฌ์ ๊ธฐ๋ก๋๋ ๊ฒ์ ๋ฐ์ดํธ์ ๋๋ค. ustruct ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ ์์ ๋ฐ์ดํธ ์ฌ์ด์ ๋ณํ์ ์ฐจ๋จํด์ผ ํ์ต๋๋ค.
I2C ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ ์ ์ ์ฃผ์๋ฅผ ๋งค๋ฒ ์ ์กํ์ง ์๊ธฐ ์ํด ์๊ณ ํธ๋ฆฌํ ํด๋์์ผ๋ก ๋ชจ๋ ์ ๋ฆฌํ์ต๋๋ค.
class EEPROMValue():
def __init__(self, i2c, eeprom_addr):
self._eeprom = EEPROM(i2c)
self._eeprom_addr = eeprom_addr
def read(self):
return self._eeprom.read(self._eeprom_addr)
def write(self, value):
self._eeprom.write(self._eeprom_addr, value)
I2C ๊ฐ์ฒด ์์ฒด๋ ๋ค์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋ฉ๋๋ค.
i2c = I2C(freq=400000, scl=Pin(5), sda=Pin(4))
๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๋ถ๋ถ์ธ MQTT๋ฅผ ํตํ ์๋ฒ์์ ํต์ ๊ตฌํ์ ์ด๋ฅด๋ ์ต๋๋ค. ๊ธ์, ํ๋กํ ์ฝ ์์ฒด๋ฅผ ๊ตฌํํ ํ์๋ ์์ต๋๋ค. ์ธํฐ๋ท์์ ์ฐพ์์ต๋๋ค. . ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๋ชจ๋ ์ฌํญ์ MQTTClient ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ CounterMQTTClient ํด๋์ค์ ์์ง๋์ด ์์ต๋๋ค. ์ฃผ๋ณ๋ถํฐ ์์ํ์
#####################################
# Class handles both counters and sends their status to MQTT
#####################################
class CounterMQTTClient(MQTTClient):
blue_led = Pin(2, Pin.OUT, value = 1)
button = Pin(0, Pin.IN)
hot_counter = Counter(12, EEPROMValue(i2c, EEPROM_ADDR_HOT_VALUE))
cold_counter = Counter(13, EEPROMValue(i2c, EEPROM_ADDR_COLD_VALUE))
์ฌ๊ธฐ์ ์ ๊ตฌ ํ๊ณผ ๋ฒํผ์ ๋ฌผ๋ก ๋์ ๋ฐ ์จ์ ๊ณ๋๊ธฐ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
์ด๊ธฐํ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ๊ฒ์ด ๊ทธ๋ ๊ฒ ์ฌ์ํ ๊ฒ์ ์๋๋๋ค.
def __init__(self):
self.internet_outage = True
self.internet_outages = 0
self.internet_outage_start = ticks_ms()
with open("config.txt") as config_file:
config['ssid'] = config_file.readline().rstrip()
config['wifi_pw'] = config_file.readline().rstrip()
config['server'] = config_file.readline().rstrip()
config['client_id'] = config_file.readline().rstrip()
self._mqtt_cold_water_theme = config_file.readline().rstrip()
self._mqtt_hot_water_theme = config_file.readline().rstrip()
self._mqtt_debug_water_theme = config_file.readline().rstrip()
config['subs_cb'] = self.mqtt_msg_handler
config['wifi_coro'] = self.wifi_connection_handler
config['connect_coro'] = self.mqtt_connection_handler
config['clean'] = False
config['clean_init'] = False
super().__init__(config)
loop = asyncio.get_event_loop()
loop.create_task(self._heartbeat())
loop.create_task(self._counter_coro(self.cold_counter, self._mqtt_cold_water_theme))
loop.create_task(self._counter_coro(self.hot_counter, self._mqtt_hot_water_theme))
loop.create_task(self._display_coro())
mqtt_as ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ ๋งค๊ฐ๋ณ์๋ฅผ ์ค์ ํ๋ ค๋ฉด ๋ค์ํ ์ค์ ์ด ํฌํจ๋ ๋๊ท๋ชจ ์ฌ์ ์ธ config๊ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋๋ถ๋ถ์ ๊ธฐ๋ณธ ์ค์ ์ ์ฐ๋ฆฌ์๊ฒ ์ ํฉํ์ง๋ง ๋ง์ ์ค์ ์ ๋ช ์์ ์ผ๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ์ฝ๋์ ์ง์ ์ค์ ์ ์ฐ์ง ์๊ธฐ ์ํด ํ ์คํธ ํ์ผ config.txt์ ์ ์ฅํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ค์ ์ ๊ด๊ณ์์ด ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ์ ์์ ๋ฟ๋ง ์๋๋ผ ์๋ก ๋ค๋ฅธ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ๋์ผํ ์ฅ์น๋ฅผ ๋ฆฌ๋ฒณํ ์ ์์ต๋๋ค.
๋ง์ง๋ง ์ฝ๋ ๋ธ๋ก์ ์์คํ ์ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ธฐ ์ํด ์ฌ๋ฌ ์ฝ๋ฃจํด์ ์์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์์ ์นด์ดํฐ๋ฅผ ์๋น์คํ๋ ์ฝ๋ฃจํด์ ๋๋ค.
async def _counter_coro(self, counter, topic):
# Publish initial value
value = counter.value()
await self.publish(topic, str(value))
# Publish each new value
while True:
value = await counter
await self.publish_msg(topic, str(value))
์ฝ๋ฃจํด์ ๋ฃจํ์์ ์ ์นด์ดํฐ ๊ฐ์ ๊ธฐ๋ค๋ฆฌ๊ณ ๊ฐ์ด ํ์๋์๋ง์ MQTT ํ๋กํ ์ฝ์ ํตํด ๋ฉ์์ง๋ฅผ ๋ณด๋ ๋๋ค. ์ฒซ ๋ฒ์งธ ์ฝ๋ ์กฐ๊ฐ์ ์นด์ดํฐ๋ฅผ ํตํด ๋ฌผ์ด ํ๋ฅด์ง ์๋๋ผ๋ ์ด๊ธฐ ๊ฐ์ ๋ณด๋ ๋๋ค.
๊ธฐ๋ณธ ํด๋์ค MQTTClient๋ ์์ฒด์ ์ผ๋ก ์๋น์ค๋ฅผ ์ ๊ณตํ๊ณ WiFi ์ฐ๊ฒฐ์ ์์ํ๊ณ ์ฐ๊ฒฐ์ด ๋์ด์ง๋ฉด ๋ค์ ์ฐ๊ฒฐํฉ๋๋ค. WiFi ์ฐ๊ฒฐ ์ํ์ ๋ณํ๊ฐ ์์ผ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ wifi_connection_handler๋ฅผ ํธ์ถํ์ฌ ์ด๋ฅผ ์๋ ค์ค๋๋ค.
async def wifi_connection_handler(self, state):
self.internet_outage = not state
if state:
self.dprint('WiFi is up.')
duration = ticks_diff(ticks_ms(), self.internet_outage_start) // 1000
await self.publish_debug_msg('ReconnectedAfter', duration)
else:
self.internet_outages += 1
self.internet_outage_start = ticks_ms()
self.dprint('WiFi is down.')
await asyncio.sleep(0)
์ด ๊ธฐ๋ฅ์ ์์ ์์ ์ ์งํ๊ฒ ๋ณต์ฌ๋์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ์ค๋จ ํ์(internet_outages)์ ๊ธฐ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. ์ฐ๊ฒฐ์ด ๋ณต์๋๋ฉด ์ ํด ์๊ฐ์ด ์๋ฒ๋ก ์ ์ก๋ฉ๋๋ค.
๊ทธ๊ฑด ๊ทธ๋ ๊ณ , ๋ง์ง๋ง ์ ์ ๋ชจ๋๋ ํจ์๋ฅผ ๋น๋๊ธฐ์์ผ๋ก ๋ง๋๋ ๋ฐ๋ง ํ์ํฉ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์๋ ๋๊ธฐ๋ฅผ ํตํด ํธ์ถ๋๋ฉฐ ๋ณธ๋ฌธ์ ๋ค๋ฅธ ๋๊ธฐ๊ฐ ํฌํจ๋ ํจ์๋ง ํธ์ถํ ์ ์์ต๋๋ค.
WiFi ์ฐ๊ฒฐ ์ธ์๋ MQTT ๋ธ๋ก์ปค(์๋ฒ)์ ๋ํ ์ฐ๊ฒฐ๋ ์ค์ ํด์ผ ํฉ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด ์์ ์ ์ํํ๋ฉฐ ์ฐ๊ฒฐ์ด ์ค์ ๋๋ฉด ์ ์ฉํ ์์ ์ ์ํํ ์ ์๋ ๊ธฐํ๋ฅผ ์ป์ต๋๋ค.
async def mqtt_connection_handler(self, client):
await client.subscribe(self._mqtt_cold_water_theme)
await client.subscribe(self._mqtt_hot_water_theme)
์ฌ๊ธฐ์๋ ์ฌ๋ฌ ๋ฉ์์ง๋ฅผ ๊ตฌ๋ ํฉ๋๋ค. ์ด์ ์๋ฒ๋ ํด๋น ๋ฉ์์ง๋ฅผ ์ ์กํ์ฌ ํ์ฌ ์นด์ดํฐ ๊ฐ์ ์ค์ ํ ์ ์์ต๋๋ค.
def mqtt_msg_handler(self, topic, msg):
topicstr = str(topic, 'utf8')
self.dprint("Received MQTT message topic={}, msg={}".format(topicstr, msg))
if topicstr == self._mqtt_cold_water_theme:
self.cold_counter.set_value(int(msg))
if topicstr == self._mqtt_hot_water_theme:
self.hot_counter.set_value(int(msg))
๋ค์ด์ค๋ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๋ฉฐ, ์ฃผ์ (๋ฉ์์ง ์ ๋ชฉ)์ ๋ฐ๋ผ ์นด์ดํฐ ์ค ํ๋์ ๊ฐ์ ์ ๋ฐ์ดํธํ๋ ๊ธฐ๋ฅ์ ๋๋ค.
๋ช ๊ฐ์ง ๋์ฐ๋ฏธ ๊ธฐ๋ฅ
# Publish a message if WiFi and broker is up, else discard
async def publish_msg(self, topic, msg):
self.dprint("Publishing message on topic {}: {}".format(topic, msg))
if not self.internet_outage:
await self.publish(topic, msg)
else:
self.dprint("Message was not published - no internet connection")
์ด ํจ์๋ ์ฐ๊ฒฐ์ด ์ค์ ๋๋ฉด ๋ฉ์์ง๋ฅผ ๋ณด๋ ๋๋ค. ์ฐ๊ฒฐ์ด ์์ผ๋ฉด ๋ฉ์์ง๊ฐ ๋ฌด์๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ ๋๋ฒ๊น ๋ฉ์์ง๋ฅผ ์์ฑํ๊ณ ์ ์กํ๋ ํธ๋ฆฌํ ๊ธฐ๋ฅ์ผ ๋ฟ์ ๋๋ค.
async def publish_debug_msg(self, subtopic, msg):
await self.publish_msg("{}/{}".format(self._mqtt_debug_water_theme, subtopic), str(msg))
ํ ์คํธ๊ฐ ๋๋ฌด ๋ง์์ ์์ง LED๋ฅผ ๊น๋ฐ์ด์ง ์์์ต๋๋ค. ์ฌ๊ธฐ
# Blink flash LED if WiFi down
async def _heartbeat(self):
while True:
if self.internet_outage:
self.blue_led(not self.blue_led()) # Fast blinking if no connection
await asyncio.sleep_ms(200)
else:
self.blue_led(0) # Rare blinking when connected
await asyncio.sleep_ms(50)
self.blue_led(1)
await asyncio.sleep_ms(5000)
2๊ฐ์ง ๊น๋ฐ์ ๋ชจ๋๋ฅผ ์ ๊ณตํ์ต๋๋ค. ์ฐ๊ฒฐ์ด ๋์ด์ง๋ฉด(๋๋ ์ฐ๊ฒฐ์ด ๋ง ์ค์ ๋๋ ์ค) ์ฅ์น๊ฐ ๋น ๋ฅด๊ฒ ๊น๋ฐ์ ๋๋ค. ์ฐ๊ฒฐ์ด ์๋ฃ๋๋ฉด ์ฅ์น๊ฐ 5์ด๋ง๋ค ํ ๋ฒ์ฉ ๊น๋ฐ์ ๋๋ค. ํ์ํ ๊ฒฝ์ฐ ์ฌ๊ธฐ์์ ๋ค๋ฅธ ๊น๋ฐ์ ๋ชจ๋๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ LED๋ ๋จ์ง ์ ์ง์ค์งํฉ๋๋ค. ๋์คํ๋ ์ด๋ ๋ชฉํ๋ก ์ผ์์ต๋๋ค.
async def _display_coro(self):
display = SSD1306_I2C(128,32, i2c)
while True:
display.poweron()
display.fill(0)
display.text("COLD: {:.3f}".format(self.cold_counter.value() / 1000), 16, 4)
display.text("HOT: {:.3f}".format(self.hot_counter.value() / 1000), 16, 20)
display.show()
await asyncio.sleep(3)
display.poweroff()
while self.button():
await asyncio.sleep_ms(20)
์ด๊ฒ์ด ์ ๊ฐ ๋งํ๊ณ ์ ํ๋ ๊ฒ์ ๋๋ค. ์ฝ๋ฃจํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ง๋ ๊ฐ๋จํ๊ณ ํธ๋ฆฌํ์ง์ ๋๋ค. ์ด ์์ ๊ธฐ๋ฅ์ ์ ์ฒด ์ฌ์ฉ์ ๊ฒฝํ์ ์ค๋ช ํฉ๋๋ค. ์ฝ๋ฃจํด์ ๋ฒํผ์ด ๋๋ฆด ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ 3์ด ๋์ ๋์คํ๋ ์ด๋ฅผ ์ผญ๋๋ค. ๋์คํ๋ ์ด์๋ ํ์ฌ ๋ฏธํฐ ํ๋ ๊ฐ์ด ํ์๋ฉ๋๋ค.
์์ง ๋ช ๊ฐ์ง ์์ ๊ฒ๋ค์ด ๋จ์ ์์ต๋๋ค. ์ด ์ ์ฒด ๊ธฐ์ ์ (์ฌ)์์ํ๋ ๊ธฐ๋ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๋ฉ์ธ ๋ฃจํ๋ 1๋ถ์ ํ ๋ฒ์ฉ ๋ค์ํ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ๋ณด๋ ๋๋ค. ๋์ฒด์ ์ผ๋ก๋ ์๋ ๊ทธ๋๋ก ์ธ์ฉํฉ๋๋ค. ๋๋ฌด ๊ธธ๊ฒ ์ฝ๋ฉํธํ ํ์๋ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
async def main(self):
while True:
try:
await self._connect_to_WiFi()
await self._run_main_loop()
except Exception as e:
self.dprint('Global communication failure: ', e)
await asyncio.sleep(20)
async def _connect_to_WiFi(self):
self.dprint('Connecting to WiFi and MQTT')
sta_if = network.WLAN(network.STA_IF)
sta_if.connect(config['ssid'], config['wifi_pw'])
conn = False
while not conn:
await self.connect()
conn = True
self.dprint('Connected!')
self.internet_outage = False
async def _run_main_loop(self):
# Loop forever
mins = 0
while True:
gc.collect() # For RAM stats.
mem_free = gc.mem_free()
mem_alloc = gc.mem_alloc()
try:
await self.publish_debug_msg("Uptime", mins)
await self.publish_debug_msg("Repubs", self.REPUB_COUNT)
await self.publish_debug_msg("Outages", self.internet_outages)
await self.publish_debug_msg("MemFree", mem_free)
await self.publish_debug_msg("MemAlloc", mem_alloc)
except Exception as e:
self.dprint("Exception occurred: ", e)
mins += 1
await asyncio.sleep(60)
์ค๋ช ์ ์์ฑํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ์ค์ ๊ณผ ์์๊ฐ ๋ ์์ต๋๋ค.
#####################################
# Constants and configuration
#####################################
config['keepalive'] = 60
config['clean'] = False
config['will'] = ('/ESP/Wemos/Water/LastWill', 'Goodbye cruel world!', False, 0)
MQTTClient.DEBUG = True
EEPROM_ADDR_HOT_VALUE = const(0)
EEPROM_ADDR_COLD_VALUE = const(4)
๋ชจ๋ ๊ฒ์ ์ด๋ ๊ฒ ์์๋๋ค
client = CounterMQTTClient()
loop = asyncio.get_event_loop()
loop.run_until_complete(client.main())
๋ด ๊ธฐ์ต์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋ฌ์ด
๊ทธ๋ผ ๋ชจ๋ ์ฝ๋๊ฐ ๊ฑฐ๊ธฐ์ ์์ต๋๋ค. ๋๋ ampy ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ์ ๋ก๋ํ์ต๋๋ค. ์ด ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ํ์ผ์ ๋ด๋ถ(ESP-07 ์์ฒด์ ์๋ ํ๋์ ๋๋ผ์ด๋ธ) ํ๋์ ๋๋ผ์ด๋ธ์ ์ ๋ก๋ํ ๋ค์ ํ๋ก๊ทธ๋จ์์ ์ผ๋ฐ ํ์ผ๋ก ์ก์ธ์คํ ์ ์์ต๋๋ค. ๋ํ mqtt_as, uasyncio, ssd1306 ๋ฐ ๋ด๊ฐ ์ฌ์ฉํ ์ปฌ๋ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(mqtt_as ๋ด๋ถ์์ ์ฌ์ฉ๋จ)๋ฅผ ์ ๋ก๋ํ์ต๋๋ค.
์คํํ๊ณ ... MemoryError๊ฐ ๋ฐ์ํฉ๋๋ค. ๋์ฑ์ด, ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ํํ ์ด๋์์ ๋์๋๊ณ ์๋์ง ์ดํดํ๋ ค๊ณ ๋ ธ๋ ฅํ ์๋ก ๋ ๋ง์ ๋๋ฒ๊ทธ ์ธ์๋ฅผ ๋ฐฐ์นํ ์๋ก ์ด ์ค๋ฅ๊ฐ ๋ ์ผ์ฐ ๋ํ๋ฌ์ต๋๋ค. ์งง์ Google ๊ฒ์์ ํตํด ๋ง์ดํฌ๋ก ์ปจํธ๋กค๋ฌ์๋ ์์น์ ์ผ๋ก 30kB์ ๋ฉ๋ชจ๋ฆฌ๋ง ์๊ณ 65kB์ ์ฝ๋(๋ผ์ด๋ธ๋ฌ๋ฆฌ ํฌํจ)๋ ๋ค์ด๊ฐ ์ ์๋ค๋ ์ฌ์ค์ ์๊ฒ ๋์์ต๋๋ค.
๊ทธ๋ฌ๋ ํ์ถ๊ตฌ๊ฐ ์์ต๋๋ค. micropython์ .py ํ์ผ์์ ์ง์ ์ฝ๋๋ฅผ ์คํํ์ง ์๋ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ์ด ํ์ผ์ด ๋จผ์ ์ปดํ์ผ๋ฉ๋๋ค. ๋ํ ๋ง์ดํฌ๋ก์ปจํธ๋กค๋ฌ์์ ์ง์ ์ปดํ์ผ๋์ด ๋ฐ์ดํธ์ฝ๋๋ก ๋ณํ๋ ํ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ฉ๋๋ค. ๊ธ์, ์ปดํ์ผ๋ฌ๊ฐ ์๋ํ๋ ค๋ฉด ์ผ์ ๋์ RAM๋ ํ์ํฉ๋๋ค.
๋น๊ฒฐ์ ๋ฆฌ์์ค ์ง์ฝ์ ์ธ ์ปดํ์ผ๋ก๋ถํฐ ๋ง์ดํฌ๋ก์ปจํธ๋กค๋ฌ๋ฅผ ์ ์ฅํ๋ ๊ฒ์ ๋๋ค. ๋ํ ์ปดํจํฐ์์ ํ์ผ์ ์ปดํ์ผํ๊ณ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง ๋ฐ์ดํธ์ฝ๋๋ฅผ ๋ง์ดํฌ๋ก์ปจํธ๋กค๋ฌ์ ์ ๋ก๋ํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด micropython ํ์จ์ด๋ฅผ ๋ค์ด๋ก๋ํ๊ณ ๋น๋ํด์ผ ํฉ๋๋ค. .
์ ๋ Makefile์ ์์ฑํ์ง ์๊ณ ๋ค์๊ณผ ๊ฐ์ด ํ์ํ ๋ชจ๋ ํ์ผ(๋ผ์ด๋ธ๋ฌ๋ฆฌ ํฌํจ)์ ์๋์ผ๋ก ์ดํด๋ณด๊ณ ์ปดํ์ผํ์ต๋๋ค.
mpy-cross water_counter.py
๋จ์ ๊ฒ์ .mpy ํ์ฅ์๋ฅผ ๊ฐ์ง ํ์ผ์ ์ ๋ก๋ํ๋ ๊ฒ๋ฟ์ ๋๋ค. ๋จผ์ ์ฅ์น์ ํ์ผ ์์คํ ์์ ํด๋น .py๋ฅผ ์ญ์ ํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค.
์ ๋ ๋ชจ๋ ๊ฐ๋ฐ์ ํ๋ก๊ทธ๋จ(IDE?) ESPlorer์์ ํ์ต๋๋ค. ์ด๋ฅผ ํตํด ์คํฌ๋ฆฝํธ๋ฅผ ๋ง์ดํฌ๋ก์ปจํธ๋กค๋ฌ์ ์ ๋ก๋ํ๊ณ ์ฆ์ ์คํํ ์ ์์ต๋๋ค. ์ ๊ฒฝ์ฐ์๋ ๋ชจ๋ ๊ฐ์ฒด์ ๋ชจ๋ ๋ก์ง๊ณผ ์์ฑ์ด water_counter.py(.mpy) ํ์ผ์ ์์ต๋๋ค. ํ์ง๋ง ์ด ๋ชจ๋ ๊ฒ์ด ์๋์ผ๋ก ์์๋๋ ค๋ฉด ์์ ์ main.py๋ผ๋ ํ์ผ๋ ์์ด์ผ ํฉ๋๋ค. ๋ํ ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ .mpy๊ฐ ์๋ ์ ํํ .py์ฌ์ผ ํฉ๋๋ค. ์ฌ์ํ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
import water_counter
์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์์ํฉ๋๋ค - ๋ชจ๋ ๊ฒ์ด ์๋ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ โโ๋ฉ๋ชจ๋ฆฌ๋ ๋๋ผ์ธ ์ ๋๋ก ์์ต๋๋ค(์ฝ 1kb). ์์ง ์ฅ์น์ ๊ธฐ๋ฅ์ ํ์ฅํ ๊ณํ์ด ์๋๋ฐ ์ด ํฌ๋ก๋ฐ์ดํธ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ํ์ง๋ง ์ด ๊ฒฝ์ฐ์๋ ํ์ถ๊ตฌ๊ฐ ์๋ค๋ ๊ฒ์ด ๋ฐํ์ก์ต๋๋ค.
์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ํ์ผ์ด ๋ฐ์ดํธ์ฝ๋๋ก ์ปดํ์ผ๋์ด ๋ด๋ถ ํ์ผ ์์คํ ์ ์์ฃผํ๋๋ผ๋ ์ค์ ๋ก๋ ์ฌ์ ํ RAM์ ๋ก๋๋์ด ๊ฑฐ๊ธฐ์์ ์คํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ micropython์ ํ๋์ ๋ฉ๋ชจ๋ฆฌ์์ ์ง์ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์คํํ ์ ์์ง๋ง ์ด๋ฅผ ์ํด์๋ ํ์จ์ด์ ์ง์ ๋น๋ํด์ผ ํฉ๋๋ค. ๋ด ๋ท๋ถ์์๋ ๊ฝค ์๊ฐ์ด ๊ฑธ๋ ธ์ง๋ง ์ด๋ ต์ง๋ ์์ต๋๋ค(๊ทธ๊ณณ์์๋ง Linux๋ฅผ ์ฌ์ฉํ๊ฒ ๋์์ต๋๋ค).
์๊ณ ๋ฆฌ์ฆ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๋ค์ด๋ก๋ ๋ฐ ์ค์น . ์ด๊ฒ์ ESP8266์ฉ ํ๋ก๊ทธ๋จ์ฉ ์ปดํ์ผ๋ฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์กฐ๋ฆฝํ๋ ๊ฒ์ ๋๋ค. ํ๋ก์ ํธ ๋ฉ์ธ ํ์ด์ง์ ์ง์นจ์ ๋ฐ๋ผ ์ด์ ๋ธํ์ต๋๋ค(์ ๋ STANDALONE=yes ์ค์ ์ ์ ํํ์ต๋๋ค).
- ๋ค์ด๋ก๋
- micropython ํธ๋ฆฌ ๋ด๋ถ์ ports/esp8266/modules์ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฐฐ์นํ์ธ์.
- ํ์ผ์ ์ง์นจ์ ๋ฐ๋ผ ํ์จ์ด๋ฅผ ์กฐ๋ฆฝํฉ๋๋ค.
- ํ์จ์ด๋ฅผ ๋ง์ดํฌ๋ก์ปจํธ๋กค๋ฌ์ ์ ๋ก๋ํฉ๋๋ค(Windows์์๋ ESP8266Flasher ํ๋ก๊ทธ๋จ ๋๋ Python esptool์ ์ฌ์ฉํ์ฌ ์ด ์์ ์ ์ํํฉ๋๋ค).
์ด์ 'import ssd1306'์ด ํ์จ์ด์์ ์ง์ ์ฝ๋๋ฅผ ๋ค์ด์ฌ๋ฆฌ๋ฉฐ ์ด๋ฅผ ์ํด RAM์ด ์๋น๋์ง ์์ต๋๋ค. ์ด ํธ๋ฆญ์ ์ฌ์ฉํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฝ๋๋ง ํ์จ์ด์ ์ ๋ก๋ํ๊ณ ๊ธฐ๋ณธ ํ๋ก๊ทธ๋จ ์ฝ๋๋ ํ์ผ ์์คํ ์์ ์คํ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ํ์จ์ด๋ฅผ ๋ค์ ์ปดํ์ผํ์ง ์๊ณ ๋ ํ๋ก๊ทธ๋จ์ ์ฝ๊ฒ ์์ ํ ์ ์์ต๋๋ค. ํ์ฌ ์ฝ 8.5kb์ ์ฌ์ RAM์ด ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฐ๋ฆฌ๋ ์์ผ๋ก ๋งค์ฐ ๋ค์ํ๊ณ ์ ์ฉํ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๊ฒ ๋ ๊ฒ์ ๋๋ค. ๊ธ์, ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ํ ์ถฉ๋ถํ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ ํ๋ก๊ทธ๋จ์ ํ์จ์ด์ ํธ์ํ ์ ์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด์ ์ฐ๋ฆฌ๋ ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
์ข์, ํ๋์จ์ด๊ฐ ๋ฉ๋๋๊ณ , ํ์จ์ด๊ฐ ์์ฑ๋๊ณ , ์์๊ฐ ์ธ์๋๊ณ , ์ฅ์น๊ฐ ๋ฒฝ์ ๋ถ์ด์ ํ๋ณตํ๊ฒ ์ ๊ตฌ๋ฅผ ๊น๋ฐ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ง๊ธ์ ์ด ๋ชจ๋ ๊ฒ์ด ๋ฌธ์ ๊ทธ๋๋ก๋ ๋น์ ์ ์ผ๋ก๋ ๋ชจ๋ ๋ธ๋๋ฐ์ค์ผ ๋ฟ์ด๋ฉฐ ์ฌ์ ํ ๊ฑฐ์ ์ธ๋ชจ๊ฐ ์์ต๋๋ค. ์ด์ ์๋ฒ๋ก ์ ์ก๋๋ MQTT ๋ฉ์์ง๋ก ์์ ์ ์ํํ ์๊ฐ์ ๋๋ค.
๋ด '์ค๋งํธ ํ'์ด ๋์๊ฐ๊ณ ์์ด์ . MQTT ๋ชจ๋์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๊ฑฐ๋ ์ถ๊ฐ ๊ธฐ๋ฅ ์์ฅ์์ ์ฝ๊ฒ ์ค์น๋ฉ๋๋ค. ์ด๋์ ์ป์๋์ง ๊ธฐ์ต์ด ๋์ง ์์ต๋๋ค. MQTT๋ ์๊ธ์์กฑ์ด ์๋๋๋ค. ์์ ๋งํ๋ ๊ฒ์ด ํ์ํฉ๋๋ค. ๋ธ๋ก์ปค - MQTT ๋ฉ์์ง๋ฅผ ์์ ํ๊ณ ์ ๋ ฌํ์ฌ ํด๋ผ์ด์ธํธ์ ์ ๋ฌํ๋ ์๋ฒ์ ๋๋ค. ์ ๋ (majordomo์ ๋ง์ฐฌ๊ฐ์ง๋ก) ๋์ผํ ๋ท๋ถ์์ ์คํ๋๋ ๋ชจ๊ธฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ฅ์น๊ฐ ๋ฉ์์ง๋ฅผ ํ ๋ฒ ์ด์ ์ ์กํ๋ฉด ํด๋น ๊ฐ์ด ์ฆ์ ๋ชฉ๋ก์ ๋ํ๋ฉ๋๋ค.

์ด๋ฌํ ๊ฐ์ ์ด์ ์์คํ
๊ฐ์ฒด์ ์ฐ๊ฒฐ๋ ์ ์์ผ๋ฉฐ, ์๋ํ ์คํฌ๋ฆฝํธ์ ์ฌ์ฉ๋ ์ ์์ผ๋ฉฐ ๋ค์ํ ๋ถ์์ด ๊ฐ๋ฅํฉ๋๋ค. ์ด ๋ชจ๋ ๋ด์ฉ์ ์ด ๊ธฐ์ฌ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค. ๊ด์ฌ ์๋ ๋๊ตฌ์๊ฒ๋ majordomo ์์คํ
์ ์ถ์ฒํ ์ ์์ต๋๋ค. โ ์น๊ตฌ๋ ์ค๋งํธ ํ์ ๊ตฌ์ถํ๊ณ ์์ผ๋ฉฐ ์์คํ
์ค์ ์ ๋ํด ๋ช
ํํ๊ฒ ์ด์ผ๊ธฐํฉ๋๋ค.
๋ช ๊ฐ์ง ๊ทธ๋ํ๋ฅผ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค. ์ด๊ฒ์ ์ผ์ผ ๊ฐ์น์ ๊ฐ๋จํ ๊ทธ๋ํ์ ๋๋ค.

๋ฐค์๋ ๋ฌผ์ ์ฌ์ฉํ๋ ์ฌ๋์ด ๊ฑฐ์ ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋ช ๋ฒ ๋๊ตฐ๊ฐ ํ์ฅ์ค์ ๊ฐ๋๋ฐ ์ญ์ผํฌ์ ํํฐ๊ฐ ํ๋ฃป๋ฐค์ ๋ช ๋ฆฌํฐ๋ฅผ ๋นจ์๋ค์ด๋ ๊ฒ ๊ฐ์ต๋๋ค. ์์นจ์๋ ์๋น๊ฐ ํฌ๊ฒ ์ฆ๊ฐํฉ๋๋ค. ์ ๋ ๋ณดํต ๋ณด์ผ๋ฌ์ ๋ฌผ์ ์ฌ์ฉํ๋๋ฐ ๋ชฉ์์ ํ๊ณ ์ถ์ด์ ์ผ์์ ์ผ๋ก ๋์ ์จ์๋ก ์ ํํ์ต๋๋ค. ์ด๋ ํ๋จ ๊ทธ๋ํ์์๋ ๋ช
ํํ๊ฒ ํ์๋ฉ๋๋ค.
์ด ๊ทธ๋ํ๋ฅผ ํตํด ํ์ฅ์ค์ ๊ฐ๋ ค๋ฉด 6~7๋ฆฌํฐ, ์ค์๋ฅผ ํ๋ ค๋ฉด 20~30๋ฆฌํฐ, ์ค๊ฑฐ์ง๋ฅผ ํ๋ ค๋ฉด 20๋ฆฌํฐ ์ ๋, ๋ชฉ์์ ํ๋ ค๋ฉด 160๋ฆฌํฐ๊ฐ ํ์ํ๋ค๋ ์ฌ์ค์ ์๊ฒ ๋๋ค. ์ฐ๋ฆฌ ๊ฐ์กฑ์ ํ๋ฃจ์ ์ฝ 500~600๋ฆฌํฐ๋ฅผ ์๋นํฉ๋๋ค.
ํนํ ๊ถ๊ธํ์ ๋ถ๋ค์ ๊ฐ๋ณ ๊ฐ๋ณ ๊ธฐ๋ก์ ๋ณด์๋ฉด ๋ฉ๋๋ค.

์ฌ๊ธฐ์์ ๋๋ ์๋๊ผญ์ง๊ฐ ์ด๋ฆฌ๋ฉด ๋ฌผ์ด 1์ด๋น ์ฝ 5๋ฆฌํฐ์ ์๋๋ก ํ๋ฅธ๋ค๋ ๊ฒ์ ๋ฐฐ์ ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด๋ฐ ํํ์ ํต๊ณ๋ ๋ณด๊ธฐ์ ๊ทธ๋ฆฌ ํธ๋ฆฌํ์ง ์์ ์๋ ์์ต๋๋ค. Majordomo์๋ ์ผ๋ณ, ์ฃผ๋ณ, ์๋ณ ์๋น ์ฐจํธ๋ฅผ ๋ณผ ์ ์๋ ๊ธฐ๋ฅ๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ง๋ ๋จ์์ ์๋น ๊ทธ๋ํ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.

์ง๊ธ๊น์ง๋ ์ผ์ฃผ์ผ ๋์์ ๋ฐ์ดํฐ๋ง ๊ฐ์ง๊ณ ์์ต๋๋ค. ํ ๋ฌ ํ์๋ ์ด ๊ทธ๋ํ๊ฐ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ ๊ณตํ ๊ฒ์
๋๋ค. ๋งค์ผ ๋ณ๋์ ์ด์ด ํ์๋ฉ๋๋ค. ์๋์ผ๋ก ์
๋ ฅํ ๊ฐ(๊ฐ์ฅ ํฐ ์ด)์ ์กฐ์ ํ๋ฉด ๊ทธ๋ฆผ์ด ์ฝ๊ฐ ์์๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ด๊ฐ ์ฒซ ๋ฒ์งธ ๊ฐ์ ๊ฑฐ์ ํ๋ธ๋ณด๋ค ์ ๊ฒ ์๋ชป ์ค์ ํ๋์ง, ์๋๋ฉด ์ด๊ฒ์ด ํ์จ์ด์ ๋ฒ๊ทธ์ด๊ณ ๋ชจ๋ ๋ฆฌํฐ๊ฐ ๊ณ์ฐ๋์ง ์์๋์ง ์ฌ๋ถ๋ ์์ง ๋ช
ํํ์ง ์์ต๋๋ค. ์๊ฐ์ด ๋ ํ์ํฉ๋๋ค.
๊ทธ๋ํ ์์ฒด์๋ ์ฌ์ ํ ๋ง๋ฒ, ํ์ดํธ์์ฑ, ํ์ธํ ์ด ํ์ํฉ๋๋ค. ์๋ง๋ ๋๋ฒ๊น ๋ชฉ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์๋น ๊ทธ๋ํ๋ฅผ ์์ฑํ ์๋ ์์ต๋๋ค. ๊ฑฐ๊ธฐ์์ ๋ญ๊ฐ๊ฐ ๋์ถ๋๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํด์ ๋ง์ด์ฃ . ์๋ง๋ ์ธํฐ๋ท์ด ์์๋ ์๋๋ฅผ ์ด๋ป๊ฒ๋ ํ์ํ๊ฒ ๋ ๊ฒ์ ๋๋ค. ํ์ฌ๋ก์๋ ์ด ๋ชจ๋ ๊ฒ์ด ์์ด๋์ด ์์ค์ ์์ต๋๋ค.
๊ฒฐ๋ก
์ค๋ ๋ด ์ํํธ๋ ์กฐ๊ธ ๋ ๋๋ํด์ก์ต๋๋ค. ์ด๋ ๊ฒ ์์ ์ฅ์น๋ฅผ ์ฌ์ฉํ๋ฉด ์ง์์ ๋ฌผ ์๋น๋์ ๋ชจ๋ํฐ๋งํ๋ ๊ฒ์ด ๋ ํธ๋ฆฌํ ๊ฒ์ ๋๋ค. ์ด์ ์๋ โ๋ ํ ๋ฌ์ ๋ฌผ์ ๋ง์ด ์ผ๋คโ๊ณ ๋ถ๊ฐํ๋ค๋ฉด ์ด์ ๋ ๊ทธ ์์ธ์ ์ฐพ์ ์ ์๋ค.
์ด๋ค ์ฌ๋๋ค์ ๋ฏธํฐ ์์ฒด์์ 1๋ฏธํฐ ๋จ์ด์ง ๊ณณ์ ์๋ ํ๋ฉด์ ํ๋ ๊ฐ์ ๋ณด๋ ๊ฒ์ด ์ด์ํ๋ค๊ณ ์๊ฐํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ฆฌ ๋ฉ์ง ์์ ๋ฏธ๋์ ๋๋ ์ฌ๋ฌ ๊ฐ์ ๋ฌผ ๋ผ์ด์ ๊ฐ ์๊ณ ๊ณ๋๊ธฐ ์์ฒด๊ฐ ์ธต๊ณ์ฐธ์ ์์นํ ๊ฐ๋ฅ์ฑ์ด ๊ฐ์ฅ ๋์ ๋ค๋ฅธ ์ํํธ๋ก ์ด์ฌํ ๊ณํ์ ๋๋ค. ๋ฐ๋ผ์ ์๊ฒฉ ํ๋ ์ฅ์น๋ ๋งค์ฐ ์ ์ฉํ ๊ฒ์ ๋๋ค.
๋ํ ์ฅ์น์ ๊ธฐ๋ฅ์ ํ์ฅํ ๊ณํ์ ๋๋ค. ์ ๋ ์ด๋ฏธ ์ ๋ ๋ฐธ๋ธ๋ฅผ ๋ณด๊ณ ์์ต๋๋ค. ์ด์ ๋ณด์ผ๋ฌ๋ฅผ ์๋๋ฌผ๋ก ์ ํํ๋ ค๋ฉด ์ ๊ทผํ๊ธฐ ์ด๋ ค์ด ํ์์ ์๋๊ผญ์ง 3๊ฐ๋ฅผ ๋๋ ค์ผ ํฉ๋๋ค. ํด๋น ํ์๊ฐ ์๋ ํ๋์ ๋ฒํผ์ผ๋ก ์ด ์์ ์ ์ํํ๋ ๊ฒ์ด ํจ์ฌ ๋ ํธ๋ฆฌํ ๊ฒ์ ๋๋ค. ๋ฌผ๋ก ๋์ถ ๋ฐฉ์ง ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๊ธฐ์ฌ์์ ๋๋ ESP8266์ ๊ธฐ๋ฐ์ผ๋ก ํ ์ฅ์น ๋ฒ์ ์ ์ค๋ช ํ์ต๋๋ค. ์ ์๊ฐ์๋ ์ฝ๋ฃจํด์ ์ฌ์ฉํ๋ ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ๋ฒ์ ์ ๋ง์ดํฌ๋กํ์ด์ฌ ํ์จ์ด๋ฅผ ์๊ฐํด ๋์ต๋๋ค. ๊ฐ๋จํ๊ณ ํ๋ฅญํฉ๋๋ค. ์บ ํ์ธ์ ์งํํ๋ฉด์ ๋๋ ๋ง์ ๋์์ค์ ๋จ์ ์ ์ค๋ช ํ๋ ค๊ณ ๋ ธ๋ ฅํ์ต๋๋ค. ์๋ง๋ ๋๋ ๋ชจ๋ ๊ฒ์ ๋๋ฌด ์์ธํ๊ฒ ์ค๋ช ํ์ ๊ฒ์ ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ๋ ์๋ก์ ๋งํ์ง ์์ ๋ด์ฉ์ ๋์ค์ ์๊ฐํ๋ ๊ฒ๋ณด๋ค ๋ถํ์ํ ๋ด์ฉ์ ๊ฑด๋ ๋ฐ๋ ๊ฒ์ด ๋ ์ฝ์ต๋๋ค.
์ธ์ ๋ ๊ทธ๋ ๋ฏ, ์ ๋ ๊ฑด์ค์ ์ธ ๋นํ์ ์ด๋ ค์์ต๋๋ค.
์ถ์ฒ : habr.com
