స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

ఒకప్పుడు, ఇంటి ఆటోమేషన్ సిస్టమ్స్ లేదా "స్మార్ట్ హోమ్" అని తరచుగా పిలవబడేవి చాలా ఖరీదైనవి మరియు ధనవంతులు మాత్రమే వాటిని కొనుగోలు చేయగలరు. నేడు మార్కెట్లో మీరు లైటింగ్, సాకెట్లు, వెంటిలేషన్, నీటి సరఫరా మరియు ఇతర వినియోగదారులను నియంత్రించడానికి సెన్సార్లు, బటన్లు/స్విచ్‌లు మరియు యాక్యుయేటర్‌లతో చాలా చవకైన కిట్‌లను కనుగొనవచ్చు. మరియు అత్యంత వంకరగా ఉన్న DIY వ్యక్తి కూడా అందంలో పాల్గొనవచ్చు మరియు చవకైన ధరలో స్మార్ట్ హోమ్ కోసం పరికరాలను సమీకరించవచ్చు.

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

సాధారణంగా, ప్రతిపాదిత పరికరాలు సెన్సార్లు లేదా యాక్యుయేటర్లు. "మోషన్ సెన్సార్ ట్రిగ్గర్ అయినప్పుడు, లైట్లను ఆన్ చేయండి" లేదా "నిష్క్రమణకు సమీపంలో ఉన్న స్విచ్ మొత్తం అపార్ట్‌మెంట్‌లోని లైట్లను ఆఫ్ చేస్తుంది" వంటి దృశ్యాలను అమలు చేయడాన్ని అవి సులభతరం చేస్తాయి. కానీ టెలిమెట్రీతో ఏదో ఒకవిధంగా విషయాలు పని చేయలేదు. ఉత్తమంగా, ఇది ఉష్ణోగ్రత మరియు తేమ యొక్క గ్రాఫ్ లేదా నిర్దిష్ట అవుట్‌లెట్ వద్ద తక్షణ శక్తి.

నేను ఇటీవల పల్స్ అవుట్‌పుట్‌తో నీటి మీటర్లను ఇన్‌స్టాల్ చేసాను. మీటర్ గుండా వెళ్ళే ప్రతి లీటరుకు, రీడ్ స్విచ్ సక్రియం చేయబడుతుంది మరియు పరిచయాన్ని మూసివేస్తుంది. వైర్లకు అతుక్కుని దాని నుండి ప్రయోజనం పొందే ప్రయత్నం చేయడమే మిగిలి ఉంది. ఉదాహరణకు, వారంలోని గంట మరియు రోజు వారీగా నీటి వినియోగాన్ని విశ్లేషించండి. బాగా, అపార్ట్మెంట్లో అనేక వాటర్ రైజర్లు ఉన్నట్లయితే, ఫ్లాష్లైట్తో కష్టతరమైన గూళ్ళలోకి ఎక్కడం కంటే ఒక స్క్రీన్పై అన్ని ప్రస్తుత సూచికలను చూడటం మరింత సౌకర్యవంతంగా ఉంటుంది.

కట్ క్రింద ESP8266 ఆధారిత పరికరం యొక్క నా వెర్షన్ ఉంది, ఇది నీటి మీటర్ల నుండి పప్పులను గణిస్తుంది మరియు MQTT ద్వారా రీడింగ్‌లను స్మార్ట్ హోమ్ సర్వర్‌కు పంపుతుంది. మేము uasyncio లైబ్రరీని ఉపయోగించి మైక్రోపైథాన్‌లో ప్రోగ్రామ్ చేస్తాము. ఫర్మ్వేర్ను సృష్టిస్తున్నప్పుడు, నేను అనేక ఆసక్తికరమైన ఇబ్బందులను ఎదుర్కొన్నాను, నేను ఈ వ్యాసంలో కూడా చర్చిస్తాను. వెళ్ళండి!

పథకం

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

మొత్తం సర్క్యూట్ యొక్క గుండె 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లను అందించడం మర్చిపోయాను మరియు నా బోర్డు వెర్షన్‌లో అవి లేవు. కానీ ప్రతి ఒక్కరూ చూడడానికి నేను ఇప్పటికే రేఖాచిత్రాన్ని పోస్ట్ చేస్తున్నాను కాబట్టి, ఈ పర్యవేక్షణను సరిదిద్దడం విలువ. ఫర్మ్‌వేర్ గ్లిచ్‌లు మరియు పిన్‌ను ఒకదానికి సెట్ చేస్తే పోర్ట్ బర్న్ కాకుండా ఉండటానికి రెసిస్టర్‌లు అవసరం, మరియు రీడ్ ఈ లైన్‌ను భూమికి షార్ట్ చేస్తుంది (రెసిస్టర్‌తో గరిష్టంగా 3.3V/1000Ohm = 3.3mA ప్రవహిస్తుంది).

