ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

වරෙක, නිවාස ස්වයංක්‍රීයකරණ පද්ධති නොහොත් “ස්මාර්ට් නිවස” ලෙස හැඳින්වූයේ ඉතා මිල අධික වූ අතර ඒවා දැරිය හැක්කේ ධනවතුන්ට පමණි. අද වෙළඳපොලේ ඔබට ආලෝකය, සොකට්, වාතාශ්රය, ජල සැපයුම සහ අනෙකුත් පාරිභෝගිකයින් පාලනය කිරීම සඳහා සංවේදක, බොත්තම් / ස්විච සහ ක්රියාකාරී යන්ත්ර සහිත තරමක් මිල අඩු කට්ටල සොයාගත හැකිය. වඩාත් වංක DIY පුද්ගලයාට පවා අලංකාරයට සම්බන්ධ විය හැකි අතර අඩු මිලකට ස්මාර්ට් නිවසක් සඳහා උපාංග එකලස් කළ හැකිය.

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

සාමාන්‍යයෙන්, යෝජිත උපාංග සංවේදක හෝ ක්‍රියාකාරක වේ. ඔවුන් "චලන සංවේදකය ක්‍රියාත්මක වූ විට, විදුලි පහන් දැල්වීම" හෝ "පිටවීම අසල ඇති ස්විචය මුළු මහල් නිවාසයේම විදුලි පහන් නිවා දමයි" වැනි අවස්ථා ක්‍රියාත්මක කිරීම පහසු කරයි. නමුත් කෙසේ හෝ ටෙලිමෙට්‍රි සමඟ දේවල් සාර්ථක වූයේ නැත. හොඳම දෙය නම්, එය උෂ්ණත්වය සහ ආර්ද්රතාවය පිළිබඳ ප්රස්ථාරයක් හෝ නිශ්චිත අලෙවිසැලක ක්ෂණික බලයයි.

මම මෑතකදී ස්පන්දන ප්රතිදානය සමඟ ජල මීටර් සවි කළා. මීටරය හරහා ගමන් කරන සෑම ලීටරයක් ​​සඳහාම, බට ස්විචය සක්රිය කර ස්පර්ශය වසා දමයි. ඉතිරිව ඇත්තේ කම්බිවල එල්ලී එයින් ප්‍රයෝජන ගැනීමට උත්සාහ කිරීම පමණි. නිදසුනක් වශයෙන්, සතියේ පැය සහ දින අනුව ජල පරිභෝජනය විශ්ලේෂණය කරන්න. හොඳයි, මහල් නිවාසයේ වෝටර් රයිසර් කිහිපයක් තිබේ නම්, ෆ්ලෑෂ් ලයිට් සමඟ ළඟා වීමට අපහසු ස්ථානවලට නැඟීමට වඩා වත්මන් දර්ශක එක් තිරයක දැකීම වඩාත් පහසු වේ.

කපාට පහළින් ඇත්තේ ESP8266 මත පදනම් වූ උපාංගයක මගේ අනුවාදයයි, එය ජල මීටරවලින් ස්පන්දන ගණන් කර MQTT හරහා කියවීම් ස්මාර්ට් හෝම් සේවාදායකයට යවයි. අපි uasyncio පුස්තකාලය භාවිතයෙන් micropython හි වැඩසටහන් කරන්නෙමු. ස්ථිරාංග නිර්මාණය කිරීමේදී, මම සිත්ගන්නාසුලු දුෂ්කරතා කිහිපයකට මුහුණ දුන් අතර, මම මෙම ලිපියෙන් ද සාකච්ඡා කරමි. යන්න!

යෝජනා ක්රමය

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

සම්පූර්ණ පරිපථයේ හදවත ESP8266 ක්ෂුද්‍ර පාලකයේ මොඩියුලයකි. ESP-12 මුලින් සැලසුම් කරන ලදී, නමුත් මගේ දෝෂය ඇති විය. අපට ලබා ගත හැකි ESP-07 මොඩියුලය සමඟ සෑහීමට පත් වීමට සිදු විය. වාසනාවකට මෙන්, ඒවා අල්ෙපෙනති සහ ක්‍රියාකාරීත්වය යන දෙකටම සමාන වේ, එකම වෙනස ඇන්ටෙනාවෙහි ය - ESP-12 හි ගොඩනඟන ලද එකක් ඇති අතර ESP-07 හි බාහිර එකක් ඇත. කෙසේ වෙතත්, WiFi ඇන්ටෙනාවක් නොමැති වුවද, මගේ නාන කාමරයේ සංඥා සාමාන්යයෙන් ලැබෙනු ඇත.

සම්මත මොඩියුල රැහැන්:

  • පුල්-අප් සහ ධාරිත්‍රකය සහිත යළි පිහිටුවීමේ බොත්තම (දෙකම දැනටමත් මොඩියුලය තුළ ඇතත්)
  • සක්‍රීය සංඥාව (CH_PD) බලයට ඇදී යයි
  • GPIO15 බිමට ඇද දමනු ලැබේ. මෙය අවශ්‍ය වන්නේ ආරම්භයේදී පමණි, නමුත් මට තවමත් මෙම කකුලට සම්බන්ධ කිරීමට කිසිවක් නැත; මට එය තවදුරටත් අවශ්‍ය නොවේ

මොඩියුලය ස්ථිරාංග ප්‍රකාරයට දැමීම සඳහා, ඔබට කෙටි පරිපථ GPIO2 බිමට ගෙන යා යුතු අතර, එය වඩාත් පහසු කිරීමට, මම ඇරඹුම් බොත්තමක් ලබා දුන්නෙමි. සාමාන්‍ය තත්වයේදී, මෙම පින් එක බලයට ඇද දමයි.

