์ˆ˜๋Ÿ‰๊ณ„๋ฅผ ์Šค๋งˆํŠธ ํ™ˆ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์˜›๋‚ ์—๋Š” ํ™ˆ ์˜คํ† ๋ฉ”์ด์…˜ ์‹œ์Šคํ…œ, ์ฆ‰ ํ”ํžˆ "์Šค๋งˆํŠธ ํ™ˆ"์ด๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์‹œ์Šคํ…œ์€ ๊ฐ€๊ฒฉ์ด ๋„ˆ๋ฌด ๋น„์‹ธ์„œ ๋ถ€์ž๋“ค๋งŒ์ด ๊ฐ๋‹นํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  ์‹œ์žฅ์—์„œ๋Š” ์กฐ๋ช…, ์†Œ์ผ“, ํ™˜๊ธฐ, ๋ฌผ ๊ณต๊ธ‰ ๋ฐ ๊ธฐํƒ€ ์†Œ๋น„์ž๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ์„ผ์„œ, ๋ฒ„ํŠผ/์Šค์œ„์น˜ ๋ฐ ์•ก์ถ”์—์ดํ„ฐ๊ฐ€ ํฌํ•จ๋œ ์ƒ๋‹นํžˆ ์ €๋ ดํ•œ ํ‚คํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ€์žฅ ๋น„๋šค์–ด์ง„ 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๋กœ ์ „์›์„ ๊ณต๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค. ์ „์›์œผ๋กœ์„œ ๋‚˜๋Š” ์ž‘์€ ๊ฒƒ์„ ๊ฐ€์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค HLK-PM03 ์ฐจ๋‹จ ํ…์Šคํƒ€ ๋กœ๋ด‡์— ์˜ํ•ด. ๊ฐœ์ธ์ ์œผ๋กœ ์•„๋‚ ๋กœ๊ทธ์™€ ์ „๋ ฅ์ „์ž์— ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ ์ž‘์€ ์ผ€์ด์Šค์— ๊ธฐ์„ฑํ’ˆ ์ „์› ๊ณต๊ธ‰ ์žฅ์น˜๊ฐ€ ๋“ค์–ด์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘๋™ ๋ชจ๋“œ๋ฅผ ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•ด 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๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ์ด ๊ฒฝ์šฐ ๋ชจ๋ธ์ด ํ›จ์”ฌ ๋” ์ ํ•ฉํ•œ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด ๋ฐ uasync ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ . ๋”์šฑ์ด 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 ํŽŒ์›จ์–ด๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ๋นŒ๋“œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. mpy-cross ์œ ํ‹ธ๋ฆฌํ‹ฐ.

์ €๋Š” 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๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค).

์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋‹ค์šด๋กœ๋“œ ๋ฐ ์„ค์น˜ ESP ์˜คํ”ˆ SDK. ์ด๊ฒƒ์€ ESP8266์šฉ ํ”„๋กœ๊ทธ๋žจ์šฉ ์ปดํŒŒ์ผ๋Ÿฌ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์กฐ๋ฆฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ๋ฉ”์ธ ํŽ˜์ด์ง€์˜ ์ง€์นจ์— ๋”ฐ๋ผ ์–ด์…ˆ๋ธ”ํ–ˆ์Šต๋‹ˆ๋‹ค(์ €๋Š” STANDALONE=yes ์„ค์ •์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค).
  • ๋‹ค์šด๋กœ๋“œ ๋งˆ์ดํฌ๋กœํŒŒ์ด์ฌ ์ •๋ ฌ
  • micropython ํŠธ๋ฆฌ ๋‚ด๋ถ€์˜ ports/esp8266/modules์— ํ•„์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ฐฐ์น˜ํ•˜์„ธ์š”.
  • ํŒŒ์ผ์˜ ์ง€์นจ์— ๋”ฐ๋ผ ํŽŒ์›จ์–ด๋ฅผ ์กฐ๋ฆฝํ•ฉ๋‹ˆ๋‹ค. ํฌํŠธ/esp8266/README.md
  • ํŽŒ์›จ์–ด๋ฅผ ๋งˆ์ดํฌ๋กœ์ปจํŠธ๋กค๋Ÿฌ์— ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค(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

DDoS ๋ณดํ˜ธ, VPS VDS ์„œ๋ฒ„๊ฐ€ ์žˆ๋Š” ์‚ฌ์ดํŠธ๋ฅผ ์œ„ํ•œ ์•ˆ์ •์ ์ธ ํ˜ธ์ŠคํŒ… ๊ตฌ์ž… ๐Ÿ”ฅ DDoS ๊ณต๊ฒฉ ๋ฐฉ์ง€ ๊ธฐ๋Šฅ์ด ํƒ‘์žฌ๋œ ์•ˆ์ •์ ์ธ ์›น์‚ฌ์ดํŠธ ํ˜ธ์ŠคํŒ…, VPS ๋ฐ VDS ์„œ๋ฒ„๋ฅผ ๊ตฌ๋งคํ•˜์„ธ์š” | ProHoster