కరెంటు పోతే ఏం చేయాలో ఆలోచించాల్సిన సమయం వచ్చింది. ప్రారంభంలో సర్వర్ నుండి ప్రారంభ కౌంటర్ విలువలను అభ్యర్థించడం మొదటి ఎంపిక. కానీ దీనికి మార్పిడి ప్రోటోకాల్ యొక్క ముఖ్యమైన సంక్లిష్టత అవసరం. అంతేకాకుండా, ఈ సందర్భంలో పరికరం యొక్క పనితీరు సర్వర్ యొక్క స్థితిపై ఆధారపడి ఉంటుంది. పవర్ ఆఫ్ చేయబడిన తర్వాత (లేదా తర్వాత ప్రారంభించబడినది) సర్వర్ ప్రారంభం కాకపోతే, నీటి మీటర్ ప్రారంభ విలువలను అభ్యర్థించదు మరియు సరిగ్గా పని చేయదు.

అందువల్ల, I2C ద్వారా కనెక్ట్ చేయబడిన మెమరీ చిప్‌లో సేవ్ చేసే కౌంటర్ విలువలను అమలు చేయాలని నేను నిర్ణయించుకున్నాను. ఫ్లాష్ మెమరీ పరిమాణానికి నాకు ప్రత్యేక అవసరాలు లేవు - మీరు కేవలం 2 సంఖ్యలను మాత్రమే సేవ్ చేయాలి (వేడి మరియు చల్లని నీటి మీటర్ల ప్రకారం లీటర్ల సంఖ్య). చిన్న మాడ్యూల్ కూడా చేస్తుంది. కానీ మీరు రికార్డింగ్ చక్రాల సంఖ్యకు శ్రద్ద అవసరం. చాలా మాడ్యూల్‌లకు ఇది 100 వేల చక్రాలు, కొన్నింటికి మిలియన్ వరకు.

ఒక మిలియన్ చాలా అని అనిపించవచ్చు. కానీ నా అపార్ట్మెంట్లో నివసిస్తున్న 4 సంవత్సరాలలో, నేను 500 క్యూబిక్ మీటర్ల కంటే కొంచెం ఎక్కువ నీటిని తీసుకున్నాను, అది 500 వేల లీటర్లు! మరియు ఫ్లాష్‌లో 500 వేల రికార్డులు. మరియు అది కేవలం చల్లని నీరు. మీరు ప్రతి రెండు సంవత్సరాలకు ఒకసారి చిప్‌ని రీసోల్డర్ చేయవచ్చు, కానీ FRAM చిప్‌లు ఉన్నాయని తేలింది. ప్రోగ్రామింగ్ దృక్కోణం నుండి, ఇది అదే I2C EEPROM, చాలా పెద్ద సంఖ్యలో రీరైట్ సైకిల్స్ (వందల మిలియన్లు)తో మాత్రమే ఉంటుంది. నేను ఇప్పటికీ అలాంటి మైక్రో సర్క్యూట్‌లతో దుకాణానికి చేరుకోలేను, కాబట్టి ప్రస్తుతానికి సాధారణ 24LC512 నిలుస్తుంది.

ముద్రిత సర్క్యూట్ బోర్డు

ప్రారంభంలో, నేను ఇంట్లోనే బోర్డు తయారు చేయాలని అనుకున్నాను. అందువల్ల, బోర్డు ఏకపక్షంగా రూపొందించబడింది. కానీ లేజర్ ఐరన్ మరియు టంకము ముసుగుతో ఒక గంట గడిపిన తర్వాత (అది లేకుండా ఇది ఏదో ఒకవిధంగా కాదు), నేను ఇప్పటికీ చైనీస్ నుండి బోర్డులను ఆర్డర్ చేయాలని నిర్ణయించుకున్నాను.

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

బోర్డ్‌ను ఆర్డర్ చేయడానికి దాదాపు ముందు, ఫ్లాష్ మెమరీ చిప్‌తో పాటు, I2C బస్‌కి డిస్‌ప్లే వంటి ఉపయోగకరమైన మరేదైనా కనెక్ట్ చేయగలనని నేను గ్రహించాను. దీనికి ఖచ్చితంగా ఏమి అవుట్‌పుట్ చేయాలి అనేది ఇప్పటికీ ప్రశ్నగా ఉంది, కానీ అది బోర్డులో రూట్ చేయబడాలి. సరే, నేను ఫ్యాక్టరీ నుండి బోర్డులను ఆర్డర్ చేయబోతున్నాను కాబట్టి, నన్ను ఒకే-వైపు బోర్డుకి పరిమితం చేయడంలో ఎటువంటి ప్రయోజనం లేదు, కాబట్టి I2C లైన్లు బోర్డు వెనుక వైపు మాత్రమే ఉంటాయి.