GPIO2 රේඛාවේ තත්වය පරීක්ෂා කරනු ලබන්නේ මෙහෙයුම ආරම්භයේදී පමණි - බලය යොදන විට හෝ යළි පිහිටුවීමෙන් පසු වහාම. එබැවින් මොඩියුලය සුපුරුදු පරිදි ආරම්භ වේ හෝ ස්ථිරාංග මාදිලියට යයි. පූරණය වූ පසු, මෙම පින් එක සාමාන්‍ය GPIO එකක් ලෙස භාවිතා කළ හැක. හොඳයි, එහි දැනටමත් බොත්තමක් ඇති බැවින්, ඔබට එය ප්රයෝජනවත් කාර්යයක් ඇමිණිය හැකිය.

ක්‍රමලේඛනය සහ නිදොස්කරණය සඳහා මම UART භාවිතා කරමි, එය පනාවකට ප්‍රතිදානය කරයි. අවශ්‍ය වූ විට, මම එහි USB-UART ඇඩැප්ටරයක් ​​සම්බන්ධ කරමි. මොඩියුලය 3.3V මගින් බල ගැන්වෙන බව ඔබ මතක තබා ගත යුතුය. ඔබට මෙම වෝල්ටීයතාවයට ඇඩප්ටරය මාරු කිරීමට සහ 5V සැපයීමට අමතක වුවහොත්, මොඩියුලය බොහෝ විට දැවී යනු ඇත.

නාන කාමරයේ විදුලිය සමඟ මට කිසිදු ගැටළුවක් නොමැත - අලෙවිසැල මීටරයෙන් මීටරයක් ​​​​පමණ පිහිටා ඇත, එබැවින් මම 220V මගින් බල ගැන්වෙනු ඇත. බලශක්ති ප්රභවයක් ලෙස මට කුඩා එකක් ඇත HLK-PM03 අවහිර කරන්න ටෙන්ස්ටාර් රොබෝ විසිනි. පුද්ගලිකව, මට ඇනලොග් සහ බල ඉලෙක්ට්‍රොනික උපකරණ සමඟ දුෂ්කර කාලයක් ඇත, නමුත් මෙන්න කුඩා නඩුවක සූදානම් කළ බල සැපයුමක්.

මෙහෙයුම් මාතයන් සංඥා කිරීම සඳහා, මම GPIO2 වෙත සම්බන්ධ LED එකක් ලබා දුන්නා. කෙසේ වෙතත්, මම එය විකුණුවේ නැත, මන්ද ... ESP-07 මොඩියුලය දැනටමත් LED එකක් ඇති අතර, එය GPIO2 වෙතද සම්බන්ධ කර ඇත. නමුත් මට මෙම LED නඩුවට ප්‍රතිදානය කිරීමට අවශ්‍ය නම්, එය පුවරුවේ තිබිය යුතුය.

අපි වඩාත් රසවත් කොටස වෙත යමු. ජල මීටරවලට තර්කයක් නැත; ඔබට වත්මන් කියවීම් සඳහා ඔවුන්ගෙන් ඉල්ලා සිටිය නොහැක. අපට ලබා ගත හැකි එකම දෙය ආවේගයන් - සෑම ලීටරයකටම බට ස්විචයේ සම්බන්ධතා වසා දැමීම. මගේ රීඩ් ස්විච් ප්‍රතිදානයන් GPIO12/GPIO13 වෙත සම්බන්ධ කර ඇත. මම මොඩියුලය තුළ ක්‍රමලේඛනාත්මකව ඇදගෙන යාමේ ප්‍රතිරෝධය සක්‍රීය කරමි.

මුලදී, මට ප්රතිරෝධක R8 සහ R9 සැපයීමට අමතක වූ අතර මගේ පුවරුවේ අනුවාදය ඒවා නොමැත. නමුත් මම දැනටමත් සෑම කෙනෙකුටම දැකීමට රූප සටහන පළ කර ඇති බැවින්, මෙම අධීක්ෂණය නිවැරදි කිරීම වටී. ෆර්ම්වෙයාර් අවුල් වී pin එක එකකට සකසන්නේ නම්, සහ රීඩ් ස්විචය මෙම රේඛාව බිමට කෙටි කළහොත් පෝට් එක දැවී නොයන ලෙස ප්‍රතිරෝධක අවශ්‍ය වේ (ප්‍රතිරෝධකයේ උපරිමය 3.3V/1000Ohm = 3.3mA ගලා යයි).

විදුලිය විසන්ධි වුවහොත් කුමක් කළ යුතු දැයි සිතා බැලීමට කාලයයි. පළමු විකල්පය වන්නේ ආරම්භයේදී සේවාදායකයෙන් ආරම්භක කවුන්ටර අගයන් ඉල්ලා සිටීමයි. නමුත් මෙය හුවමාරු ප්රොටෝකෝලයෙහි සැලකිය යුතු සංකූලතාවයක් අවශ්ය වනු ඇත. එපමණක් නොව, මෙම නඩුවේ උපාංගයේ ක්රියාකාරිත්වය සේවාදායකයේ තත්වය මත රඳා පවතී. බලය අක්‍රිය කිරීමෙන් පසු සේවාදායකය ආරම්භ නොකළේ නම් (හෝ පසුව ආරම්භ කළ), ජල මීටරයට ආරම්භක අගයන් ඉල්ලා සිටීමට නොහැකි වන අතර නිවැරදිව ක්‍රියා නොකරයි.

