اول از همه، سلام دنیا! فکر کنم وقتش رسید که بنویسم. به عنوان اولین پست وبلاگم قراره تجربهام در خصوص یک پروژه الکترونیک شخصی رو با شما به اشتراک بذارم.
تابستون برای من معمولاً فرصت غرق شدن داخل الکترونیکه. توی عمق بودن حس خوبی داره. حرف زدن با سختافزار میتونه بهمون دید خوبی از فرایندهای کامپیوتری بده. برای من شخصاً جذابیتش در این بخشه که بجای در اختیار داشتن ۱۶ گیگابایت مموری و یک پردازنده قدرتمند فرضاً I9 یا M1 و…، چیزی که در اختیارمه دارای چند کیلوبایت حافظه و فرکانس پایینی از قدرت پردازندهست. چالش اصلی اینه که در این مواقع چطوری برنامه بنویسم؟ چقدر حواسم به پاکسازی حافظه هست و چقدر روی مرتبه زمانی الگوریتمهام حساسم؟
تعریف ایده و هدف
امسال تابستون گرمی رو سپری میکنیم و خب ظاهراً قراره هرسال بدتر هم بشه 🙂 یک مشکلی که من دارم اینه که وقتی درگیر کار و مطالعه میشم. گذر زمان، مکان، دما و… از دستم میره و به خودم میام میفهمم که ساعتهاست در هوای گرم نشستم و گاهی باعث مریضیم میشه. به عنوان کسی دوست داره وقتی از یک فرضیه مثل فلانجای خونهام برای کار مناسبتتره حرف میزنه، اعداد رو ضمیمهش کنه. تصمیم گرفتم سیستمی رو طراحی کنم که میزان دما و رطوبت رو بصورت در لحظه اندازه بگیره و روی صفحه نمایش گوشیم و داشبورد آنلاین نمایش بده. اینطوری میتونم ازین دیتا استفاده کنم تا عملکرد بهتری داشته باشم.
البته این فقط بخشی از ماجراجویی هست که در ذهن دارم. بصورت قدم به قدم قراره یک سیستم مرکزی طراحی کنم تا بتونه بطور محدود یسری از وسایل خونه رو طبق پارامترهای محیطی کنترل کنه. نکتهای که باید بهش اشاره کنم اینه که من مدرس الکترونیک نیستم و صرفاً علاقهمند به این حوزهام. لذا هرچیزی که در این وبلاگ مینویسم صرفاً اشتراکگذاری تجارب شخصی است. اگر شماهم به این حوزه علاقه دارید دعوت میکنم تا با من همراه باشید.
انتخاب ابزار
من معمولاً سعی میکنم با هرچیزی که در اختیار دارم کارم رو پیش ببرم. مگر اینکه خیلی هدف خاصی رو دنبال کنم. البته که هر از گاهی بصورت حضوری یا آنلاین از فروشگاههای لوازم الکترونیک یکسری بردها و ماژولهایی میخرم که در اون لحظه کاربردی رو براش متصور نیستم. اما بعداً سعی میکنم با ترکیبشون یک پروژه کارآمد شخصی رو پیش ببرم.
قطعات الکترونیک
ابزار اصلی این پروژه برد توسعه NodeMCU ESP8266 است که بر پایه میکروکنترلر ESP8266 ساخته شده. این برد انواع مختلف داره اما نسخهای که من توی این پروژه استفاده کردم یک برد ESP8266 مجهز به Wi-Fi است. همچنین برای اندازهگیری میزان دما و رطوبت هم از سنسور DHT11 استفاده کردم. این سنسور دقت نسبتاً پایین اما سرعت پاسخگویی بالا داره. میشه برای افزایش دقت از DHT22 استفاده کرد تا دیتای بهتری استخراج بشه.
ابزار اصلی الکترونیکی مورد استفاده:
- Bread Board: صفحهای برای جایگذاری و اتصال قطعات بههم
- NodeMCU ESP8266: برد توسعه
- DHT11 Module/Sensor: ماژول/سنسور اندازهگیری دما و رطوبت
- MicroUSB Cable: کابل منبع تغذیه و انتقال داده به برد توسعه
- Jumper Cables: کابلهای جامپر برای اتصال قطعات بههم
ابزار فرعی (اختیاری):
- Battery Li-Ion 18650 3.7v: باطری یونی ۳.۷ ولت
- 3.7v to 5v Boost Converter: ماژول و برد افزاینده ولتاژ ۳.۷ به ۵ ولت
زبان و فریمورک
روشهای مختلفی برای برنامهریزی بردهای NodeMCU ESP8266 وجود داره اما برای اینکه قراره در قدمهای بعدی برای توسعه سرور نگهداری اطلاعات از زبان پایتون استفاده کنیم. من تصمیم گرفتم از فریمورک MicroPython استفاده کنم که برنامهریزی برد هم با زبان پایتون پیش بره. اما شخصاً استفاده از زبان مخصوص Arduino که برپایه زبان CPP رو بیشتر ترجیح میدم. دلیل؟ بخاطر اینکه اونجا میتونی ارتباط بیشتری با سطح برد بگیری و کتابخونههای بیشتری هم در دسترس داری.
مشخصاً میشه از IDEهای مختلفی هم استفاده کرد اما هرآنچه از پایتون برآید بر پایتون نشیند 🙂 و درنتیجه میریم سراغ Thonny که یک IDE ساختهشده با زبان پایتون است. دلیل اصلیتر این انتخاب، وجود ابزار آماده Thonny برای کار با MicroPython و برد ESP8266 است و کارمو خیلی راحتتر میکنه.
مونتاژ قطعات
هر قطعه و برد الکترونیکی معروفی که شما بصورت آنلاین یا حضوری تهییه میکنید، شامل یک نقشه پینها و راهنمای کارکرد با پین و ولتاژ ورودی خروجی است. مخصوصاً ابزارهایی که من در این پروژه استفاده کردم میشه خیلی ساده و آسون باهاشون کارکرد و چالش خاصی ندارن. در ادامه به تصویر زیر دقت کنید تا نحوه اتصال سنسور DHT11 به ESP8266 رو مشاهده کنید.
همهچیز سادهست. طبق نقشه مپهای DHT11 در این تصویر، قطب منفی (GND) به راستترین پایه سنسور و قطب مثبت (3V) به چپترین پایه اون وصل میشه. همچنین برای دریافت اطلاعات از سنسور هم دومین پایه از سمت چپ رو به یکی از پینهای دلخواه برد وصل میشه که من اینجا پین D1 رو انتخاب کردم.
بخش دلخواه
اگر شما هم بعد از خوندن این وبلاگ تصمیم گرفتید تا پروژه خودتون رو انجام بدید. میتونید برای ایجاد منبع تغذیه برد، از یک باطری یونی استفاده کنید. من از مدل Li-Ion 18650 با ولتاژ 3.7V استفاده کردم. اما چون برای عملکرد بهتر برد ESP8266 باید ولتاژ ورودی اون 5V باشه، باید از یک برد افزاینده ولتاژ سر راه باطری استفاده بشه تا ولتاژ باطری رو به ولتاژ مورد استفاده برد تغییر بده. نحوه مونتاژ این قطعات خیلی سادهست. کافیه قطب منفی و مثبت باطری رو به ورودی ولتاژ برد افزاینده بدید و خروجی مثبت و منفی برد رو به برد توسعه وصل کنید.
برنامهریزی برد توسعه
راهاندازی محیط توسعه
بسته به نوع برد توسعه و زبان برنامهنویسی که استفاده میشه، فرایند آمازهسازی محیط توسعه متفاوته. برای آمادهسازی محیط Thonny برای برد ESP8266 و فریمورک MicroPython؛ اول از همه باید آخرین Firmware میکروپایتون رو دانلود و روی برد توسعه نصب کرد. مراحلشم سادهست:
- برد رو به لپتاپ وصل میکنیم
- برنامه Thonny رو باز میکنیم
- از منوی Run گزینه Configure interpreter رو انتخاب میکنیم
- نوع Interpreter روی ESP8266 تنظیم میکنیم
- آدرس پورت USB متصل به لپتاپ رو انتخاب میکنیم
- از پایین سمت چپ گزینه Install or update MicroPython انتخاب میکنیم
- در صفحه بازشده از سهنقطه پایین صفحه روی Select local file کلیک میکنیم
- در نهایت Install رو میزنیم تا فرایند انجام بشه
نکته: اگر بعد از اتمام مراحل نصب، چراغ داخلی برد بصورت ممتد و عجیبی چشمک زد، فرایند موفق نبوده و باید یسری تنظیمات دستی اعمال بشه.
برای اینکه چک کنید تا نصب فریمور موفقیت آمیز بوده. دستور help()
رو در shell تایپ کنید و نتیجه باید راهنمای کار با فریمورک میکروپایتون باشه.
برنامه اصلی
در ابتدا ماژولهای مورد نیاز برای کار را وارد برنامه میکنیم. اما قبل از آن حتماً باید پکیج dht را از Package Manager تانی نصب کنیم.
import dht
import time
import urequests
import network
from machine import Pin
سپس مقادیر ثابت و پینهای مورد استفاده در برنامه را تعریف میکنیم.
P5 = Pin(5, Pin.IN)
LED = Pin(16, Pin.OUT)
WIFI_SSID = ""
WIFI_PASSWORD = ""
API_URL = "http://host/sensors_data"
d = dht.DHT11(P5)
طبق نقشه پینهای ESP8266 پین D1 با عدد GPIO 5 و پین مرتبط با LEDهای داخلی برد نیز با GPIO 16 و GPIO 2 مشخص میشن که من از GPIO 16 استفاده میکنم. همچنین نام و پسورد وایفای، آدرس API آپلود اطلاعات (که در آینده توسعه میدیم) رو مشخص میکنیم. در نهایت یک شئ از کلاس DHT11 میسازیم و پین دریافت اطلاعات رو براش مشخص میکنیم.
حالا وقتشه که به وایفای متصل بشیم و آیپی خودمون رو دریافت کنیم.
# Connect to WiFi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
فرایند خیلی سادهست. اول وایفای رو فعال میکنیم و درخواست اتصال ایجاد میکنیم و تا زمان برقراری اتصال صبر میکنیم. سپس تنظیمات شبکه رو دریافت و نمایش میدیم. تا همینجا بهتره یکبار برنامه رو اجرا کنیم و خروجی رو ببینیم.
میبینیم که با موفقیت به وایفای وصل شد. حالا تست عملکرد LED رو تست میکنیم.
while True:
LED.value(0) # ON
time.sleep(0.5)
LED.value(1) # OFF
time.sleep(0.5)
انتساب مقدار 0 برای پین LED به منزله ولتاژ بالا و روشن شدن چراغ و مقدار 1 هم به منظور عدم ولتاژ و خاموش شدن چراغ است.
در نهایت بصورت دورهای (هر ۱۰ ثانیه) مقدار دما و رطوبت رو از سنسور دریافت میکنیم و به API مربوطه ارسال میکنیم.
try:
print("getting dht data...")
d.measure()
temperature = d.temperature()
humidity = d.humidity()
print(f"temperature: {temperature}")
print(f"humidity: {humidity}")
urequests.post(API_URL, json={"temperature": temperature, "humidity": humidity})
except OSError as e:
print("Error:", e)
time.sleep(9)
فکر میکنم همهچیز واضح باشه 🙂
راهاندازی سرور
خیلی ساده قراره یک API ایجاد کنیم که اطلاعات سنسور رو دریافت کنه و داخل یک دیتابیس Time-Series ذخیره کنه. من اینجا از فریمورک Flask و دیتایس InfluxDB استفاده کردم.
برای راهاندازی دیتابیس InfluxDB میشه از داکر استفاده کرد.
docker run -p 8086:8086 -v myInfluxVolume:/var/lib/influxdb2 influxdb:latest
بعد از اجرای این دستور، پنل مدیریت InfluxDB از آدرس http://localhost:8686 قابل دسترسه و شما میتونید اطلاعات خودتون رو وارد کنید. یک bucket بسازید و در نهایت توکن حسابتون رو دریافت کنید.
کد نهایی سرور به این صورت خواهد بود:
from flask import Flask, request
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
app = Flask(__name__)
token = "<DB-TOKEN>"
org = "<DB-ORG>"
url = "http://localhost:8086"
bucket="test"
write_client = InfluxDBClient(url=url, token=token, org=org)
write_api = write_client.write_api(write_options=SYNCHRONOUS)
@app.route("/sensors_data", methods=["POST"])
def sensors_data():
data = request.get_json()
# Store the data in InfluxDB
point = (
Point("measurement1")
.tag("tagname1", "tagvalue1")
.field("temperature", data["temperature"])
.field("humidity", data["humidity"])
)
write_api.write(bucket=bucket, org=org, record=point)
return {"ok": True}
if __name__ == '__main__':
app.run("0.0.0.0", 8000, True)
در کد بالا اول از همه اطلاعات دیتابیس رو تعریف کردیم. به کلاینت وصل شدیم و یک API برای نوشتن روی دیتابیس ایجاد کردیم. در قدم بعدی با تعریف اندپوینت sensors_data، اطلاعات رو بصورت جیسان دریافت کردیم و در قالب یک Data Point داخل دیتابیس ذخیره کردیم.
ذخیره برنامه در برد
بعد از اجرای سرور حالا آدرس نهایی API رو داخل برنامه برد توسعه وارد میکنیم و یکبار تست میکنیم تا همهچیز به درستی کار کنه. بعد از منوی فایل گزینه Save As رو میزنیم و از پنجره باز شده MicroPython Device رو انتخاب میکنیم. فایل رو با عنوان main.py
ذخیره میکنیم و تمام. حالا باید دکمه RST روی برد رو فشار بدیم تا برد با برنامه جدید بوت بشه. الان باید هر ۱۰ ثانیه چراغ برد چشمک بزنه و یک ریکوئست به API ما ارسال بشه و دیتا روی دیتابیس ذخیره بشه.
دیپلوی کردن سرور
هرچقدر سادهتر بهتر. سخت نمیگیریم. این پروژه شخصیه. میشه خود برنامه رو بصورت خیلی راحت به سرور منتقل کرد و همونجا مستقیماً اجراش کرد یا با کمک یک کانفیگ ساده داکر، وباپلیکیشن و دیتابیس رو کنار هم راهاندازی کرد. من از توضیحات فرایند دیپلوی در اینجا میگذرم اما کانفیگهای داکر رو در ریپوی گیتهاب پروژه قرار میدم تا اگر کسی خواست استفاده کنه.
خروجی نهایی
حالا که سنسور داره کار میکنه. سرور ما بالاست و همهچیز اوکیه. کافیه وارد داشبورد InfluxDB بشیم و یک کوئری ایجاد کنیم تا اطلاعات لحظهای سنسور رو مشاهده کنیم.
همونطور که میبینید نمودار هیستوگرام دو سنسور دما و رطوبت رسم شده و بصورت درلحظه آپدیت میشه.
حالا میشه یک داشبورد ایجاد کرد و این دیتارو در فرمتهای مختلف مشاهده کرد. مثلا داشبوردی که من برای خودم درست کردم به این شکله:
اضافهکاری
خب وقتی دست آدم گرم میشه و از هرجایی یه چیزی بلده. میخواد همرو باهم ترکیب کنه. البته اگر درحال انجام پروژه شخصی هستید این میتونه یه تفریح باشه و اگر در یک شرکت کار میکنید، کمی تأمل کنید.
حالا من چیکار کردم؟ با سواد کمی که از برنامهنویسی IOS و زبان Swift داشتم. به کمک سرچ و ChatGPT تونستم یک لایو ویجت مخصوص IOS درست کنم تا اطلاعات رو از سرور بگیره و روی صفحه نمایش نشون بده.
ایدههای زیاد دیگهای میشه انجام داد. مثلا میشه الگوریتمهای Pattern Recognition روی این اطلاعات اعمال کرد. میشه گزارش هفتگی از تغییر دما/رطوبت خانه تهییه کرد. میشه یسری آلارمها تنظیم کرد که فرضاً اگر دما یا رطوبت خانه به یک حدی رسید به شما ناتیفیکشن بده. میشه طبق دما درجه کولر (کولرهای قدیمی) رو کم و زیاد کرد و…
سخن پایانی
من قراره تجربههام از کارهایی که در این مسیر انجام میدم رو با شما به اشتراک بذارم. همونطور که گفتم، من مدرس هیچکدوم ازین حوزهها نیستم و صرفاً سعی میکنم برای ایدههایی که دارم دنبال ابزار مناسب بگردم و این فرایند رو با شما به اشتراک بذارم. هدف اینه شما با فرایندها و ابزارها و کلیدواژهها آشنا بشید و روی پروژههای خودتون کار کنید.
لینک ریپوی گیتهاب: https://github.com/shahriarshm/monitor-temperature-and-humidity
3 دیدگاه روشن مانیتور کردن دما و رطوبت خانه
بسیار عالی
سلام
مطلب خیلی خوبی بود.
اگه مقدور باشه ویدیو هم بگیری از روند پروژه خیلی خوب میشه.
سلام
مطلب قوی و خوبی بود
ممنون و صد البته ممنون از دوره های یوتیوبتون که میشه به صراحت گفت بهترین دوره های مربوط به بخش asynchurnos بود چنلز و سلری و asyncio
و ببخشید
اینکه دیگه فعالیت یوتیوبتون رو ادامه نمیدید ؟