వన్-వే వైరింగ్‌తో ఒక పెద్ద సమస్య కూడా ఉంది. ఎందుకంటే బోర్డు ఒక-వైపుగా డ్రా చేయబడింది, కాబట్టి ట్రాక్‌లు మరియు SMD భాగాలు ఒక వైపు మరియు అవుట్‌పుట్ భాగాలు, కనెక్టర్లు మరియు విద్యుత్ సరఫరా మరొక వైపు ఉంచడానికి ప్రణాళిక చేయబడ్డాయి. ఒక నెల తర్వాత నేను బోర్డులను స్వీకరించినప్పుడు, నేను అసలు ప్లాన్ గురించి మరచిపోయాను మరియు ముందు వైపున ఉన్న అన్ని భాగాలను విక్రయించాను. మరియు విద్యుత్ సరఫరాను టంకం చేయడానికి వచ్చినప్పుడు మాత్రమే ప్లస్ మరియు మైనస్ రివర్స్‌లో వైర్ చేయబడిందని తేలింది. నేను జంపర్లతో వ్యవసాయం చేయాల్సి వచ్చింది. పై చిత్రంలో, నేను ఇప్పటికే వైరింగ్‌ను మార్చాను, కానీ బూట్ బటన్ యొక్క పిన్స్ ద్వారా నేల బోర్డు యొక్క ఒక భాగం నుండి మరొకదానికి బదిలీ చేయబడుతుంది (రెండవ పొరపై ట్రాక్‌ను గీయడం సాధ్యమవుతుంది).

ఇది ఇలా మారింది

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

హౌసింగ్

తదుపరి దశ శరీరం. మీకు 3D ప్రింటర్ ఉంటే, ఇది సమస్య కాదు. నేను పెద్దగా బాధపడలేదు - నేను సరైన పరిమాణంలో పెట్టెను గీసాను మరియు సరైన ప్రదేశాలలో కటౌట్‌లను చేసాను. కవర్ చిన్న స్వీయ-ట్యాపింగ్ స్క్రూలతో శరీరానికి జోడించబడింది.

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

బూట్ బటన్‌ను సాధారణ ప్రయోజన బటన్‌గా ఉపయోగించవచ్చని నేను ఇప్పటికే పేర్కొన్నాను - కాబట్టి మేము దానిని ముందు ప్యానెల్‌లో ప్రదర్శిస్తాము. ఇది చేయుటకు, నేను బటన్ నివసించే ప్రత్యేక "బాగా" గీసాను.

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

కేసు లోపల బోర్డ్ ఇన్‌స్టాల్ చేయబడిన మరియు ఒకే M3 స్క్రూతో భద్రపరచబడిన స్టడ్‌లు కూడా ఉన్నాయి (బోర్డ్‌లో ఎక్కువ స్థలం లేదు)

నేను కేసు యొక్క మొదటి నమూనా సంస్కరణను ముద్రించినప్పుడు నేను ఇప్పటికే ప్రదర్శనను ఎంచుకున్నాను. ప్రామాణిక రెండు-లైన్ రీడర్ ఈ సందర్భంలో సరిపోలేదు, కానీ దిగువన OLED డిస్ప్లే SSD1306 128×32 ఉంది. ఇది కొంచెం చిన్నది, కానీ నేను ప్రతిరోజూ దాన్ని తదేకంగా చూడవలసిన అవసరం లేదు-ఇది నాకు చాలా ఎక్కువ.

ఈ విధంగా మరియు దాని నుండి వైర్లు ఎలా మళ్లించబడతాయో గుర్తించడం ద్వారా, నేను కేసు మధ్యలో డిస్ప్లేను ఉంచాలని నిర్ణయించుకున్నాను. ఎర్గోనామిక్స్, వాస్తవానికి, సమానంగా దిగువన ఉన్నాయి - బటన్ పైన ఉంది, ప్రదర్శన దిగువన ఉంది. కానీ డిస్‌ప్లేను అటాచ్ చేయాలనే ఆలోచన చాలా ఆలస్యంగా వచ్చిందని మరియు బటన్‌ను తరలించడానికి బోర్డ్‌ను రీవైర్ చేయడానికి నేను చాలా సోమరిగా ఉన్నానని నేను ఇప్పటికే చెప్పాను.

పరికరం సమావేశమై ఉంది. డిస్ప్లే మాడ్యూల్ వేడి జిగురుతో స్నాట్‌కు అతుక్కొని ఉంటుంది

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

తుది ఫలితం KDPVలో చూడవచ్చు

ఫర్మువేర్