එබැවින්, I2C හරහා සම්බන්ධිත මතක චිපයක සුරැකීමේ කවුන්ටර අගයන් ක්රියාත්මක කිරීමට මම තීරණය කළෙමි. ෆ්ලෑෂ් මතකයේ ප්‍රමාණය සඳහා මට විශේෂ අවශ්‍යතා නොමැත - ඔබට ඉතිරි කළ යුත්තේ අංක 2 ක් පමණි (උණුසුම් හා සීතල ජල මීටර අනුව ලීටර් ගණන). කුඩාම මොඩියුලය පවා සිදු කරනු ඇත. නමුත් ඔබ පටිගත කිරීමේ චක්‍ර ගණන කෙරෙහි අවධානය යොමු කළ යුතුය. බොහෝ මොඩියුල සඳහා මෙය චක්‍ර 100 දහසක් වන අතර සමහරක් සඳහා මිලියනයක් දක්වා වේ.

මිලියනයක් යනු බොහෝ බව පෙනේ. නමුත් මගේ මහල් නිවාසයේ ජීවත් වූ වසර 4 තුළ මම ජලය ඝන මීටර් 500 කට වඩා ටිකක් පරිභෝජනය කළෙමි, එය ලීටර් 500 කි! සහ ෆ්ලෑෂ් වාර්තා 500 ක්. ඒ වගේම සීතල වතුර විතරයි. ඔබට, ඇත්ත වශයෙන්ම, සෑම වසර දෙකකට වරක් චිපය නැවත අලෙවි කළ හැකිය, නමුත් FRAM චිප්ස් ඇති බව පෙනේ. ක්‍රමලේඛන දෘෂ්ටි කෝණයකින්, මෙය එකම I2C EEPROM වේ, නැවත ලිවීමේ චක්‍ර විශාල සංඛ්‍යාවක් (මිලියන සිය ගණනක්) සමඟ පමණි. මට තවමත් එවැනි ක්ෂුද්‍ර පරිපථ සමඟ ගබඩාවට යාමට නොහැකි වීම පමණි, එබැවින් දැනට සුපුරුදු 24LC512 පවතිනු ඇත.

මුද්රිත පරිපථ පුවරුව

මුලදී, මම ගෙදරදීම පුවරුව සෑදීමට සැලසුම් කළා. එමනිසා, පුවරුව එක පැත්තක් ලෙස නිර්මාණය කර ඇත. නමුත් ලේසර් යකඩ සහ පෑස්සුම් වෙස් මුහුණක් සමඟ පැයක් ගත කිරීමෙන් පසුව (එය කෙසේ හෝ නොමැතිව එය කළ නොහැක), මම තවමත් චීන ජාතිකයන්ගෙන් පුවරු ඇණවුම් කිරීමට තීරණය කළෙමි.

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

බෝඩ් එක ඕඩර් කරන්න කලින්ම මට තේරුනා ෆ්ලෑෂ් මතක චිප් එකට අමතරව ඩිස්ප්ලේ එකක් වගේ තවත් ප්‍රයෝජනවත් දෙයක් I2C බස් එකට සම්බන්ධ කරන්න පුළුවන් කියලා. එයට හරියටම ප්‍රතිදානය කරන්නේ කුමක්ද යන්න තවමත් ප්‍රශ්නයකි, නමුත් එය පුවරුව මත යොමු කළ යුතුය. හොඳයි, මම කර්මාන්ත ශාලාවෙන් පුවරු ඇණවුම් කිරීමට යන නිසා, තනි පැත්තක පුවරුවකට මා සීමා කිරීම තේරුමක් නැත, එබැවින් I2C රේඛා පුවරුවේ පිටුපස පැත්තේ පමණි.

එක පැත්තක කම්බි දැමීමේ එක් විශාල ගැටලුවක් ද විය. නිසා පුවරුව එක් පැත්තක් ලෙස ඇද ගන්නා ලදී, එබැවින් ධාවන පථ සහ SMD සංරචක එක් පැත්තක තැබීමට සැලසුම් කර ඇති අතර අනෙක් පැත්තෙන් ප්රතිදාන සංරචක, සම්බන්ධක සහ බල සැපයුම. මාසයකට පසු මට පුවරු ලැබුණු විට, මම මුල් සැලැස්ම ගැන අමතක කර ඉදිරිපස පැත්තේ සියලුම සංරචක පෑස්සුවා. බල සැපයුම පෑස්සීමට පැමිණි විට පමණක් ප්ලස් සහ අඩුව ප්‍රතිලෝමව වයර් කර ඇති බව පෙනී ගියේය. මට ගොවිතැන් කරන්න වුණේ ජම්පර් එක්ක. ඉහත පින්තූරයේ, මම දැනටමත් රැහැන් මාරු කර ඇත, නමුත් බූට් බොත්තමේ අල්ෙපෙනති හරහා බිම පුවරුවේ එක් කොටසක සිට තවත් කොටසකට මාරු කරනු ලැබේ (දෙවන ස්ථරයේ ධාවන පථයක් ඇඳීමට හැකි වුවද).

එය මෙසේ විය

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

නිවාස

ඊළඟ පියවර වන්නේ ශරීරයයි. ඔබට ත්‍රිමාණ මුද්‍රණ යන්ත්‍රයක් තිබේ නම්, මෙය ගැටළුවක් නොවේ. මම වැඩිය කරදර කළේ නැහැ - මම නියම ප්‍රමාණයේ පෙට්ටියක් ඇද නිවැරදි ස්ථානවල කටවුට් සෑදුවෙමි. ආවරණය කුඩා ස්වයං-කැපුම් ඉස්කුරුප්පු වලින් ශරීරයට සවි කර ඇත.

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

