Project
Project
8thSemesterProjectReportSubmittedinfulfilmentoftherequirementsforthedegreeof
BachelorofTechnologyfromMaulanaAbulKalamAzadUniversityofTechnology,West Bengal
(formerly known as West Bengal University of Technology)
By
SAHARIYARCHOWDHURY(34900321022)
SRUTIBASUROYCHOWDHURY(34900322034)
ARATRIKADAS(34900322038)
SUSMITAGAYEN(34900322049)
UndertheGuidanceof
ProjectSupervisor/(s):[Link]
TechnicalFacilitator:[Link]
pg. 1
DepartmentofElectronicsandCommunicationEngineering Cooch
Behar Government Engineering College
CoochBehar,WestBengal 2026
Certificate of Recommendation
It is hereby recommended to consider the project report entitled "Automated Mist Cooling System" submitted by-
for partial fulfilment of the requirements for the award of the degree of Bachelor of Technology in Electronics and
Communication Engineering from Cooch Behar Govt. Engineering College affiliated to Maulana Abul Kalam Azad
University of Technology (formerly known as West Bengal University of Technology).
------------------------------ -------------------------------
pg. 2
Certificate of Approval
It is hereby approved that the project report entitled "Automated Mist Cooling System" submitted by-
for partial fulfilment of the requirements for the award of the degree of Bachelor of Technology in Electronics and
Communication Engineering from Cooch Behar Govt. Engineering College affiliated to Maulana Abul Kalam Azad
University of Technology (formerly known as West Bengal University of Technology).
Board of Examiners
Name Signature
-------------------------------------------- --------------------------------------------
-------------------------------------------- --------------------------------------------
-------------------------------------------- --------------------------------------------
-------------------------------------------- --------------------------------------------
-------------------------------------------- --------------------------------------------
pg. 3
Acknowledgement
Iwouldliketoexpressmysinceregratitudetoallthosewhohavecontributedtothesuccessfulcompletion of this
project titled “Automated Mist Cooling System.”
Firstandforemost, Iexpressmyheartfeltthankstomyprojectguidefortheirvaluableguidance,constant
encouragement, and constructive suggestions throughout the course of this project. Their expertise and
support played a crucial role in shaping this work.
I am also thankful to the Head of the Department and all the faculty members of the department for
providingthenecessaryfacilities,resources,andacademicsupportrequiredforthecompletionofthis project.
Iwouldliketoextendmygratitudetomyfriendsandclassmatesfortheircooperation,teamwork,andmoral support
during the development and testing phases of the project.
Finally, I am deeply grateful to my parents and family members for their continuous encouragement,
patience,[Link],thisproject
would not have been possible.
ProjectMembers
Roll No. Name Signature
34900321022 SAHARIYARCHOWDHURY
34900322034 SRUTIBASUROYCHOWDHURY
34900322038 ARATRIKADAS
34900322049 SUSMITAGAYEN
pg. 4
Contents
Publication
ListofPrincipalSymbolsandAcronyms List
of Figures
List of Tables
AbstractChapter
1 Introduction
Chapter 2
LiteratureSurvey
Chapter 3
SystemArchitectureandHardwareDesign
3.1 SystemOverview
3.2 HardwareComponents
Chapter4
SoftwareDesignandImplementation
4.2 ControlAlgorithm
Chapter 5
FutureWork
Chapter 6
6.2 Conclusion
6.3 FutureScope
Reference
Appendix
pg. 5
List of Principal Symbolsand Acronyms
Symbol/ Acronym Description
IoT InternetofThings
ESP32 Wi-FiandBluetoothenabledmicrocontrollerbyEspressifDC
Direct Current
AC Alternating Current
DHT11 DigitalTemperatureandHumidity Sensor
GPIO GeneralPurposeInput Output
PWM PulseWidthModulation
Wi-Fi WirelessFidelity
MCU MicrocontrollerUnit
API ApplicationProgrammingInterface
Blynk IoTcloudplatformformonitoringandcontrol
V Voltage(Volts)
I Current (Amperes)
W Power(Watts)
°C DegreeCelsius
%RH PercentageRelativeHumidity
RTC RealTimeClock
LED LightEmittingDiode
NO NormallyOpen
NC NormallyClosed
ADC Analogto Digital Converter
PSU PowerSupplyUnit
MOSFET MetalOxideSemiconductorFieldEffectTransistor
PCB Printed Circuit Board
pg. 6
ListofFigures
Fig. 2.1 SmartIrrigationandMistControlSystems
Fig. 2.2 DC Pump
pg. 7
Abstract
TheAutomatedMistCoolingSystemusingInternetofThings(IoT)isanintelligentandenergy-
efficient solution designed to control temperature and humidity in various environments
through real-time monitoring and automation. The system operates on the principle of
evaporativecooling,wherefinewatermistissprayedtoreduceambienttemperatureeffectively
while minimizing water consumption. By integrating sensors, a microcontroller, and cloud-
basedplatforms,thesystemenablesbothautomaticandmanualcontrolofthemistingprocess.
The proposed system utilizes temperature and humidity sensors to continuously monitor
environmental [Link] ESP32 microcontroller processes the sensor data and activates
a DC misting pump when the measured parameters exceed predefined threshold values.
Manual control buttons are also incorporated to allow user override and ensure system
[Link],
enabling real-time data visualization, remote monitoring, and control through a mobile
application.
Thisautomatedmistcoolingsystemreduceshumanintervention,conservesenergyandwater, and
improves operational efficiency. It is particularly suitable for applications such as agriculture,
greenhouses, poultry farms, industrial cooling, and outdoor environments. The
implementation of IoT technology enhances system reliability, scalability, and user
convenience, making it a sustainable and smart solution for modern cooling requirements.
pg. 8
Chapter1 INTRODUCTION
Mistcoolingworksontheprincipleofevaporativecooling,wherefinewaterdropletsabsorb heat
from the surrounding air during evaporation, thereby reducing ambient temperature.
Compared to conventional air-conditioning systems, mist cooling systems consume less
powerandwater,[Link] IoT
technology, the mist cooling process can be monitored and controlled remotely, improving
system efficiency and user convenience.
The automated mist cooling system uses sensors such as temperature and humidity sensors
(DHT11/DHT22) and soil moisture sensors to continuously monitor environmental
conditions. A microcontroller like the ESP32 processes this sensor data and activates a DC
[Link] both
automatic and manual modes, allowing flexibility in operation. Additionally, cloud platforms
such as Blynk enable real-time data visualization, remote control, and alert notifications
through smartphones or web interfaces.
This IoT-based mist cooling system is highly suitable for applications such as greenhouses,
agriculturalfields,poultryfarms,outdoorcoolingareas,industrialenvironments,andsmart
homes. By reducing water wastage, energy consumption, and manual effort, the system
promotes sustainable cooling practices. Hence, the Automated Mist Cooling System using
IoT represents an efficient and intelligent solution for modern environmental control
challenges.
pg. 9
Chapter2LiteratureSurvey
2.1 Introduction
Traditionalcoolingmethodssuchasairconditioners,fans,andconventionalwatersprinklers are
widely used in residential, agricultural, and industrial environments. Although effective, air-
conditioning systems consume high electrical energy and are not environmentally
sustainable. Conventional misting and sprinkler systems often operate manually or on fixed
timers, leading to inefficient water usage and lack of adaptability to changing environmental
conditions. These systems lack real-time monitoring and automation, resulting in higher
operational costs and reduced efficiency.
With the development of embedded systems, sensor-based automation has become a key
area of research. Several researchers have implemented temperature and humidity-based
control [Link],sensorslikeDHT11
andDHT22areusedtomonitorenvironmentalparameters,andcoolingdevicesareactivated when
threshold values are exceeded. While these systems improve efficiency compared to
manualsystems,theyareoftenlimitedtolocalcontrolandlackremotemonitoringcapabilities.
The emergence of IoT has enabled real-time monitoring and control of environmental
[Link]-basedtemperatureandhumidity
[Link]
platforms like Blynk, ThingSpeak, and Firebase are used to visualize sensor data and control
[Link]-makingbutareoften
focused on monitoring rather than active cooling control.
pg. 10
2.5 Smart Irrigation and Mist Control Systems
Fig.2.1 SmartIrrigationandMistControlSystems
SeveralresearchworkshaveexploredIoT-basedsmartirrigationsystemswheresoilmoisture
sensors, temperature sensors, and humidity sensors are used to control water pumps
automatically. These systems aim to reduce water wastage and improve crop yield. Some
studies extend this concept to mist control for greenhouses and poultry farms, where
[Link],manyexistingsystemslack
manual override options and fail to address system reliability during network failure.
DCpumpsarecommonlyusedinlow-powerautomatedsystemsduetotheirenergyefficiency,
compactsize,[Link]
misting pumps are suitable for IoT-based applications as they can be easily controlled using
[Link],previousimplementationsoftensufferfrom
issuessuchaspumpoverheating,cloggingofmistnozzles,andinadequatesafetymechanisms.
pg. 11
2.7 Limitations of Existing Systems
Highenergyconsumptioninconventionalcooling systems
Lackofreal-timeadaptabilityintimer-basedmist systems
Limitedremoteaccessinsensor-onlyautomatedsystems
Absenceofmanualcontrolandemergencyoverrideoptions
Dependenceoncontinuousinternet connectivity
Inadequateintegrationofmultiplesensorsandsafetyfeatures
Theselimitationsindicatetheneedforamorereliable,flexible,anduser-friendlymistcooling
solution.
2.8 ResearchGapandMotivation
The literature survey reveals a gap in developing a fully integrated automated mist cooling
system that combines real-time sensing, IoT-based monitoring, manual override, and energy-
[Link] mistcoolingbasedon
environmental conditions but also provides remote control, data visualization, and backup
manual control. This project aims to address these gaps by implementing an IoT-based
automatedmistcoolingsystemusingESP32,DCmistingpump, multiplesensors,andacloud
platform.
2.9 Summary
This chapter reviewed existing cooling systems, sensor-based automation, and IoT-based
environmental monitoring solutions. Although significant progress has been made in smart
coolingandirrigationtechnologies,existingsystemsstillfacechallengesrelatedtoefficiency,
reliability, and user control. The proposed Automated Mist Cooling System using IoT is
designedtoovercometheselimitationsbyprovidinganintelligent,energy-efficient,andflexible
solution suitable for modern applications.
pg. 12
Chapter3
SystemArchitectureandHardwareDesign
3.1 SystemOverview
ThesystemintegratesanESP32microcontrollerwithmultiplesensorsandactuators. Data is
Fig.3.1 HardwareSetup
pg. 13
3.2 HardwareComponents
• ESP32 Microcontroller
Fig.3.2 SmartIrrigationandMistControlSystems
ESP32isafamilyoflow-cost,energy-efficientmicrocontrollersthatintegratebothWi-
FiandBluetoothcapabilities. These chips feature a variety of processing options,
including theTensilicaXtensa LX6 microprocessor available in both dual-core and
single-corevariants,theXtensaLX7dual-coreprocessor,orasingle-coreRISC-
Vmicroprocessor. In addition, the ESP32 incorporates components essential for
wireless data communication such as built-in antenna switches, an RFbalun, power
amplifiers, low-noise receivers, filters, and power-management modules.
Typically, the ESP32 is embedded on device-specific printed circuit boards or offered as part of
development kits that include a variety of GPIOpins and connectors, with
configurationsvaryingbymodelandmanufacturer.TheESP32wasdesigned byEspressif Systemsand is
manufactured byTSMCusing their 40nm [Link] is a successor to the ESP8266 microcontroller.
• SoilMoistureSensor
Fig.3.3 SoilMoistureSensor
pg. 14
Soil moisture sensors measure the volumetric water content in soil. Since the direct
gravimetricmeasurementoffreesoilmoisturerequiresremoving,drying,andweighing of
a sample, soil moisture sensors measure the volumetric water content indirectly by
usingsomeotherpropertyofthesoil,suchaselectricalresistance,dielectricconstant, or
interaction with neutrons, as a proxy for the moisture content.
The relation between the measured property and soil moisture must be calibrated
and mayvarydependingonenvironmentalfactorssuchassoiltype,temperature,orelectric
[Link] for
remote sensing in hydrology and agriculture. Portable probe instruments can be used
by farmers or gardeners.
Soilmoisturesensorstypicallyrefertosensorsthatestimatevolumetricwatercontent.
Another class of sensors measure another property of moisture in soils called water
potential; these sensors are usually referred to as soil water potential sensors and
include tensiometers and gypsum blocks.
• DHT11TemperatureandHumiditySensor
Fig.3.4DHT11Sensor
[Link]
affectsvariousphysical,[Link],
humiditycanaffectthebusinesscostoftheproducts,healthandsafetyoftheemployees.
So,insemiconductorindustriesandcontrolsystemindustriesmeasurementofhumidity is
very [Link] measurement determines the amount of moisture present in
the gas that can be a mixture of water vapour, nitrogen, argon or pure gas etc…
[Link]
humidity sensor and Absolute humidity sensor. DHT11 is a digital temperature and
humidity sensor.
pg. 15
[Link]
canbeeasilyinterfacedwithanymicro-controllersuchasArduino,RaspberryPietc… to
measure humidity and temperature instantaneously.
[Link]
differencebetweenthissensorandmoduleisthepull-upresistorandapower-onLED.
[Link] a
thermistor and a capacitive humidity sensor.
DHT11 sensor consists of a capacitive humidity sensing element and a thermistor for
sensing [Link] humidity sensing capacitor has two electrodes with a
[Link]
[Link],processthischanged
resistance values and change them into digital form.
pg. 16
A DC misting pump is an electrically operated pumping device designed to deliver water at high
pressure in the form of fine mist or micro-droplets. It is widely used in applications such as
agriculture irrigation systems, greenhouse climate control, cooling systems, humidity control, and
IoT-based automation projects. Unlike conventional water pumps, a misting pump produces
extremely fine droplets that increase surface area, enabling faster evaporation and efficient
moisture distribution with minimal water wastage.
DC misting pumps operate using direct current (DC) power, typically supplied by
batteries,DCadapters,[Link]
lowpowerconsumption,compactsize,[Link]
no or ESP32, DC misting pumps are highly suitable for smart and automated systems.
As the diaphragm or piston moves forward, water is compressed and pushed out
through the outlet at high pressure. When connected to misting nozzles, this high-
pressurewaterisatomizedintoextremelyfinedroplets,[Link]
spreadsinthesurroundingenvironment,increasinghumidityorreducing temperature
through evaporative cooling.
The pump’s operation can be controlled using relays, motor drivers, or MOSFET switches, enabling
automatic ON/OFF control based on sensor data such as temperature, humidity, or soil moisture.
• ManualControlButtons
Manual control buttons work on a simple electrical switching principle. When the
button is pressed, it either completes (normally open type) or breaks (normally closed
type)[Link] such as
the ESP32 through a digital input pin.
When the microcontroller senses a HIGH or LOW logic level change at the input pin,
[Link],pressingabuttonmay
activatethemistingpump,[Link]
implemented using polling or interrupt-based methods depending on system
requirements.
0.96-inchOLEDSSD1306(Display)
ItusesOrganicLEDs(OLEDs),meaningeachindividualpixellightsuponitsown.
Thisgives it fantastic contrast (deep blacks) and a wide viewing angle. It typically uses *I2C* or *SPI*
to talk to a microcontroller (like an Arduino or ESP32).
HC-SR04(UltrasonicSensor)
pg. 18
Fig. 3.8 Ultrasonic Sensor
PiezoBuzzer
Inside is a piezoelectric ceramic element. When you apply an electrical voltage, the material
physically flexes. By toggling the voltage on and off quickly (using PWM), you cause it to
vibrate and create sound waves (beeps, tones, or melodies).
An easy, low-power wayto give audio feedback. In your setup, it could actas an alarmif the
HC-SR04 detects something too close, or if the INA219 detects a power surge.
1N4007 Diode
Astandard,general-purposesiliconrectifierdiode.
It acts as a *one-way valve* for electricity. Current can flow easily from the anode (positive
side)tothecathode(markedbythesilverstripe),[Link] rated to
handle up to 1 Amp of current and up to 1000 Volts.
INA219(PowerMonitoring Sensor)
AdigitalcurrentandvoltagemonitorthatcommunicatesoverI2C.
Itmeasuresboththe*high-sidevoltage*(thevoltagebeingsuppliedtoaload)andthe
*shuntvoltage*acrossatiny,[Link]'sLaw(V=IR),itcalculates
theexactamountofcurrentpassingthroughthecircuitandmultipliesitbythevoltage to give you the real-time
*power consumption* (in Watts)
pg. 20
SMPS(Switched-ModePowerSupply)
Ahighlyefficientelectronicpowersupplythatconvertselectrical power.
Unlike old-school, heavy linear power supplies that waste excess voltage as heat, an SMPS
rapidly switches a power transistor on and off to step down voltage cleanly and efficiently.A
standard phone charger or a desktop computer power brick are common examples. It will
provide the stable, clean DC voltage (typically 5V or 12V) needed to power your
microcontroller, sensors, and display without overheating.
pg. 21
Chapter4
SoftwareDesignandImplementation
WehavecreatedawebserverandDashboardusingBlynkCloud
pg. 22
Chapter5FutureWork
The Automated Mist Cooling System using IoT developed in this project provides an efficient
and reliable solution for temperature and humidity control. However, there are several
enhancements and extensions that can be implemented in the future to improve system
performance, scalability, and intelligence.
One major improvement can be the integration of advanced sensors such as high-accuracy
temperature and humidity sensors, air quality sensors, and pressure sensors to obtain more
precise environmental data. This would enable better control decisions and enhance system
reliability in diverse operating conditions.
The system can be further enhanced by incorporating artificial intelligence and machine
[Link],thesystemcanpredictenvironmental
changes and optimize misting duration and frequency automatically. This would result in
improvedenergyefficiency,reducedwaterconsumption,andadaptivecontrolbasedonusage
patterns.
Future versions of the system can also include solar power integration to make it completely
[Link]
can be added to ensure uninterrupted operation during power outages.
TheuseofadditionalcommunicationtechnologiessuchasLoRa, GSM,or NB-IoTcan extend the
system’s range and reliability, especially in agricultural fields or industrial environments
where Wi-Fi connectivity is limited. This would allow large-scale deployment of mist cooling
systems across multiple zones.
Another possible enhancement is the development of a dedicated mobile or web application
withadvancedfeaturessuchasdataanalytics,graphicalreports,alertnotifications,andvoice-
based control. Integration with smart assistants could further improve user interaction.
Finally, the system can be expanded to control multiple misting zones independently using
distributed sensors and pumps. This zonal control approach would provide precise
environmental regulation and make the system suitable for large greenhouses, poultry
farms, and industrial cooling applications.
Inconclusion,theproposedsystemoffers significant scopefor futureadvancements, andwith
these enhancements, it can evolve into a fully intelligent, scalable, and sustainable smart
cooling solution.
pg. 23
Chapter6
6.1 ResultandDiscussion
6.1.1 Result
[Link] HardwarePerformance
The hardware subsystem consisted of temperature and humidity sensors, a soil moisture
sensor, a voltage sensing circuit, a relay-controlled mist pump, and an ESP32
microcontroller. During experimentation, the sensors accurately measured environmental
parameters such as temperature, humidity, soil moisture, and supply voltage. The ESP32
[Link]
respondedcorrectlytobothautomaticcontrolsignalsandmanualcommandsreceivedfrom the
mobile application and Blynk dashboard. The system operated continuously without
communication failure, indicating good stability.
Auser-friendlyAndroidapplicationwasdevelopedusingNiotrontomonitorandcontrolthe system.
The application displayed real-time sensor data using linear progress bars and numeric
labels for soil moisture, humidity, temperature, voltage level, and pump status. Manual
control was provided through HIGH, MID, LOW, and STOP options, while an
[Link]
commands always took priority over automatic operation. The application interface was
responsive, intuitive, and suitable for real-time monitoring.
[Link] BlynkDashboardResults
The Blynk dashboard acted as an additional control and visualization platform. It allowed
real-time observation of sensor readings and remote control of the mist pump. Data shown
ontheBlynkdashboardmatchedthevaluesdisplayedinthemobileapplication,confirming
[Link],enablingsystemcontroleven when
the custom app was not in use.
[Link] CommunicationandDataSynchronization
pg. 24
Communication between the ESP32, cloud server, and mobile application was achieved using
HTTP-based requests through theBlynk [Link] data polling mechanism was
implemented to avoid data conflicts and ensure smooth updates. Sensor data was refreshed
approximately every 1–3 seconds depending on network conditions. The synchronization
among hardware, cloud, and application was consistent and reliable.
6.1.2 Discussion
The results demonstrate that theAutomated Mist Cooling System is efficient, reliable, and
suitable for real-world applications. The integration of IoT hardware with cloud services and
a mobile application enables smart environmental control with minimal human intervention.
[Link] EffectivenessofAutomaticControl
The automatic mode effectively activated mist cooling based on environmental conditions,
thereby maintaining optimal temperature and humidity levels. This approach reduced
unnecessaryoperationofthemistpump,[Link]
especially beneficial in environments such as greenhouses, agricultural fields, industrial
cooling zones, and livestock shelters.
[Link] ManualOverrideandOperationalSafety
The inclusion of manual override enhanced system safety and flexibility. Users could
immediately take control of the system in case of abnormal conditions or specific
requirements. This dual-mode operation improved user confidence and ensured reliable
system behavior under all operating scenarios.
The use of linear progress bars, formatted numeric labels, and color-based indicators
improved readability and quick interpretation of sensor data. The mobile application
interfacewassimplerandmoreaccessiblecomparedtotraditionalcontrolpanels,makingit suitable
for non-technical users.
pg. 25
6.2 Conclusion
The Automated Mist Cooling System using IoT presented in this project successfully
demonstrates an efficient, reliable, and intelligent approach to environmental temperature
and humidity control. By integrating sensors, a microcontroller, and IoT technology, the
systemautomatesthemistingprocessbasedonreal-timeenvironmentalconditions,thereby
reducing manual intervention and improving operational efficiency.
The system utilizes an ESP32 microcontroller along with temperature, humidity, and soil
moisture sensors to continuously monitor surrounding conditions. When the sensed
parameters exceed predefined threshold values, a DC misting pump is activated
automatically to provide effective cooling through evaporative misting. The inclusion of
manualcontrolbuttonsensuressystemreliabilitybyallowinguseroverrideandemergency
control during sensor failure or network unavailability.
The integration of a cloud-based IoT platform enables real-time monitoring, remote control,
[Link] and
supports timely decision-making. Compared to conventional cooling methods, the proposed
system consumes less energy and water, making it environmentally friendly and cost-
effective.
Overall, the implemented system proves to be a practical solution for applications such as
agriculture, greenhouses, poultry farms, industrial cooling, and outdoor environments. The
project highlights the potential of IoT in developing smart, sustainable, and scalable cooling
[Link],thesystemcanbeexpandedintoamoreintelligentand
autonomous environmental control platform.
pg. 26
6.3 FutureScope
The Automated Mist Cooling System using IoT has significant potential for further
enhancement and large-scale deployment. In the future, the system can be upgraded by
integratingadvancedandhigh-precisionsensorsfortemperature,humidity,airquality,and
pressure monitoring to improve accuracy and system responsiveness.
The system can be extended by incorporating artificial intelligence and machine learning
techniques to analyze historical environmental data and predict cooling requirements. This
predictivecontrolapproachwouldoptimizemistingduration,reducewaterconsumption,and enhance
energy efficiency.
Integration of renewable energy sources such as solar power can make the system more
sustainable and suitable for remote or rural areas. Additionally, advanced battery
managementsystemscanbeimplementedtoensureuninterruptedoperationduringpower
outages.
The communication range and reliability can be improved by adopting technologies such as
LoRa,GSM,orNB-IoT,enablingthesystemtooperateeffectivelyinlargeagriculturalfields and
industrial environments where Wi-Fi connectivity is limited.
Future enhancements may also include multi-zone mist control, where different areas are
[Link]-scale
greenhouses, poultry farms, and industrial cooling applications. With these advancements,
the proposed system can evolve into a fully intelligent, scalable, and eco-friendly smart
cooling solution.
pg. 27
References
1. [Link],“That‘InternetofThings’Thing,”RFIDJournal,vol.22,no.7,pp.97–114, 2009.
2. Nayyar and V. Puri, “Smart Farming: IoT Based Smart Irrigation System,”
InternationalJournalofAdvancedResearchinComputerScience,vol.7,no.3,pp.1–5, 2016.
3. [Link],[Link],[Link],“DesignandDevelopmentofPrecision Agriculture
System Using Wireless Sensor Network,” IEEE International Conference on
Automation, Control, Energy and Systems, pp. 1–6, 2014.
4. M.A. Salam and S. M. Hasan, “Temperature and Humidity Monitoring System Using
IoT,” International Journal of Computer Applications, vol. 179, no. 25, pp. 30–34,
2018.
5. ESP32TechnicalReferenceManual,EspressifSystems,2023.
6. DHT11TemperatureandHumiditySensorDatasheet,AosongElectronicsCo.,Ltd.
7. BlynkInc.,“BlynkIoTPlatformDocumentation,”2023.
8. [Link] [Link],InternetofThings:PrinciplesandParadigms,Morgan Kaufmann,
2016.
9. S. Madakam, R. Ramaswamy, and S. Tripathi, “Internet of Things (IoT):A Literature
Review,”JournalofComputerandCommunications,vol.3,no.5,pp.164–173,2015.
10. DCDiaphragmWaterPumpDatasheet,GenericManufacturerDocumentation.
pg. 28
Appendix
AppendixA:BriefDescriptionofSourceCodeFiles
A.1 [Link]
Purpose:
[Link] is the main program of the Smart Mist Cooling System. It initializes all hardware
modules,establishesWi-Ficommunication,startstheHTMLwebserver,andcontinuously
executes the main control loop.
Functions:
Initializessensorsandperipherals.
Updatesthefuzzylogiccontroller.
RefreshestheOLEDdisplay.
Processesusercommandsfromthewebinterface.
A.2 [Link]
Purpose:
Thisfilestoresallsystemconfigurationparametersandhardwaresettingsinoneplace.
Functions:
pg. 29
Defines Wi-Fi credentials.
AssignsESP32GPIO pins.
SetsPWMfrequencyandduty-cyclelimits. Stores
Definestanklevelthresholds.
Configureswebserversettingsandtimingparameters.
A.3 [Link]
Purpose:
[Link].
Functions:
pump state.
Storesfuzzylogicoutput. Stores
PWM value.
Sharesdatabetweendifferentsoftwaremodules.
A.4 [Link]
Purpose:
Thismoduleacquiresreal-timedatafromallconnectedsensors.
Functions:
ReadstemperatureandhumidityfromtheDHT11sensor.
pg. 30
Measuressoilmoisture.
Readsvoltage,current,andpowerusingtheINA219sensor.
Updatessystemvariablesforfurtherprocessing.
A.5 [Link]
Purpose:
ThismoduleimplementstheMamdaniFuzzyLogicControllerforintelligentpumpspeed control.
Functions:
Performsfuzzificationofsensorinputs.
Appliescentroiddefuzzification.
ConvertstheoutputintoPWMvalues.
Determinesthepumpoperating state.
A.6 [Link]
Purpose:
ThismodulecontrolstheDCmistingpumpthroughtheL298Nmotordriver.
Functions:
pg. 31
GeneratesPWMsignals.
Controlspumpspeed.
SupportsHIGH,MID,LOW,andSTOPmodes.
Protectsthepumpduringabnormal conditions.
A.7 [Link]
Purpose:
Thismodulemanageswirelessnetworkcommunication.
Functions:
ConnectstheESP32totheconfiguredWi-Finetwork. Creates an
DisplaystheassignedIPaddress.
A.8 [Link]
Purpose:
ThismodulecreatesanembeddedHTMLwebserverontheESP32.
Functions:
Hosts the HTML dashboard. Displaysreal-
Receivesbrowserrequests.
pg. 32
Processesusercommands.
Updatessystemparametersthroughthewebinterface.
A.9 [Link]
Purpose:
ThismodulecontrolstheOLEDdisplayusedforlocal monitoring.
Functions:
Displaystemperatureandhumidity.
Showsvoltage,current,andpower.
Showsoperating mode.
DisplaysWi-Ficonnectionstatus.
Cyclesautomaticallybetweendisplaypages.
A.10 [Link]
Purpose:
ThismoduleinterfaceswiththeINA219currentandvoltagesensor.
Functions:
Measures bus voltage.
Measurescurrentconsumption.
Calculates power.
Estimatesenergyconsumptionovertime.
pg. 33
Sendsmeasurementstothecontroller.
A.11 [Link]
Purpose:
Thismodulecalculateselectricalenergyconsumedbythemistingpump.
Functions:
Computesenergyusingmeasuredpowerandoperatingtime.
Providesenergydataformonitoringandanalysis.
A.12 [Link]
Purpose:
Thismodulemeasuresthewaterlevelinsidethestoragetank.
Functions:
Sendstriggerpulses.
Measuresechotime.
Calculates distance.
Determineswaterlevelpercentage.
Detectslow-waterandempty-tank conditions.
A.13 [Link]
Purpose:
Thismodulecontrolsthepiezobuzzerforwarningindications
pg. 34
Functions:
Generatesaudiblealerts.
Warnswhenthewatertan
klevelislow. Indicates
fault conditions.
Alertsusersduringcriticalsystemevents.
A.14 HTMLDashboard
Purpose:
TheHTMLdashboardprovidesabrowser-
basedgraphicalinterfaceformonitoringand controlling the Smart Mist
Cooling System.
Functions:
Displaystemperature,humidity,soilmoisture,andelectricalpara
AllowsuserstoselectAUTO,HIGH,MID,LOW,orS
UpdatesdatainrealtimeoverthelocalWi-Finetwork.
pg. 35
MicroPythonCode
"""
=========================================================
[Link]
=========================================================
Contains
✓ DHT11
✓ Soil Moisture
✓ Piezo Buzzer
=========================================================
"""
import time
import dht
import config
class SensorManager:
def __init__(self):
pg. 36
# --------------------------
# DHT11
# --------------------------
[Link] = dht.DHT11(
Pin(config.DHT_PIN)
self.last_temp = 0
self.last_hum = 0
# --------------------------
# Soil Sensor
# --------------------------
[Link] = ADC(
Pin(config.SOIL_PIN)
[Link](ADC.ATTN_11DB)
# --------------------------
# Ultrasonic
# --------------------------
[Link] = Pin(
config.TRIG_PIN,
[Link]
[Link] = Pin(
pg. 37
config.ECHO_PIN,
[Link]
[Link](0)
# --------------------------
# Buzzer
# --------------------------
[Link] = Pin(
config.BUZZER_PIN,
[Link]
[Link]()
# =====================================================
# DHT11
# =====================================================
def read_dht(self):
try:
[Link]()
self.last_temp = [Link]()
self.last_hum = [Link]()
pg. 38
except:
pass
# =====================================================
# Soil Moisture
# =====================================================
def soil_percent(self):
raw = [Link]()
raw = max(
min(raw, config.SOIL_DRY),
config.SOIL_WET
percent = int(
(config.SOIL_DRY - raw)
* 100
(config.SOIL_DRY - config.SOIL_WET)
pg. 39
if percent < 0:
percent = 0
percent = 100
return percent
# =====================================================
# Ultrasonic
# =====================================================
def distance_cm(self):
[Link]()
time.sleep_us(2)
[Link]()
time.sleep_us(10)
[Link]()
timeout = 30000
start = time.ticks_us()
while [Link]() == 0:
if time.ticks_diff(
time.ticks_us(),
start
pg. 40
) > timeout:
return None
pulse_start = time.ticks_us()
while [Link]() == 1:
if time.ticks_diff(
time.ticks_us(),
pulse_start
) > timeout:
return None
pulse_end = time.ticks_us()
duration = time.ticks_diff(
pulse_end,
pulse_start
return distance
# =====================================================
# Water Level %
# =====================================================
def tank_level(self):
pg. 41
distance = self.distance_cm()
if distance is None:
return 0
level = (
config.TANK_HEIGHT
- distance
) * 100 / config.TANK_HEIGHT
if level < 0:
level = 0
level = 100
return int(level)
# =====================================================
# Tank Status
# =====================================================
def tank_empty(self):
return (
pg. 42
self.tank_level()
<=
config.EMPTY_LEVEL
# =====================================================
# Buzzer
# =====================================================
def update_buzzer(self):
if self.tank_empty():
[Link]()
else:
[Link]()
# =====================================================
# Read Everything
# =====================================================
def read_all(self):
soil = self.soil_percent()
pg. 43
tank = self.tank_level()
self.update_buzzer()
return {
"temperature": temp,
"humidity": hum,
"soil": soil,
"tank": tank,
"tank_empty": self.tank_empty()
# =====================================================
# =====================================================
def update(self):
data = self.read_all()
[Link] = data["temperature"]
pg. 44
[Link] = data["humidity"]
[Link] = data["soil"]
state.tank_level = data["tank"]
state.tank_empty = data["tank_empty"]
return data
# =====================================================
# Global Object
# =====================================================
sensors = SensorManager()
"""
=========================================================
[Link]
=========================================================
"""
import socket
import time
import config
pg. 45
from state import state
class WebServer:
# =====================================================
# Constructor
# =====================================================
def __init__(self):
[Link] = [Link]()
[Link](
socket.SOL_SOCKET,
socket.SO_REUSEADDR,
try:
[Link](
"[Link]",
config.WEB_PORT
except OSError as e:
pg. 46
print("Web Server Bind Error :", e)
return
[Link](
config.WEB_BACKLOG
[Link](
config.WEB_TIMEOUT
print()
print("========================================")
print("----------------------------------------")
print(" AP : [Link]
print("========================================")
print()
# =====================================================
# System Health
# =====================================================
pg. 47
def health(self):
# Highest Priority
if state.tank_empty:
state.system_health = "WARNING"
return "WARNING"
# Router Lost
if not state.router_connected:
# Cloud Lost
if not state.blynk_connected:
state.system_health = "LOCAL"
return "LOCAL"
state.system_health = "NORMAL"
return "NORMAL"
# =====================================================
# ESP32 Uptime
# =====================================================
pg. 48
def uptime(self):
seconds = int(
[Link]()
state.start_time
seconds %= 86400
seconds %= 3600
minutes = seconds // 60
seconds %= 60
if days > 0:
return (
pg. 49
).format(
days,
hours,
minutes,
seconds
return (
).format(
hours,
minutes,
seconds
# =====================================================
# =====================================================
def update_time(self):
pg. 50
now = [Link]()
state.last_refresh = (
"{:02d}:{:02d}:{:02d}"
).format(
now[3],
now[4],
now[5]
# =====================================================
# HTML Header
# =====================================================
def html_head(self):
return f"""
<!DOCTYPE html>
<html>
<head>
pg. 51
<meta charset="utf-8">
<meta
name="viewport"
content="width=device-width,initial-scale=1">
<meta
http-equiv="refresh"
content="{config.WEB_REFRESH}">
<title>
</title>
<style>
*{
box-sizing:border-box;
margin:0;
padding:0;
body{
background:#edf2f7;
pg. 52
font-family:Arial,Helvetica,sans-serif;
padding:20px;
.container{
max-width:1000px;
margin:auto;
background:white;
padding:20px;
border-radius:18px;
h1{
text-align:center;
color:#1565C0;
margin-bottom:20px;
pg. 53
}
.health{
padding:12px;
border-radius:10px;
background:#E3F2FD;
text-align:center;
font-size:20px;
font-weight:bold;
margin-bottom:20px;
.grid{
display:grid;
grid-template-columns:
repeat(auto-fit,minmax(220px,1fr));
gap:15px;
pg. 54
.card{
background:#fafafa;
padding:15px;
border-radius:10px;
.card h3{
font-size:18px;
color:#444;
margin-bottom:10px;
.value{
font-size:28px;
font-weight:bold;
color:#1976D2;
pg. 55
}
.buttons{
margin-top:25px;
text-align:center;
button{
width:120px;
height:45px;
margin:8px;
border:none;
border-radius:8px;
font-size:16px;
font-weight:bold;
color:white;
cursor:pointer;
transition:0.2s;
pg. 56
}
.stop{
background:#d32f2f;
.low{
background:#43a047;
.mid{
background:#fb8c00;
.high{
background:#1976d2;
.auto{
background:#7b1fa2;
pg. 57
}
button:hover{
opacity:.9;
.footer{
margin-top:25px;
font-size:15px;
text-align:center;
color:#666;
</style>
</head>
<body>
<div class="container">
<h1>
pg. 58
</h1>
<div class="health">
System Health :
{[Link]()}
</div>
"""
# =====================================================
# =====================================================
def html_cards(self):
return f"""
<div class="grid">
<div class="card">
<h3>🌡 Temperature</h3>
</div>
pg. 59
<div class="card">
<h3>💧 Humidity</h3>
</div>
<div class="card">
</div>
<div class="card">
<h3>⚡ Voltage</h3>
</div>
<div class="card">
<h3>🔋 Current</h3>
</div>
<div class="card">
<h3>⚙ Power</h3>
</div>
<div class="card">
<h3>💡 Energy</h3>
</div>
pg. 60
<div class="card">
<h3>🚿 Pump</h3>
<div class="value">{state.pump_state}</div>
</div>
<div class="card">
<h3>🎯 Mode</h3>
<div class="value">{[Link]}</div>
</div>
<div class="card">
<h3>🚰 Tank</h3>
<div class="value">{tank}</div>
</div>
<div class="card">
<h3>🌐 Router</h3>
<div class="value">{router}</div>
</div>
<div class="card">
<h3>☁️ Blynk</h3>
<div class="value">{blynk}</div>
</div>
<div class="card">
<h3>📡 Hotspot</h3>
<div class="value">{config.AP_SSID}</div>
</div>
<div class="card">
pg. 61
<h3>📍 AP IP</h3>
<div class="value">{state.hotspot_ip}</div>
</div>
<div class="card">
<div class="value">{state.router_ip}</div>
</div>
<div class="card">
<div class="value">{[Link]()}</div>
</div>
</div>
"""
# =====================================================
# HTML Footer
# =====================================================
def html_footer(self):
return f"""
<div class="buttons">
<a href="/cmd?m=stop">
<button class="stop">
STOP
pg. 62
</button>
</a>
<a href="/cmd?m=low">
<button class="low">
LOW
</button>
</a>
<a href="/cmd?m=mid">
<button class="mid">
MID
</button>
</a>
<a href="/cmd?m=high">
<button class="high">
HIGH
</button>
</a>
<a href="/cmd?m=auto">
<button class="auto">
AUTO
</button>
</a>
</div>
<hr>
pg. 63
<div class="footer">
<table
style="width:100%;border-collapse:collapse;">
<tr>
<td><b>Router</b></td>
<td>
</td>
</tr>
<tr>
<td><b>Blynk</b></td>
<td>
</td>
</tr>
<tr>
pg. 64
<td><b>Hotspot</b></td>
<td>
{config.AP_SSID}
</td>
</tr>
<tr>
<td><b>AP IP</b></td>
<td>
{state.hotspot_ip}
</td>
</tr>
<tr>
<td><b>Router IP</b></td>
<td>
{state.router_ip}
</td>
pg. 65
</tr>
<tr>
<td><b>Last Refresh</b></td>
<td>
{state.last_refresh}
</td>
</tr>
</table>
<br>
ESP32 Uptime :
<b>{[Link]()}</b>
</div>
</div>
</body>
</html>
"""
pg. 66
# =====================================================
# =====================================================
def webpage(self):
self.update_time()
page = ""
page += self.html_head()
page += self.html_cards()
page += self.html_footer()
return page
# =====================================================
# Handle Command
# =====================================================
if "/cmd?m=stop" in request:
[Link]("STOP")
pg. 67
[Link]("LOW")
[Link]("MID")
[Link]("HIGH")
[Link]("AUTO")
# =====================================================
# Handle Client
# =====================================================
def handle_client(self):
try:
except OSError:
return
try:
request = [Link](1024)
pg. 68
if not request:
[Link]()
return
request = [Link]("utf-8","ignore")
if "[Link]" in request:
[Link]()
return
self.handle_command(request)
html = [Link]()
[Link](
b"Connection: close\r\n\r\n"
pg. 69
[Link]([Link]())
except Exception as e:
finally:
try:
[Link]()
except:
pass
# =====================================================
# =====================================================
def update(self):
self.handle_client()
# =====================================================
# Print Debug
# =====================================================
def print_debug(self):
print()
pg. 70
print("========== WEB SERVER ==========")
print("===============================")
print()
# =====================================================
# Global Object
# =====================================================
webserver = WebServer()
"""
=========================================================
[Link]
pg. 71
Smart Mist Cooling System
WiFi Manager
Mode :
STA + AP
=========================================================
"""
import network
import time
import config
class WiFiManager:
# =====================================================
# Constructor
# =====================================================
def __init__(self):
# Router Interface
[Link] = [Link](network.STA_IF)
# ESP32 Hotspot
[Link] = [Link](network.AP_IF)
pg. 72
[Link](True)
[Link](True)
# =====================================================
# =====================================================
def start_ap(self):
[Link](
essid=config.AP_SSID,
password=config.AP_PASSWORD,
authmode=network.AUTH_WPA_WPA2_PSK
state.hotspot_ip = [Link]()[0]
print("--------------------------------")
print("--------------------------------")
# =====================================================
pg. 73
# Connect Router
# =====================================================
def connect_router(self):
if [Link]():
state.router_connected = True
state.router_ip = [Link]()[0]
return True
print("Connecting Router...")
[Link](
config.WIFI_SSID,
config.WIFI_PASSWORD
timeout = 20
if [Link]():
state.router_connected = True
state.router_ip = [Link]()[0]
pg. 74
print("--------------------------------")
print("Router Connected")
print("--------------------------------")
return True
timeout -= 1
[Link](1)
state.router_connected = False
state.router_ip = ""
return False
# =====================================================
# Start WiFi
# =====================================================
def start(self):
self.start_ap()
self.connect_router()
# =====================================================
# Auto Reconnect
pg. 75
# =====================================================
def reconnect(self):
if [Link]():
state.router_connected = True
state.router_ip = [Link]()[0]
return
state.router_connected = False
print("Router Lost...")
self.connect_router()
# =====================================================
# RSSI
# =====================================================
def rssi(self):
try:
return [Link]("rssi")
except:
return 0
pg. 76
# =====================================================
# Update
# =====================================================
def update(self):
[Link]()
# =====================================================
# Debug
# =====================================================
def print_debug(self):
print()
print("==========================")
print()
pg. 77
# =====================================================
# Global Object
# =====================================================
wifi = WiFiManager()
"""
=========================================================
[Link]
Compatible with:
BlynkLib v0.2.6
=========================================================
"""
import blynklib
import config
class BlynkManager:
# =====================================================
pg. 78
# Constructor
# =====================================================
def __init__(self):
[Link] = [Link](
config.BLYNK_AUTH_TOKEN
self.register_events()
[Link] = False
# =====================================================
# Register Events
# =====================================================
def register_events(self):
@[Link].handle_event("connect")
def connect_handler():
print("Blynk Connected")
state.blynk_connected = True
[Link] = True
pg. 79
@[Link].handle_event("disconnect")
def disconnect_handler():
print("Blynk Disconnected")
state.blynk_connected = False
[Link] = False
@[Link].handle_event("write V0")
try:
cmd = int(value[0])
except:
return
if cmd == 0:
[Link]("STOP")
elif cmd == 1:
[Link]("LOW")
elif cmd == 2:
pg. 80
[Link]("MID")
elif cmd == 3:
[Link]("HIGH")
elif cmd == 4:
[Link]("AUTO")
# =====================================================
# =====================================================
def send(self):
if not [Link]:
return
[Link].virtual_write(1, [Link])
[Link].virtual_write(2, [Link])
[Link].virtual_write(3, [Link])
[Link].virtual_write(4, [Link])
[Link].virtual_write(5, [Link])
[Link].virtual_write(6, [Link])
pg. 81
[Link].virtual_write(7, round([Link], 4))
[Link],
state.pump_state,
[Link].virtual_write(
8,
status
# =====================================================
# Update
# =====================================================
def update(self):
[Link]()
[Link]()
pg. 82
# =====================================================
# Debug
# =====================================================
def print_debug(self):
print()
print("=========================")
print()
# =====================================================
# Global Object
# =====================================================
blynk = BlynkManager()
"""
[Link]
=========================================================
Hardware Configuration
=========================================================
"""
pg. 83
# =========================================================
# Wi-Fi
# =========================================================
WIFI_PASSWORD = "11111111"
# ESP32 Hotspot
AP_SSID = "SmartMistCooling"
AP_PASSWORD = "12345678"
# =========================================================
# Blynk
# =========================================================
BLYNK_AUTH_TOKEN = "K6WG5sQl5vJ5_NidbQ7dTnJ5yE73kGBT"
BLYNK_TEMPLATE_ID = "TMPLxxxxxxx"
# =========================================================
# =========================================================
PWM_PIN = 19
IN1_PIN = 18
IN2_PIN = 5
PWM_FREQ = 1000
PWM_MAX = 1023
LEVEL_STOP = 0
pg. 84
LEVEL_LOW = int(PWM_MAX * 0.45)
LEVEL_HIGH = PWM_MAX
# =========================================================
# Push Buttons
# =========================================================
BTN_LOW = 23
BTN_MID = 27
BTN_HIGH = 26
BTN_STOP = 14
BTN_AUTO = 15
# =========================================================
# DHT11
# =========================================================
DHT_PIN = 4
# =========================================================
# =========================================================
SOIL_PIN = 34
SOIL_DRY = 3000
SOIL_WET = 1700
# =========================================================
# =========================================================
TRIG_PIN = 32
ECHO_PIN = 33
pg. 85
# Distance from sensor to tank bottom (cm)
TANK_HEIGHT = 20.0
# Alarm Thresholds
LOW_LEVEL = 25 #%
EMPTY_LEVEL = 5 # %
# =========================================================
# Piezo Buzzer
# =========================================================
BUZZER_PIN = 25
# =========================================================
# I2C Bus
# =========================================================
I2C_ID = 0
I2C_SDA = 21
I2C_SCL = 22
I2C_FREQ = 400000
INA219_ADDR = 0x40
# =========================================================
# OLED
# =========================================================
OLED_WIDTH = 128
OLED_HEIGHT = 64
# =========================================================
# Timing
# =========================================================
pg. 86
MAIN_LOOP_DELAY = 1
OLED_REFRESH = 2
WEB_REFRESH = 2
BLYNK_REFRESH = 2
ENERGY_SAVE_INTERVAL = 60
# =========================================================
# (Optimized)
# =========================================================
VP_MODE = "V0"
VP_TEMP = "V1"
VP_HUM = "V2"
VP_SOIL = "V3"
VP_VOLTAGE = "V4"
VP_CURRENT = "V5"
VP_POWER = "V6"
VP_ENERGY = "V7"
VP_TANK = "V8"
pg. 87
I2C_OBJ = I2C(
I2C_ID,
sda=Pin(I2C_SDA),
scl=Pin(I2C_SCL),
freq=I2C_FREQ
WEB_PORT = 80
WEB_TIMEOUT = 0.1
WEB_BACKLOG = 2
"""
=========================================================
[Link]
Energy Calculator
=========================================================
"""
import time
class EnergyMeter:
# =====================================================
# Constructor
# =====================================================
pg. 88
def __init__(self):
self.last_time = time.ticks_ms()
# =====================================================
# Reset Energy
# =====================================================
def reset(self):
[Link] = 0.0
self.last_time = time.ticks_ms()
# =====================================================
# Update Energy
# =====================================================
def update(self):
now = time.ticks_ms()
elapsed_ms = time.ticks_diff(
now,
self.last_time
pg. 89
self.last_time = now
elapsed_hour = (
elapsed_ms
/ 1000
/ 3600
# Power is in Watt
energy = (
[Link]
* elapsed_hour
) / 1000
[Link] += energy
return [Link]
# =====================================================
# BOT Unit
# =====================================================
def unit(self):
pg. 90
return [Link]
# =====================================================
# Debug
# =====================================================
def print_debug(self):
print()
print(
"Power :",
round([Link],2),
"W"
print(
"Energy :",
round([Link],6),
"kWh"
pg. 91
print("============================")
print()
# =====================================================
# Global Object
# =====================================================
energy = EnergyMeter()
"""
=========================================================
[Link]
Inputs
------
2. Temperature (°C)
3. Humidity (%)
Output
-------
=========================================================
"""
pg. 92
class FuzzyController:
def __init__(self):
# ==========================================
# Linguistic Variables
# ==========================================
[Link] = (
"DRY",
"NORMAL",
"WET"
[Link] = (
"LOW",
"NORMAL",
"HIGH"
[Link] = (
"LOW",
"NORMAL",
"HIGH"
[Link] = (
"STOP",
"LOW",
pg. 93
"MID",
"HIGH"
# Universe of discourse
# Rule Base
[Link] = []
self.build_rule_base()
# =====================================================
# =====================================================
if x <= a or x >= c:
return 0.0
if x == b:
return 1.0
if x < b:
return (x - a) / (b - a)
pg. 94
return (c - x) / (c - b)
# =====================================================
# =====================================================
if x <= a:
return 1.0
if x >= b:
return 0.0
return (b - x) / (b - a)
# =====================================================
# =====================================================
if x <= a:
return 0.0
if x >= b:
return 1.0
return (x - a) / (b - a)
# =====================================================
pg. 95
# Trapezoidal Membership
# =====================================================
if x <= a or x >= d:
return 0.0
if b <= x <= c:
return 1.0
if a < x < b:
return (x - a) / (b - a)
return (d - x) / (d - c)
# =====================================================
# Soil Membership
# =====================================================
return {
"DRY":
"NORMAL":
"WET":
pg. 96
self.right_shoulder(value, 60, 80)
# =====================================================
# Temperature Membership
# =====================================================
return {
"LOW":
"NORMAL":
"HIGH":
# =====================================================
# Humidity Membership
# =====================================================
return {
pg. 97
"LOW":
"NORMAL":
"HIGH":
# =====================================================
# =====================================================
def output_sets(self):
return {
# =====================================================
# Fuzzification
pg. 98
# =====================================================
def fuzzify(self):
state.soil_membership = self.soil_membership(
[Link]
state.temp_membership = self.temperature_membership(
[Link]
state.hum_membership = self.humidity_membership(
[Link]
# =====================================================
# =====================================================
def build_rule_base(self):
[Link] = [
# -------------------------------------------------
# SOIL = DRY
# -------------------------------------------------
pg. 99
("DRY", "NORMAL", "LOW", "HIGH"),
# -------------------------------------------------
# SOIL = NORMAL
# -------------------------------------------------
# -------------------------------------------------
# SOIL = WET
# -------------------------------------------------
pg. 100
("WET", "LOW", "HIGH", "STOP"),
# =====================================================
# =====================================================
def get_memberships(self):
[Link]()
return (
state.soil_membership,
state.temp_membership,
state.hum_membership
# =====================================================
pg. 101
# Mamdani Max-Min Inference
# =====================================================
def inference(self):
aggregation = {
"STOP": 0.0,
"LOW": 0.0,
"MID": 0.0,
"HIGH": 0.0
soil_label = rule[0]
temp_label = rule[1]
hum_label =rule[2]
output = rule[3]
firing_strength = min(
soil[soil_label],
temp[temp_label],
pg. 102
hum[hum_label]
if firing_strength> aggregation[output]:
aggregation[output] = firing_strength
return aggregation
# =====================================================
# =====================================================
sets = self.output_sets()
if label == "STOP":
a, b, c, d = sets["STOP"]
a, b, c, d = sets["HIGH"]
pg. 103
elif label == "LOW":
a, b, c = sets["LOW"]
return [Link]( x, a, b, c )
else:
a, b, c = sets["MID"]
# =====================================================
# Centroid Defuzzification
# =====================================================
def defuzzify(self):
aggregation = [Link]()
numerator = 0.0
denominator = 0.0
for x in self.X:
mu = 0.0
membership = min(
pg. 104
aggregation[label],
self.output_membership(label, x)
mu = membership
numerator += x * mu
denominator += mu
if denominator == 0:
return 0.0
# =====================================================
# =====================================================
def calculate(self):
output = [Link]()
if output < 0:
output = 0
pg. 105
output = 100
state.fuzzy_output = output
return output
# =====================================================
# =====================================================
def get_pwm(self):
value = [Link]()
if pwm< 0:
pwm = 0
if pwm> 1023:
pwm = 1023
[Link] = pwm
return pwm
# =====================================================
# =====================================================
def get_pump_state(self):
pg. 106
value = state.fuzzy_output
state.pump_state = "STOP"
state.pump_state = "LOW"
state.pump_state = "MID"
else:
state.pump_state = "HIGH"
return state.pump_state
# =====================================================
# Update Controller
# =====================================================
def update(self):
[Link]()
self.get_pwm()
pg. 107
self.get_pump_state()
return {
"output": state.fuzzy_output,
"pwm": [Link],
"pump": state.pump_state
# =====================================================
# Debug
# =====================================================
def print_debug(self):
print("---------------------------")
pg. 108
print("Pump State :", state.pump_state)
print("===========================\n")
# =====================================================
# Global Object
# =====================================================
fuzzy = FuzzyController()
"""
=========================================================
[Link]
INA219 Driver
=========================================================
"""
import struct
import config
pg. 109
class INA219:
# =====================================================
# Register Address
# =====================================================
REG_CONFIG = 0x00
REG_SHUNT_VOLT = 0x01
REG_BUS_VOLT = 0x02
REG_POWER = 0x03
REG_CURRENT = 0x04
REG_CALIBRATION = 0x05
# =====================================================
# Constructor
# =====================================================
def __init__(self):
[Link] = config.INA219_ADDR
self.i2c = config.I2C_OBJ
[Link]()
# =====================================================
# Write Register
# =====================================================
pg. 110
data = [Link](">H", value)
# =====================================================
# Read Register
# =====================================================
data = self.i2c.readfrom_mem([Link],reg, )
return value
# =====================================================
# =====================================================
value = self.read_register(reg)
value -= 65536
return value
pg. 111
# =====================================================
# Configure INA219
# =====================================================
def configure(self):
# Reset
self.write_register(self.REG_CONFIG, 0x800)
# Calibration
self.write_register(self.REG_CALIBRATION, 4096 )
# Configuration
# 32V
# Gain 320mV
# 12-bit ADC
# Continuous
self.write_register(self.REG_CONFIG, 0x3EEF )
# =====================================================
# =====================================================
pg. 112
def bus_voltage(self):
raw >>= 3
# =====================================================
# =====================================================
def shunt_voltage(self):
raw = self.read_signed(self.REG_SHUNT_VOLT )
# =====================================================
# Current (A)
# =====================================================
def current(self):
raw = self.read_signed(self.REG_CURRENT)
return current
# =====================================================
pg. 113
# Power (W)
# =====================================================
def power(self):
raw = self.read_register(self.REG_POWER)
return power
# =====================================================
# Read All
# =====================================================
def read(self):
try:
voltage = self.bus_voltage()
current = [Link]()
power = [Link]()
except:
voltage = 0.0
current = 0.0
pg. 114
power = 0.0
return (voltage,current,power)
# =====================================================
# =====================================================
def update(self):
[Link] = voltage
[Link] = current
[Link] = power
return (voltage,current,power )
# =====================================================
# Global Object
# =====================================================
ina219 = INA219()
"""
=========================================================
[Link]
pg. 115
Main Program
=========================================================
"""
import gc
import time
import config
# =========================================================
# BOOT
# =========================================================
[Link]()
pg. 116
state.start_time = [Link]()
print()
print("========================================")
print("========================================")
print("Booting Firmware...")
print("========================================")
# =========================================================
# INITIALIZE MODULES
# =========================================================
print("Starting WiFi...")
[Link]()
print("Initializing Sensors...")
[Link]()
print("Initializing INA219...")
[Link]()
[Link]()
[Link]()
print()
pg. 117
print("========================================")
print("========================================")
print("[Link]
if state.router_connected:
print("========================================")
print()
# =========================================================
# MAIN LOOP
# =========================================================
while [Link]:
try:
# ---------------------------------------------
# WiFi
# ---------------------------------------------
[Link]()
pg. 118
# ---------------------------------------------
# Sensors
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# Power Monitor
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# Energy Calculation
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# Fuzzy Logic
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# Motor Controller
# ---------------------------------------------
[Link]()
# ---------------------------------------------
pg. 119
# OLED Display
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# Blynk
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# Garbage Collection
# ---------------------------------------------
[Link]()
# ---------------------------------------------
# ---------------------------------------------
[Link](config.MAIN_LOOP_DELAY)
except KeyboardInterrupt:
pg. 120
print()
print("Keyboard Interrupt")
break
except Exception as e:
print()
print(e)
[Link](1)
# =========================================================
# SHUTDOWN
# =========================================================
print()
print("========================================")
print("========================================")
try:
[Link]()
except Exception as e:
pg. 121
print("Motor Stop Error :", e)
try:
[Link] = False
except:
pass
try:
print()
[Link]()
except Exception as e:
try:
print("Disconnecting WiFi...")
[Link]()
[Link](False)
pg. 122
[Link](False)
except Exception as e:
print("WiFiError :", e)
[Link]()
print()
print("========================================")
print("========================================")
"""
=========================================================
[Link]
=========================================================
"""
import config
pg. 123
class MotorController:
# =====================================================
# Constructor
# =====================================================
def __init__(self):
# -----------------------------------------------
# L298N
# -----------------------------------------------
self.in1 = Pin(
config.IN1_PIN,
[Link]
self.in2 = Pin(
config.IN2_PIN,
[Link]
[Link] = PWM(
Pin(config.PWM_PIN),
freq=1000
pg. 124
[Link](0)
[Link]()
[Link]()
# -----------------------------------------------
# Buttons
# -----------------------------------------------
self.btn_stop = Pin(config.BTN_STOP,[Link],Pin.PULL_UP )
self.btn_auto = Pin(config.BTN_AUTO,[Link],Pin.PULL_UP )
# -----------------------------------------------
# PWM Table
# -----------------------------------------------
"MID":760,
"HIGH":1023
pg. 125
self.button_event = None
self.last_interrupt = 0
[Link] = 200
self.attach_interrupts()
# =====================================================
# Attach Interrupts
# =====================================================
def attach_interrupts(self):
self.btn_low.irq(
trigger=Pin.IRQ_FALLING,
handler=self.button_irq
self.btn_mid.irq(
trigger=Pin.IRQ_FALLING,
handler=self.button_irq
pg. 126
self.btn_high.irq(
trigger=Pin.IRQ_FALLING,
handler=self.button_irq
self.btn_stop.irq(
trigger=Pin.IRQ_FALLING,
handler=self.button_irq
self.btn_auto.irq(
trigger=Pin.IRQ_FALLING,
handler=self.button_irq
# =====================================================
# Interrupt
# =====================================================
import time
pg. 127
now = time.ticks_ms()
if time.ticks_diff(
now,
self.last_interrupt
) <[Link]:
return
self.last_interrupt = now
if pin == self.btn_low:
self.button_event = "LOW"
self.button_event = "MID"
self.button_event = "HIGH"
self.button_event = "STOP"
pg. 128
elif pin == self.btn_auto:
self.button_event = "AUTO"
# =====================================================
# Set PWM
# =====================================================
if value < 0:
value = 0
value = 1023
[Link](value)
[Link] = value
# =====================================================
# Stop Pump
# =====================================================
def stop(self):
self.apply_pwm(0)
state.pump_state = "STOP"
pg. 129
[Link] = "MANUAL"
# =====================================================
# Command Processor
# =====================================================
cmd = [Link]()
# --------------------------------------------
# Highest Priority
# Tank Empty
# --------------------------------------------
if state.tank_empty:
[Link]()
return
# --------------------------------------------
# STOP
# --------------------------------------------
if cmd == "STOP":
[Link]()
return
pg. 130
# --------------------------------------------
# AUTO
# --------------------------------------------
if cmd == "AUTO":
[Link] = "AUTO"
state.manual_override = False
return
# --------------------------------------------
# Manual Override
# --------------------------------------------
[Link] = "MANUAL"
state.manual_override = True
# --------------------------------------------
# LOW
# --------------------------------------------
if cmd == "LOW":
self.apply_pwm(
[Link]["LOW"]
pg. 131
)
state.pump_state = "LOW"
return
# --------------------------------------------
# MID
# --------------------------------------------
if cmd == "MID":
self.apply_pwm(
[Link]["MID"]
state.pump_state = "MID"
return
# --------------------------------------------
# HIGH
# --------------------------------------------
if cmd == "HIGH":
self.apply_pwm(
[Link]["HIGH"]
pg. 132
)
state.pump_state = "HIGH"
return
# =====================================================
# Auto Mode
# =====================================================
def auto_update(self):
if [Link] != "AUTO":
return
if state.tank_empty:
[Link]()
return
self.apply_pwm(
[Link]
# =====================================================
# Button Event
pg. 133
# =====================================================
def process_buttons(self):
if self.button_event is None:
return
[Link](
self.button_event
self.button_event = None
# =====================================================
# Update Motor
# =====================================================
def update(self):
# ---------------------------------------------
# Highest Priority
# Tank Protection
# ---------------------------------------------
if state.tank_empty:
if state.pump_state != "STOP":
pg. 134
[Link]()
return
# ---------------------------------------------
# Physical Buttons
# ---------------------------------------------
self.process_buttons()
# ---------------------------------------------
# AUTO Mode
# ---------------------------------------------
self.auto_update()
# =====================================================
# =====================================================
def get_state(self):
return {
"mode": [Link],
"pump": state.pump_state,
"pwm": [Link],
"manual_override": state.manual_override
pg. 135
}
# =====================================================
# Print Status
# =====================================================
def print_debug(self):
print()
print("===========================")
print()
# =====================================================
# Global Object
# =====================================================
pg. 136
motor = MotorController()
"""
=========================================================
[Link]
128x64 I2C
=========================================================
"""
import time
import config
import ssd1306
class OLED:
# =====================================================
# Constructor
# =====================================================
def __init__(self):
pg. 137
[Link] = ssd1306.SSD1306_I2C(
config.OLED_WIDTH,
config.OLED_HEIGHT,
config.I2C_OBJ
[Link] = 0
self.last_change = time.ticks_ms()
self.page_time = 3000
[Link](0)
[Link]()
# =====================================================
# Page Change
# =====================================================
def next_page(self):
now = time.ticks_ms()
if time.ticks_diff(
pg. 138
now,
self.last_change
) >= self.page_time:
[Link] += 1
if [Link]> 3:
[Link] = 0
self.last_change = now
# =====================================================
# Page 1
# =====================================================
def page1(self):
d = [Link]
[Link]("SMART MIST",15,0)
# =====================================================
pg. 139
# Page 2
# =====================================================
def page2(self):
d = [Link]
[Link]("POWER", 40, 0)
[Link]("Pwr :{:.2f}W".format([Link]),0,5)
# =====================================================
# Page 3
# =====================================================
def page3(self):
d = [Link]
[Link]("SYSTEM", 34, 0)
pg. 140
# =====================================================
# Page 4
# =====================================================
def page4(self):
d = [Link]
[Link]("STATUS", 34, 0)
# =====================================================
# Update Display
# =====================================================
def update(self):
self.next_page()
[Link](0)
if [Link] == 0:
self.page1()
[Link] == 1:
pg. 141
self.page2()
[Link] == 2:
self.page3()
else:
self.page4()
[Link]()
# =====================================================
# Global Object
# =====================================================
oled = OLED()
pg. 142