సాఫ్ట్‌వేర్ భాగానికి వెళ్దాం. ఇలాంటి చిన్న చేతిపనుల కోసం, నేను నిజంగా పైథాన్‌ని ఉపయోగించాలనుకుంటున్నాను (మైక్రోపైథాన్) - కోడ్ చాలా కాంపాక్ట్ మరియు అర్థమయ్యేలా మారుతుంది. అదృష్టవశాత్తూ, మైక్రోసెకన్లను పిండడానికి రిజిస్టర్ స్థాయికి వెళ్లవలసిన అవసరం లేదు - ప్రతిదీ పైథాన్ నుండి చేయవచ్చు.

ప్రతిదీ చాలా సులభం, కానీ చాలా సులభం కాదు - పరికరం అనేక స్వతంత్ర విధులను కలిగి ఉంది:

  • వినియోగదారు బటన్‌ను దూర్చి ప్రదర్శన వైపు చూస్తారు
  • ఫ్లాష్ మెమరీలో లీటర్లు టిక్ మరియు అప్‌డేట్ విలువలు
  • మాడ్యూల్ WiFi సిగ్నల్‌ను పర్యవేక్షిస్తుంది మరియు అవసరమైతే మళ్లీ కనెక్ట్ చేస్తుంది
  • బాగా, మెరిసే లైట్ బల్బ్ లేకుండా అది అసాధ్యం

కొన్ని కారణాల వల్ల ఒక ఫంక్షన్ మరొకటి నిలిచిపోయినట్లయితే అది పని చేయలేదని మీరు ఊహించలేరు. నేను ఇప్పటికే ఇతర ప్రాజెక్ట్‌లలో కాక్టిని నింపాను మరియు ఇప్పుడు నేను ఇప్పటికీ "మరో లీటర్ మిస్ అయ్యాను ఎందుకంటే డిస్‌ప్లే ఆ సమయంలో అప్‌డేట్ అవుతోంది" లేదా "మాడ్యూల్ కనెక్ట్ అవుతున్నప్పుడు వినియోగదారు ఏమీ చేయలేరు వైఫై.” అయితే, కొన్ని పనులు అంతరాయాల ద్వారా చేయవచ్చు, కానీ మీరు వ్యవధి, కాల్‌ల గూడు లేదా వేరియబుల్స్‌కు అణు-యేతర మార్పులపై పరిమితులను ఎదుర్కొంటారు. సరే, ప్రతిదీ చేసే కోడ్ త్వరగా ముష్‌గా మారుతుంది.

В మరింత తీవ్రమైన ప్రాజెక్ట్ నేను క్లాసిక్ ప్రీఎంప్టివ్ మల్టీ టాస్కింగ్ మరియు FreeRTOSని ఉపయోగించాను, కానీ ఈ సందర్భంలో మోడల్ మరింత అనుకూలంగా మారింది. కొరౌటిన్లు మరియు uasync లైబ్రరీలు . అంతేకాకుండా, కొరౌటిన్ల పైథాన్ అమలు కేవలం అద్భుతమైనది - ప్రోగ్రామర్ కోసం ప్రతిదీ సరళంగా మరియు సౌకర్యవంతంగా చేయబడుతుంది. మీ స్వంత లాజిక్‌ను వ్రాయండి, మీరు స్ట్రీమ్‌ల మధ్య ఏ ప్రదేశాలలో మారవచ్చో చెప్పండి.

ప్రీఎంప్టివ్ మరియు కాంపిటేటివ్ మల్టీ టాస్కింగ్ మధ్య తేడాలను ఐచ్ఛిక అంశంగా అధ్యయనం చేయాలని నేను సూచిస్తున్నాను. ఇప్పుడు చివరకు కోడ్‌కి వెళ్దాం.

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

కాంటాక్ట్ బౌన్స్‌ని ఫిల్టర్ చేయడానికి 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

సరే, ఇప్పుడు పైథాన్ మరియు 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)

పైథాన్‌లో, బైట్‌లతో నేరుగా పని చేయడం కష్టం, అయితే ఇది మెమరీకి వ్రాయబడిన బైట్‌లు. నేను 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 సెకన్ల పాటు ప్రదర్శనను ఆన్ చేస్తుంది. ప్రదర్శన ప్రస్తుత మీటర్ రీడింగులను చూపుతుంది.

ఇంకా కొన్ని చిన్న విషయాలు మిగిలి ఉన్నాయి. ఈ మొత్తం ఎంటర్‌ప్రైజ్‌ను తిరిగి ప్రారంభించే ఫంక్షన్ ఇక్కడ ఉంది. ప్రధాన లూప్ నిమిషానికి ఒకసారి వివిధ డీబగ్గింగ్ సమాచారాన్ని పంపుతుంది. సాధారణంగా, నేను దానిని కోట్ చేస్తున్నాను - ఎక్కువగా వ్యాఖ్యానించాల్సిన అవసరం లేదని నేను భావిస్తున్నాను

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

నా జ్ఞాపకశక్తికి ఏదో జరిగింది