Boot බොත්තම පොදු කාර්ය බොත්තමක් ලෙස භාවිතා කළ හැකි බව මම දැනටමත් සඳහන් කර ඇත - එබැවින් අපි එය ඉදිරිපස පුවරුවේ පෙන්වමු. මෙය සිදු කිරීම සඳහා, මම බොත්තම ජීවත් වන විශේෂ "ළිඳක්" ඇද ගත්තෙමි.

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

නඩුව ඇතුළත පුවරුව සවි කර ඇති සහ තනි M3 ඉස්කුරුප්පු ඇණකින් සුරක්ෂිත කර ඇති ස්ටුඩ් ද ඇත (පුවරුවේ තවත් ඉඩක් නොතිබුණි)

මම නඩුවේ පළමු නියැදි අනුවාදය මුද්‍රණය කරන විට දැනටමත් සංදර්ශකය තෝරා ගතිමි. සම්මත පේළි දෙකක කියවනය මෙම නඩුවට නොගැලපේ, නමුත් පතුලේ OLED සංදර්ශකය SSD1306 128 × 32 විය. එය ටිකක් කුඩායි, නමුත් මට සෑම දිනකම එය දෙස බලා සිටිය යුතු නැත - එය මට ඕනෑවට වඩා වැඩිය.

මේ ආකාරයෙන් සහ එයින් වයර් ගමන් කරන්නේ කෙසේදැයි සොයා බැලීමෙන්, මම නඩුවේ මැද සංදර්ශකය ඇලවීමට තීරණය කළෙමි. Ergonomics, ඇත්ත වශයෙන්ම, සමානව පහතින් ඇත - බොත්තම ඉහළින්, සංදර්ශකය පහළින් ඇත. එත් මම කලිනුත් කිව්වා ඩිස්ප්ලේ එක ඇමිණීමේ අදහස ආවෙ ගොඩක් පරක්කු වෙලා නිසා මට කම්මැලියි බෝඩ් එක ගෙනියන්න ලෑස්ති ​​කරන්න.

උපාංගය එකලස් කර ඇත. සංදර්ශක මොඩියුලය උණුසුම් මැලියම් සමඟ snot වෙත ඇලී ඇත

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

අවසාන ප්‍රතිඵලය KDPV හි දැකිය හැක

ස්ථිරාංග

අපි මෘදුකාංග කොටස වෙත යමු. මෙවැනි කුඩා අත්කම් සඳහා, මම ඇත්තටම Python භාවිතා කිරීමට කැමතියි (micropython) - කේතය ඉතා සංයුක්ත සහ තේරුම් ගත හැකි බවට හැරේ. වාසනාවකට මෙන්, මයික්‍රො තත්පර මිරිකා හැරීම සඳහා ලේඛන මට්ටමට බැසීමට අවශ්‍ය නැත - සියල්ල පයිතන් වෙතින් කළ හැකිය.

සෑම දෙයක්ම සරල බව පෙනේ, නමුත් ඉතා සරල නොවේ - උපාංගය ස්වාධීන කාර්යයන් කිහිපයක් ඇත:

  • පරිශීලකයා බොත්තම ඔබා සංදර්ශකය දෙස බලයි
  • ෆ්ලෑෂ් මතකයේ ලීටර් ටික් කර අගයන් යාවත්කාලීන කරයි
  • මොඩියුලය WiFi සංඥාව නිරීක්ෂණය කරන අතර අවශ්ය නම් නැවත සම්බන්ධ වේ
  • හොඳයි, දැල්වෙන විදුලි බුබුලක් නොමැතිව එය කළ නොහැකි ය

කිසියම් හේතුවක් නිසා තවත් කාර්යයක් හිර වී ඇත්නම්, එක් කාර්යයක් ක්‍රියා කළේ නැතැයි ඔබට උපකල්පනය කළ නොහැක. මම දැනටමත් වෙනත් ව්‍යාපෘතිවල මගේ පතොක් පුරවා ඇති අතර දැන් මම තවමත් “එම මොහොතේ සංදර්ශකය යාවත්කාලීන වූ නිසා තවත් ලීටරයක් ​​මග හැරුණි” හෝ “මොඩියුලය සම්බන්ධ වන විට පරිශීලකයාට කිසිවක් කළ නොහැක” යන විලාසයේ දෝෂ දකිමි. Wifi." ඇත්ත වශයෙන්ම, සමහර දේවල් බාධා කිරීම් හරහා සිදු කළ හැක, නමුත් ඔබට කාලසීමාව, ඇමතුම් කැදලි තැබීම හෝ විචල්‍යයන් සඳහා පරමාණුක නොවන වෙනස්කම් මත සීමාවන් ඇති විය හැක. හොඳයි, සෑම දෙයක්ම කරන කේතය ඉක්මනින් මුෂ් බවට හැරේ.

В වඩාත් බරපතල ව්යාපෘතිය මම සම්භාව්‍ය පූර්වගාමී බහුකාර්ය සහ FreeRTOS භාවිතා කළ නමුත් මෙම අවස්ථාවෙහිදී ආකෘතිය වඩාත් සුදුසු විය. coroutines සහ uasync පුස්තකාල . එපමනක් නොව, coroutines 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