కాబట్టి, అన్ని కోడ్ ఉంది. నేను ఆంపీ యుటిలిటీని ఉపయోగించి ఫైల్‌లను అప్‌లోడ్ చేసాను - ఇది వాటిని అంతర్గత (ESP-07లోనిది) ఫ్లాష్ డ్రైవ్‌కు అప్‌లోడ్ చేయడానికి మరియు ప్రోగ్రామ్ నుండి సాధారణ ఫైల్‌లుగా యాక్సెస్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది. అక్కడ నేను ఉపయోగించిన mqtt_as, uasyncio, ssd1306 మరియు సేకరణల లైబ్రరీలను కూడా అప్‌లోడ్ చేసాను (mqtt_as లోపల ఉపయోగించబడింది).

మేము ప్రారంభించాము మరియు... మాకు మెమరీ ఎర్రర్ వస్తుంది. అంతేకాకుండా, మెమరీ ఎక్కడ లీక్ అవుతుందో అర్థం చేసుకోవడానికి నేను ఎంత ఎక్కువ ప్రయత్నించానో, నేను ఎక్కువ డీబగ్ ప్రింట్‌లను ఉంచాను, అంత త్వరగా ఈ లోపం కనిపించింది. మైక్రోకంట్రోలర్‌కు సూత్రప్రాయంగా 30 kB మెమరీ మాత్రమే ఉందని, 65 kB కోడ్ (లైబ్రరీలతో సహా) సరిపోదని ఒక చిన్న Google శోధన నాకు అర్థమైంది.

కానీ ఒక మార్గం ఉంది. మైక్రోపైథాన్ నేరుగా .py ఫైల్ నుండి కోడ్‌ని అమలు చేయదని తేలింది - ఈ ఫైల్ మొదట కంపైల్ చేయబడింది. అంతేకాకుండా, ఇది మైక్రోకంట్రోలర్‌లో నేరుగా సంకలనం చేయబడుతుంది, బైట్‌కోడ్‌గా మార్చబడుతుంది, అది మెమరీలో నిల్వ చేయబడుతుంది. బాగా, కంపైలర్ పని చేయడానికి, మీకు కొంత మొత్తంలో RAM కూడా అవసరం.

రిసోర్స్-ఇంటెన్సివ్ కంపైలేషన్ నుండి మైక్రోకంట్రోలర్‌ను సేవ్ చేయడం ఉపాయం. మీరు పెద్ద కంప్యూటర్‌లో ఫైల్‌లను కంపైల్ చేయవచ్చు మరియు మైక్రోకంట్రోలర్‌లోకి రెడీమేడ్ బైట్‌కోడ్‌ను అప్‌లోడ్ చేయవచ్చు. దీన్ని చేయడానికి, మీరు మైక్రోపైథాన్ ఫర్మ్‌వేర్‌ను డౌన్‌లోడ్ చేసి బిల్డ్ చేయాలి mpy-క్రాస్ యుటిలిటీ.

నేను మేక్‌ఫైల్ రాయలేదు, కానీ మాన్యువల్‌గా వెళ్లి అవసరమైన అన్ని ఫైల్‌లను (లైబ్రరీలతో సహా) ఇలా సంకలనం చేసాను

mpy-cross water_counter.py

.mpy పొడిగింపుతో ఫైల్‌లను అప్‌లోడ్ చేయడం మాత్రమే మిగిలి ఉంది, ముందుగా పరికరం ఫైల్ సిస్టమ్ నుండి సంబంధిత .pyని తొలగించడం మర్చిపోవద్దు.

నేను ప్రోగ్రామ్ (IDE?) ESPlorer లో అన్ని అభివృద్ధిని చేసాను. ఇది మైక్రోకంట్రోలర్‌కు స్క్రిప్ట్‌లను అప్‌లోడ్ చేయడానికి మరియు వాటిని వెంటనే అమలు చేయడానికి మిమ్మల్ని అనుమతిస్తుంది. నా విషయంలో, అన్ని వస్తువుల యొక్క అన్ని తర్కం మరియు సృష్టి water_counter.py (.mpy) ఫైల్‌లో ఉంది. కానీ ఇవన్నీ ఆటోమేటిక్‌గా స్టార్ట్ కావాలంటే ప్రారంభంలో main.py అనే ఫైల్ కూడా ఉండాలి. అంతేకాకుండా, ఇది ఖచ్చితంగా .py అయి ఉండాలి మరియు ముందుగా కంపైల్ చేసిన .mpy కాదు. దాని అల్పమైన విషయాలు ఇక్కడ ఉన్నాయి

import water_counter

మేము దానిని ప్రారంభించాము - ప్రతిదీ పని చేస్తుంది. కానీ ఉచిత మెమరీ భయంకరంగా చిన్నది - సుమారు 1kb. పరికరం యొక్క కార్యాచరణను విస్తరించడానికి నేను ఇప్పటికీ ప్రణాళికలను కలిగి ఉన్నాను మరియు ఈ కిలోబైట్ నాకు స్పష్టంగా సరిపోదు. అయితే ఈ కేసుకు కూడా ఓ మార్గం ఉందని తేలింది.

ఇక్కడ విషయం ఉంది. ఫైల్‌లు బైట్‌కోడ్‌లో కంపైల్ చేయబడినప్పటికీ మరియు అంతర్గత ఫైల్ సిస్టమ్‌లో ఉన్నప్పటికీ, వాస్తవానికి అవి ఇప్పటికీ RAMలోకి లోడ్ చేయబడి, అక్కడ నుండి అమలు చేయబడతాయి. కానీ మైక్రోపైథాన్ ఫ్లాష్ మెమరీ నుండి నేరుగా బైట్‌కోడ్‌ను అమలు చేయగలదని తేలింది, అయితే దీని కోసం మీరు దీన్ని నేరుగా ఫర్మ్‌వేర్‌లోకి నిర్మించాలి. ఇది కష్టం కాదు, అయినప్పటికీ నా నెట్‌బుక్‌లో కొంత సమయం పట్టింది (అక్కడ మాత్రమే నేను Linuxని కలిగి ఉన్నాను).

అల్గోరిథం క్రింది విధంగా ఉంది:

  • డౌన్‌లోడ్ చేసి, ఇన్‌స్టాల్ చేయండి ESP ఓపెన్ SDK. ఈ విషయం ESP8266 కోసం ప్రోగ్రామ్‌ల కోసం కంపైలర్ మరియు లైబ్రరీలను సమీకరించింది. ప్రాజెక్ట్ యొక్క ప్రధాన పేజీలోని సూచనల ప్రకారం సమీకరించబడింది (నేను STANDALONE=అవును సెట్టింగ్‌ని ఎంచుకున్నాను)
  • డౌన్లోడ్ మైక్రోపైథాన్ రకాలు
  • మైక్రోపైథాన్ ట్రీ లోపల పోర్ట్‌లు/esp8266/మాడ్యూల్స్‌లో అవసరమైన లైబ్రరీలను ఉంచండి
  • ఫైల్‌లోని సూచనల ప్రకారం మేము ఫర్మ్‌వేర్‌ను సమీకరించాము ports/esp8266/README.md
  • మేము మైక్రోకంట్రోలర్‌కు ఫర్మ్‌వేర్‌ను అప్‌లోడ్ చేస్తాము (నేను దీన్ని Windowsలో ESP8266Flasher ప్రోగ్రామ్‌లు లేదా Python esptool ఉపయోగించి చేస్తాను)

అంతే, ఇప్పుడు 'దిగుమతి ssd1306' నేరుగా ఫర్మ్‌వేర్ నుండి కోడ్‌ను ఎత్తివేస్తుంది మరియు దీని కోసం RAM వినియోగించబడదు. ఈ ట్రిక్‌తో, నేను లైబ్రరీ కోడ్‌ను మాత్రమే ఫర్మ్‌వేర్‌లోకి అప్‌లోడ్ చేసాను, అయితే ప్రధాన ప్రోగ్రామ్ కోడ్ ఫైల్ సిస్టమ్ నుండి అమలు చేయబడుతుంది. ఫర్మ్‌వేర్‌ను రీకంపైల్ చేయకుండా ప్రోగ్రామ్‌ను సులభంగా సవరించడానికి ఇది మిమ్మల్ని అనుమతిస్తుంది. ప్రస్తుతం నా దగ్గర 8.5kb ఉచిత ర్యామ్ ఉంది. ఇది భవిష్యత్తులో చాలా విభిన్న ఉపయోగకరమైన కార్యాచరణలను అమలు చేయడానికి మాకు అనుమతిస్తుంది. సరే, తగినంత మెమరీ లేకపోతే, మీరు ప్రధాన ప్రోగ్రామ్‌ను ఫర్మ్‌వేర్‌లోకి నెట్టవచ్చు.

కాబట్టి మనం ఇప్పుడు దాని గురించి ఏమి చేయాలి?

సరే, హార్డ్‌వేర్ కరిగించబడింది, ఫర్మ్‌వేర్ వ్రాయబడింది, పెట్టె ముద్రించబడింది, పరికరం గోడపై ఇరుక్కుపోయింది మరియు ఆనందంగా లైట్ బల్బ్‌ను బ్లింక్ చేస్తుంది. కానీ ప్రస్తుతానికి అదంతా బ్లాక్ బాక్స్ (అక్షరాలా మరియు అలంకారికంగా) మరియు ఇది ఇప్పటికీ చాలా తక్కువ ఉపయోగం. సర్వర్‌కు పంపబడే MQTT సందేశాలతో ఏదైనా చేయవలసిన సమయం ఇది.