සෑම කවුන්ටරයක්ම කවුන්ටර පන්තියේ අවස්ථාවක් මගින් හසුරුවනු ලැබේ. පළමුවෙන්ම, ආරම්භක කවුන්ටර අගය EEPROM (අගය_ගබඩාව) වෙතින් අඩු කරනු ලැබේ - බල බිඳවැටීමකින් පසු ප්‍රතිසාධනය ක්‍රියාත්මක වන්නේ එලෙස ය.

විදුලිබල සැපයුම වෙත ගොඩනඟන ලද ඇදීමක් සමඟ පින් ආරම්භ කර ඇත: බට ස්විචය වසා තිබේ නම්, රේඛාව ශුන්‍ය වේ, රේඛාව විවෘත නම්, එය බල සැපයුම දක්වා ඇදී යන අතර පාලකය එකක් කියවයි.

මෙහි වෙනම කාර්යයක් ද දියත් කර ඇති අතර එමඟින් පින් ඡන්ද විමසනු ඇත. සෑම කවුන්ටරයක්ම තමන්ගේම කාර්යයක් ඉටු කරනු ඇත. මෙන්න ඇගේ කේතය

    """ 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)

සම්බන්ධතා bounce පෙරීමට 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 හි, ඔබට එජ් බාධාවක් සංවිධානය කළ හැකි අතර, පයිතන් හි මෙම බාධාව සඳහා හසුරුවන්නක් ලිවිය හැකිය. මෙම බාධාවේදී, විචල්‍යයක අගය යාවත්කාලීන කළ හැක. බොහෝ විට, කවුන්ටරය වහල් උපාංගයක් නම් මෙය ප්රමාණවත් වනු ඇත - එය මෙම අගය ඉල්ලා සිටින තෙක් බලා සිටින එකක්.

අවාසනාවකට (හෝ වාසනාවකටද?) මගේ උපාංගය සක්‍රියයි, එයම 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 පෙළ ගොනුවේ ගබඩා කරමි. සැකසුම් නොසලකා කේතය වෙනස් කිරීමට මෙන්ම විවිධ පරාමිතීන් සහිත සමාන උපාංග කිහිපයක් රිවට් කිරීමට මෙය ඔබට ඉඩ සලසයි.

අවසාන කේත කොටස මඟින් පද්ධතියේ විවිධ කාර්යයන් ඉටු කිරීම සඳහා coroutine කිහිපයක් ආරම්භ කරයි. උදාහරණයක් ලෙස, සේවා කවුන්ටර සපයන කොරූටින් එකක් මෙහි ඇත

    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))

coroutine නව කවුන්ටර අගයක් සඳහා ලූපයක් තුළ රැඳී සිටින අතර, එය දිස් වූ වහාම 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) සහ ඒවායේ කාලසීමාව ගණනය කරයි. සම්බන්ධතාවය ප්‍රතිසාධනය වූ විට, අක්‍රිය වේලාවක් සේවාදායකයට යවනු ලැබේ.

මාර්ගය වන විට, අවසාන නින්ද අවශ්‍ය වන්නේ ශ්‍රිතය අසමමුහුර්ත කිරීමට පමණි - පුස්තකාලය තුළ එය Wait හරහා හඳුන්වනු ලබන අතර, ශරීරයේ තවත් අපේක්ෂාවක් අඩංගු කාර්යයන් පමණක් හැඳින්විය හැක.

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)

මම Blinking modes 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 ක් සංදර්ශකය සක්‍රිය කරයි. සංදර්ශකය වත්මන් මීටර කියවීම් පෙන්වයි.

තව පොඩි දේවල් දෙකක් ඉතුරුයි. මෙම සම්පූර්ණ ව්‍යවසාය (නැවත) ආරම්භ කරන ශ්‍රිතය මෙන්න. ප්‍රධාන ලූපය විනාඩියකට වරක් විවිධ නිදොස් කිරීමේ තොරතුරු යවයි. පොදුවේ ගත් කල, මම එය එලෙසම උපුටා දක්වමි - ඕනෑවට වඩා අදහස් දැක්වීමේ අවශ්‍යතාවයක් ඇතැයි මම නොසිතමි

   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())

මගේ මතකයට යමක් සිදු විය

ඉතින්, සියලුම කේතය එහි ඇත. මම ගොනු උඩුගත කළේ ඇම්පිය උපයෝගිතා භාවිතයෙන් - එය ඔබට අභ්‍යන්තර (ඊඑස්පී-07 හි ඇති එක) ෆ්ලෑෂ් ධාවකය වෙත උඩුගත කිරීමට ඉඩ සලසයි, ඉන්පසු එය සාමාන්‍ය ගොනු ලෙස වැඩසටහනෙන් ප්‍රවේශ විය හැකිය. එහිදී මම භාවිතා කළ mqtt_as, uasyncio, ssd1306 සහ එකතු කිරීමේ පුස්තකාල ද උඩුගත කළෙමි (mqtt_as ඇතුළත භාවිතා වේ).

අපි දියත් කරනවා සහ... අපිට MemoryError එකක් ලැබෙනවා. එපමණක්ද නොව, මතකය කාන්දු වන්නේ කොතැනද යන්න තේරුම් ගැනීමට මම වැඩි වැඩියෙන් උත්සාහ කළ විට, මම වැඩි වැඩියෙන් දෝශ නිරාකරණ මුද්‍රණ තැබූ විට, මෙම දෝෂය කලින් දිස් විය. කෙටි ගූගල් සෙවුමක් මඟින් මයික්‍රොකොන්ට්‍රෝලර් සතුව ඇත්තේ ප්‍රතිපත්තිමය වශයෙන් 30 kB මතකයක් පමණක් වන අතර 65 kB කේත (පුස්තකාල ඇතුළුව) සරලව නොගැලපෙන බව මට අවබෝධ විය.

නමුත් මගක් තිබේ. මයික්‍රොපිතන් කෙලින්ම .py ගොනුවකින් කේතය ක්‍රියාත්මක නොකරන බව පෙනේ - මෙම ගොනුව මුලින්ම සම්පාදනය කර ඇත. එපමනක් නොව, එය ක්ෂුද්ර පාලකය මත සෘජුවම සම්පාදනය කර, බයිට්කෝඩ් බවට පත් කර, පසුව මතකයේ ගබඩා කර ඇත. හොඳයි, සම්පාදකය වැඩ කිරීමට, ඔබට නිශ්චිත RAM ප්‍රමාණයක් ද අවශ්‍ය වේ.

උපක්‍රමය නම් ක්ෂුද්‍ර පාලකය සම්පත්-දැඩි සම්පාදනයෙන් සුරැකීමයි. ඔබට විශාල පරිගණකයක ගොනු සම්පාදනය කර සූදානම් කළ බයිට් කේතය මයික්‍රොකොන්ට්‍රෝලර් වෙත උඩුගත කළ හැකිය. මෙය සිදු කිරීම සඳහා, ඔබ micropython ස්ථිරාංග බාගත කර ගොඩනගා ගත යුතුය mpy-cross උපයෝගීතාව.

මම Makefile එකක් ලිව්වේ නැත, නමුත් අතින් ගොස් අවශ්‍ය සියලුම ලිපිගොනු (පුස්තකාල ඇතුළුව) මේ වගේ දෙයක් සම්පාදනය කළා

mpy-cross water_counter.py

ඉතිරිව ඇත්තේ .mpy දිගුව සමඟ ගොනු උඩුගත කිරීම පමණි, පළමුව උපාංගයේ ගොනු පද්ධතියෙන් අනුරූප .py මකා දැමීමට අමතක නොකරන්න.

මම වැඩසටහනේ (IDE?) ESPlorer හි සියලුම සංවර්ධන කටයුතු සිදු කළා. එය ඔබට ස්ක්‍රිප්ට් ක්ෂුද්‍ර පාලකයට උඩුගත කිරීමට සහ ඒවා වහාම ක්‍රියාත්මක කිරීමට ඉඩ සලසයි. මගේ නඩුවේදී, සියලු වස්තූන්ගේ සියලු තර්ක සහ නිර්මාණය water_counter.py (.mpy) ගොනුවේ පිහිටා ඇත. නමුත් මේ සියල්ල ස්වයංක්‍රීයව ආරම්භ වීමට නම් මුලදී main.py නමින් ගොනුවක් ද තිබිය යුතුය. එපමණක් නොව, එය හරියටම .py විය යුතු අතර, පෙර සම්පාදනය නොකළ .mpy විය යුතුය. මෙන්න එහි සුළු අන්තර්ගතය

import water_counter

අපි එය දියත් කරමු - සියල්ල ක්රියා කරයි. නමුත් නිදහස් මතකය භයානක ලෙස කුඩායි - 1kb පමණ. මම තවමත් උපාංගයේ ක්රියාකාරිත්වය පුළුල් කිරීමට සැලසුම් කර ඇති අතර, මෙම කිලෝබයිට් මට පැහැදිලිවම ප්රමාණවත් නොවේ. නමුත් මෙම නඩුව සඳහාද මගක් ඇති බව පෙනී ගියේය.

මෙන්න කාරණය. ගොනු bytecode බවට සම්පාදනය කර අභ්‍යන්තර ගොනු පද්ධතිය මත පැවතුනද, ඇත්ත වශයෙන්ම ඒවා තවමත් RAM වෙත පටවා එතැනින් ක්‍රියාත්මක වේ. නමුත් මයික්‍රොපිතන්ට ෆ්ලෑෂ් මතකයෙන් සෘජුවම බයිට්කෝඩ් ක්‍රියාත්මක කළ හැකි බව පෙනේ, නමුත් මේ සඳහා ඔබ එය කෙලින්ම ස්ථිරාංගයට ගොඩනගා ගත යුතුය. මගේ නෙට්බුක් එකේ සෑහෙන වෙලාවක් ගත්තත් ඒක අමාරු නැහැ (මට ලිනක්ස් තිබුණේ එතන විතරයි).

ඇල්ගොරිතම පහත පරිදි වේ:

  • බාගත කර ස්ථාපනය කරන්න ESP විවෘත SDK. මෙම දෙය ESP8266 සඳහා වැඩසටහන් සඳහා සම්පාදකයක් සහ පුස්තකාලයක් එකලස් කරයි. ව්‍යාපෘතියේ ප්‍රධාන පිටුවේ ඇති උපදෙස් අනුව එකලස් කරන ලදී (මම STANDALONE=ඔව් සැකසුම තෝරා ගත්තෙමි)
  • බාගත කරන්න micropython වර්ග
  • මයික්‍රොපිතන් ගස තුළ වරාය/esp8266/මොඩියුලවල අවශ්‍ය පුස්තකාල තබන්න
  • ගොනුවේ ඇති උපදෙස් අනුව අපි ස්ථිරාංග එකලස් කරමු ports/esp8266/README.md
  • අපි ස්ථිරාංග ක්ෂුද්‍ර පාලකයට උඩුගත කරමු (මම මෙය වින්ඩෝස් හි ESP8266Flasher වැඩසටහන් හෝ Python esptool භාවිතයෙන් සිදු කරමි)

එපමණයි, දැන් 'import ssd1306' මඟින් කේතය ස්ථිරාංගයෙන් කෙලින්ම ඔසවන අතර මේ සඳහා RAM පරිභෝජනය නොකෙරේ. මෙම උපක්‍රමය සමඟ, මම පුස්තකාල කේතය පමණක් ස්ථිරාංග වෙත උඩුගත කළ අතර ප්‍රධාන වැඩසටහන් කේතය ගොනු පද්ධතියෙන් ක්‍රියාත්මක වේ. ස්ථිරාංග නැවත සම්පාදනය නොකර වැඩසටහන පහසුවෙන් වෙනස් කිරීමට මෙය ඔබට ඉඩ සලසයි. දැනට මට නොමිලේ RAM 8.5kb පමණ ඇත. අනාගතයේදී විවිධ ප්‍රයෝජනවත් ක්‍රියාකාරකම් රාශියක් ක්‍රියාත්මක කිරීමට මෙය අපට ඉඩ සලසයි. හොඳයි, ප්‍රමාණවත් මතකයක් නොමැති නම්, ඔබට ප්‍රධාන වැඩසටහන ස්ථිරාංගයට තල්ලු කළ හැකිය.

ඉතින් අපි දැන් ඒ ගැන කුමක් කළ යුතුද?

හරි, හාඩ්වෙයාර් එක පාස්සලා, ෆර්ම්වෙයාර් එක ලියලා, පෙට්ටිය ප්‍රින්ට් කරලා, ඩිවයිස් එක බිත්තියේ හිරවෙලා සතුටින් බල්බයක් ඇසිපිය ගහනවා. නමුත් දැනට ඒ සියල්ල කළු පෙට්ටියක් (වචනාර්ථයෙන් සහ සංකේතාත්මකව) වන අතර එය තවමත් එතරම් ප්‍රයෝජනයක් නැත. සේවාදායකයට යවන MQTT පණිවිඩ සමඟ යමක් කිරීමට කාලයයි.

මගේ "ස්මාර්ට් හෝම්" කැරකෙමින් තිබේ Majordomo පද්ධතිය. MQTT මොඩියුලය එක්කෝ කොටුවෙන් පිටතට පැමිණේ, නැතහොත් ඇඩෝන වෙළඳපොලෙන් පහසුවෙන් ස්ථාපනය කර ඇත - මට එය ලැබුනේ කොහෙන්දැයි මට මතක නැත. MQTT යනු ස්වයංපෝෂිත දෙයක් නොවේ - ඔබට ඊනියා අවශ්ය වේ. තැරැව්කරු - සේවාලාභීන්ට MQTT පණිවිඩ ලබා ගන්නා, වර්ග කරන සහ යොමු කරන සේවාදායකයකි. මම මදුරුවන් භාවිතා කරමි, එය (මජර්ඩෝමෝ වැනි) එකම නෙට්බුක් මත ධාවනය වේ.

උපාංගය අවම වශයෙන් එක් වරක් පණිවිඩයක් යැවීමෙන් පසු, අගය වහාම ලැයිස්තුවේ දිස්වනු ඇත.

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

මෙම අගයන් දැන් පද්ධති වස්තු සමඟ සම්බන්ධ කළ හැකිය, ඒවා ස්වයංක්‍රීය ස්ක්‍රිප්ට් වල භාවිතා කළ හැකි අතර විවිධ විශ්ලේෂණයන්ට භාජනය කළ හැකිය - මේ සියල්ල මෙම ලිපියේ විෂය පථයෙන් ඔබ්බට ය. උනන්දුවක් දක්වන ඕනෑම කෙනෙකුට මට මේජර්ඩොමෝ ක්‍රමය නිර්දේශ කළ හැකිය චැනල් ඉලෙක්ට්‍රොනික්ස් ඉන් ලෙන්ස් - මිතුරෙකු ද ස්මාර්ට් නිවසක් ගොඩනඟමින් සිටින අතර පද්ධතිය සැකසීම ගැන පැහැදිලිව කථා කරයි.

මම ඔබට ප්‍රස්තාර කිහිපයක් පෙන්වන්නම්. මෙය දෛනික අගයන්හි සරල ප්‍රස්ථාරයකි

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම
රාත්‍රී කාලයේ කිසිවකු ජලය භාවිත නොකළ බව ද දැකගත හැකිය. කිහිප වතාවක් යමෙකු වැසිකිළියට ගිය අතර, ප්‍රතිලෝම ඔස්මෝසිස් පෙරණය රාත්‍රියකට ලීටර් කිහිපයක් උරා බොන බව පෙනේ. උදෑසන, පරිභෝජනය සැලකිය යුතු ලෙස වැඩි වේ. මම සාමාන්‍යයෙන් බොයිලේරුවෙන් ජලය භාවිතා කරමි, නමුත් පසුව මට ස්නානය කිරීමට අවශ්‍ය වූ අතර තාවකාලිකව නගර උණු වතුරට මාරු විය - මෙය පහළ ප්‍රස්ථාරයේ ද පැහැදිලිව දැකගත හැකිය.

මෙම ප්‍රස්ථාරයෙන් මම දැනගත්තේ වැසිකිළි යාමට වතුර ලීටර් 6-7ක්, ස්නානය කිරීමට ලීටර් 20-30ක්, පිඟන් සෝදන්නට ලීටර් 20ක් සහ නාන්න ලීටර් 160ක් අවශ්‍ය වන බවයි. මගේ පවුල දිනකට ලීටර් 500-600 ක් පමණ පරිභෝජනය කරයි.

විශේෂයෙන් කුතුහලයෙන් සිටින අය සඳහා, ඔබට එක් එක් තනි අගය සඳහා වාර්තා දෙස බැලිය හැකිය

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

ටැප් එක විවෘත කළ විට තත්පර 1 කට ආසන්න වශයෙන් ලීටර් 5 ක වේගයෙන් ජලය ගලා යන බව මම මෙතැන් සිට ඉගෙන ගතිමි.

නමුත් මෙම ආකෘතියේ සංඛ්යා ලේඛන බැලීමට බොහෝ විට පහසු නැත. Majordomo හට දින, සතිය සහ මාසය අනුව පරිභෝජන ප්‍රස්ථාර බැලීමේ හැකියාව ද ඇත. මෙන්න, උදාහරණයක් ලෙස, බාර්වල පරිභෝජන ප්රස්ථාරයක් වේ

ස්මාර්ට් නිවසකට ජල මීටරයක් ​​සම්බන්ධ කිරීම

මෙතෙක් මා සතුව දත්ත ඇත්තේ සතියකට පමණි. මාසයකින්, මෙම ප්‍රස්ථාරය වඩාත් ඇඟවුම් කරයි - සෑම දිනකම වෙනම තීරුවක් ඇත. මම අතින් ඇතුල් කරන අගයන්ට ගැලපීම් මගින් පින්තූරය තරමක් නරක් වී ඇත (විශාලතම තීරුව). මම පළමු අගයන් වැරදි ලෙස සකසා තිබේද, ඝනකයක් පමණ අඩුද, නැතහොත් මෙය ස්ථිරාංගයේ දෝෂයක්ද යන්න සහ සියලුම ලීටර් ගණන් කර නොමැතිද යන්න තවමත් පැහැදිලි නැත. තව කල් ඕන.

ප්‍රස්ථාර වලට තවමත් මැජික්, සුදු හුනු ගෑම, පින්තාරු කිරීම අවශ්‍ය වේ. සමහර විට මම නිදොස් කිරීමේ අරමුණු සඳහා මතක පරිභෝජනයේ ප්‍රස්ථාරයක් ද ගොඩනඟන්නෙමි - යම් දෙයක් එහි කාන්දු වුවහොත්. සමහර විට මම අන්තර්ජාලය නොමැති කාල පරිච්ඡේද පෙන්වනු ඇත. දැනට, මේ සියල්ල අදහස් මට්ටමේ ය.

නිගමනය

අද මගේ මහල් නිවාසය ටිකක් බුද්ධිමත් වී ඇත. එවැනි කුඩා උපාංගයක් සමඟ, නිවසේ ජල පරිභෝජනය නිරීක්ෂණය කිරීම මට වඩාත් පහසු වනු ඇත. මීට පෙර මම “නැවතත්, අපි මාසයක් තුළ ජලය විශාල ප්‍රමාණයක් පරිභෝජනය කළෙමු” යනුවෙන් කෝපයට පත් වූවා නම්, දැන් මට මෙම පරිභෝජනයේ මූලාශ්‍රය සොයාගත හැකිය.

මීටරයේ සිට මීටරයක් ​​දුරින් නම් තිරයේ කියවීම් දෙස බැලීම සමහරුන්ට අමුතු දෙයක් විය හැකිය. නමුත් ඉතා නුදුරු අනාගතයේ දී, මම වෙනත් මහල් නිවාසයකට යාමට අදහස් කරමි, එහිදී ජල රයිසර් කිහිපයක් ඇති අතර, මීටර බොහෝ දුරට ගොඩබෑමේ පිහිටා ඇත. එබැවින් දුරස්ථ කියවීමේ උපකරණයක් ඉතා ප්රයෝජනවත් වනු ඇත.

උපාංගයේ ක්රියාකාරිත්වය පුළුල් කිරීමට ද මම සැලසුම් කරමි. මම දැනටමත් මෝටර් කපාට දෙස බලමි. දැන්, බොයිලේරු නගරයේ ජලය වෙත මාරු කිරීම සඳහා, මට ළඟා වීමට අපහසු ස්ථානයකට ටැප් 3 ක් හැරවිය යුතුය. අනුරූප ඇඟවීමක් සහිත එක් බොත්තමක් සමඟ මෙය කිරීම වඩාත් පහසු වනු ඇත. හොඳයි, ඇත්ත වශයෙන්ම, කාන්දුවීම් වලට එරෙහිව ආරක්ෂාව ක්රියාත්මක කිරීම වටී.

ලිපියේ මම ESP8266 මත පදනම් වූ උපාංගයක මගේ අනුවාදය විස්තර කළෙමි. මගේ මතය අනුව, මම coroutines භාවිතා කරමින් micropython firmware හි ඉතා රසවත් අනුවාදයක් ඉදිරිපත් කළෙමි - සරල හා ලස්සනයි. ප්‍රචාරක ව්‍යාපාරයේදී මා මුහුණ දුන් බොහෝ සූක්ෂ්මතා සහ අඩුපාඩු විස්තර කිරීමට මම උත්සාහ කළෙමි. සමහර විට මම සෑම දෙයක්ම ඕනෑවට වඩා විස්තරාත්මකව විස්තර කළෙමි; පුද්ගලිකව, පාඨකයෙකු ලෙස, මට නොකියා ඉතිරිව ඇති දේ ගැන පසුව සිතනවාට වඩා අනවශ්‍ය දේ මඟ හැරීම පහසුය.

සෑම විටම මෙන්, මම නිර්මාණාත්මක විවේචන සඳහා විවෘතව සිටිමි.

ප්‍රභව කේතය
පරිපථය සහ පුවරුව
නඩු ආකෘතිය

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න