నా "స్మార్ట్ హోమ్" తిరుగుతోంది ప్రధాన వ్యవస్థ. MQTT మాడ్యూల్ బాక్స్ నుండి బయటకు వస్తుంది లేదా యాడ్-ఆన్ మార్కెట్ నుండి సులభంగా ఇన్‌స్టాల్ చేయబడుతుంది - నేను దానిని ఎక్కడ నుండి పొందానో నాకు గుర్తు లేదు. MQTT అనేది స్వయం సమృద్ధి గల విషయం కాదు - మీకు పిలవబడేది అవసరం. బ్రోకర్ - MQTT సందేశాలను ఖాతాదారులకు స్వీకరించే, క్రమబద్ధీకరించే మరియు ఫార్వార్డ్ చేసే సర్వర్. నేను దోమను ఉపయోగిస్తాను, ఇది (మేజర్‌డోమో లాగా) అదే నెట్‌బుక్‌లో నడుస్తుంది.

పరికరం కనీసం ఒక్కసారైనా సందేశాన్ని పంపిన తర్వాత, విలువ వెంటనే జాబితాలో కనిపిస్తుంది.

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

ఈ విలువలు ఇప్పుడు సిస్టమ్ వస్తువులతో అనుబంధించబడతాయి, అవి ఆటోమేషన్ స్క్రిప్ట్‌లలో ఉపయోగించబడతాయి మరియు వివిధ విశ్లేషణలకు లోబడి ఉంటాయి - ఇవన్నీ ఈ కథనం యొక్క పరిధికి మించినవి. నేను ఆసక్తి ఉన్న ఎవరికైనా మేజర్‌డోమో సిస్టమ్‌ని సిఫార్సు చేయగలను ఛానెల్ ఎలక్ట్రానిక్స్ ఇన్ లెన్స్ — ఒక స్నేహితుడు కూడా స్మార్ట్ హోమ్‌ని నిర్మిస్తున్నాడు మరియు సిస్టమ్‌ను సెటప్ చేయడం గురించి స్పష్టంగా మాట్లాడుతున్నాడు.

నేను మీకు రెండు గ్రాఫ్‌లను చూపుతాను. ఇది రోజువారీ విలువల యొక్క సాధారణ గ్రాఫ్

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది
రాత్రి వేళల్లో దాదాపు ఎవరూ నీటిని వినియోగించకపోవడం గమనించవచ్చు. ఒకటిరెండు సార్లు ఎవరైనా టాయిలెట్‌కి వెళ్లినప్పుడు, రివర్స్ ఆస్మాసిస్ ఫిల్టర్ రాత్రికి రెండు లీటర్లు పీలుస్తుంది. ఉదయం, వినియోగం గణనీయంగా పెరుగుతుంది. నేను సాధారణంగా బాయిలర్ నుండి నీటిని ఉపయోగిస్తాను, కానీ నేను స్నానం చేయాలనుకున్నాను మరియు తాత్కాలికంగా సిటీ వేడి నీటికి మారాను - ఇది దిగువ గ్రాఫ్‌లో కూడా స్పష్టంగా కనిపిస్తుంది.

టాయిలెట్‌కి వెళ్లడానికి 6-7 లీటర్ల నీరు అవసరమని, స్నానం చేయడానికి 20-30 లీటర్లు, పాత్రలు కడగడానికి 20 లీటర్లు, స్నానం చేయడానికి 160 లీటర్లు అవసరమని ఈ గ్రాఫ్ నుండి నేను తెలుసుకున్నాను. నా కుటుంబం రోజుకు 500-600 లీటర్లు వినియోగిస్తుంది.

ప్రత్యేకించి ఆసక్తి ఉన్నవారి కోసం, మీరు ఒక్కొక్క విలువకు సంబంధించిన రికార్డులను చూడవచ్చు

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

ఇక్కడ నుండి నేను ట్యాప్ తెరిచినప్పుడు, నీరు 1 సెకన్లకు సుమారు 5 లీటరు వేగంతో ప్రవహిస్తుంది.

కానీ ఈ రూపంలో గణాంకాలు బహుశా చూడటానికి చాలా సౌకర్యవంతంగా లేవు. Majordomo రోజు, వారం మరియు నెల వారీగా వినియోగ చార్ట్‌లను వీక్షించే సామర్థ్యాన్ని కూడా కలిగి ఉంది. ఇక్కడ, ఉదాహరణకు, బార్‌లలోని వినియోగ గ్రాఫ్

స్మార్ట్ హోమ్‌కి వాటర్ మీటర్‌ని కనెక్ట్ చేస్తోంది

ఇప్పటివరకు నా దగ్గర ఒక వారం డేటా మాత్రమే ఉంది. ఒక నెలలో, ఈ గ్రాఫ్ మరింత సూచికగా ఉంటుంది - ప్రతి రోజు ప్రత్యేక కాలమ్ ఉంటుంది. నేను మాన్యువల్‌గా (అతిపెద్ద కాలమ్) నమోదు చేసిన విలువలకు సర్దుబాట్ల ద్వారా చిత్రం కొద్దిగా చెడిపోయింది. మరియు నేను చాలా మొదటి విలువలను తప్పుగా సెట్ చేసానా, దాదాపు ఒక క్యూబ్ తక్కువగా ఉందా లేదా ఇది ఫర్మ్‌వేర్‌లో బగ్ మరియు అన్ని లీటర్లు లెక్కించబడలేదా అనేది ఇంకా స్పష్టంగా తెలియలేదు. మరింత సమయం కావాలి.

గ్రాఫ్‌లకు ఇప్పటికీ కొంత మేజిక్, వైట్‌వాషింగ్, పెయింటింగ్ అవసరం. బహుశా డీబగ్గింగ్ ప్రయోజనాల కోసం మెమరీ వినియోగం యొక్క గ్రాఫ్‌ను కూడా నేను నిర్మిస్తాను - ఒకవేళ అక్కడ ఏదైనా లీక్ అయినట్లయితే. ఇంటర్నెట్ లేనప్పుడు నేను ఏదో ఒకవిధంగా కాలాలను ప్రదర్శిస్తాను. ప్రస్తుతానికి ఇదంతా ఆలోచనల స్థాయిలోనే ఉంది.

తీర్మానం

ఈ రోజు నా అపార్ట్మెంట్ కొంచెం తెలివిగా మారింది. ఇంత చిన్న పరికరంతో, ఇంట్లో నీటి వినియోగాన్ని పర్యవేక్షించడం నాకు మరింత సౌకర్యవంతంగా ఉంటుంది. ఇంతకుముందు నేను "మళ్ళీ, మేము ఒక నెలలో చాలా నీరు త్రాగాము" అని కోపంగా ఉంటే, ఇప్పుడు నేను ఈ వినియోగానికి మూలాన్ని కనుగొనగలను.

మీటర్‌కు మీటరు దూరంలో ఉంటే స్క్రీన్‌పై రీడింగ్‌లు చూడటం కొందరికి వింతగా అనిపించవచ్చు. కానీ చాలా సుదూర భవిష్యత్తులో, నేను మరొక అపార్ట్మెంట్కు వెళ్లాలని ప్లాన్ చేస్తున్నాను, అక్కడ అనేక వాటర్ రైజర్లు ఉంటాయి మరియు మీటర్లు ల్యాండింగ్లో ఎక్కువగా ఉంటాయి. కాబట్టి రిమోట్ రీడింగ్ పరికరం చాలా ఉపయోగకరంగా ఉంటుంది.

నేను పరికరం యొక్క కార్యాచరణను విస్తరించాలని కూడా ప్లాన్ చేస్తున్నాను. నేను ఇప్పటికే మోటరైజ్డ్ వాల్వ్‌లను చూస్తున్నాను. ఇప్పుడు, బాయిలర్‌ను సిటీ వాటర్‌కి మార్చడానికి, నేను 3 ట్యాప్‌లను హార్డ్-టు-రీచ్ సముచితంలో తిప్పాలి. సంబంధిత సూచనతో ఒక బటన్‌తో దీన్ని చేయడం చాలా సౌకర్యవంతంగా ఉంటుంది. బాగా, వాస్తవానికి, లీక్‌లకు వ్యతిరేకంగా రక్షణను అమలు చేయడం విలువ.

వ్యాసంలో నేను ESP8266 ఆధారంగా పరికరం యొక్క నా సంస్కరణను వివరించాను. నా అభిప్రాయం ప్రకారం, నేను కరోటిన్‌లను ఉపయోగించి మైక్రోపైథాన్ ఫర్మ్‌వేర్ యొక్క చాలా ఆసక్తికరమైన వెర్షన్‌తో ముందుకు వచ్చాను - సరళమైనది మరియు బాగుంది. ప్రచార సమయంలో నేను ఎదుర్కొన్న అనేక సూక్ష్మ నైపుణ్యాలు మరియు లోపాలను వివరించడానికి ప్రయత్నించాను. బహుశా నేను ప్రతిదీ చాలా వివరంగా వివరించాను; వ్యక్తిగతంగా, పాఠకుడిగా, చెప్పకుండా మిగిలిపోయిన వాటిని తర్వాత ఆలోచించడం కంటే అనవసరమైన విషయాలను దాటవేయడం నాకు సులభం.

ఎప్పటిలాగే, నేను నిర్మాణాత్మక విమర్శలకు సిద్ధంగా ఉన్నాను.

మూల
సర్క్యూట్ మరియు బోర్డు
కేస్ మోడల్

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి