Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Raspberry pi pico 2w
120 min
Share

عرض حالة الطقس والجو على صفحة ويب باستخدام لوحة راسبيرى باى بيكو

في هذا الدرس سنتعلّم كيفية عرض حالة الطقس على صفحة ويب باستخدام لوحة راسبيري باي بيكو، بحيث يتم عرض درجة الحرارة ونسبة الرطوبة ومقياس جودة الهواء على صفحة ويب يمكن الوصول إليها من خلال أي حاسوب أو هاتف ذكي متصل بنفس شبكة الواي فاي المتصلة بها لوحة الراسبيري باي بيكو.

Project Video

Overview

Getting the Items

No items found.

Steps

Wiring it Up

قم بتوصيل الأسلاك بين لوحة الراسبيري باي بيكو وحساس الحرارة والرطوبة وحساس جودة الهواء MQ135 كما هو موضح في الصورة التالية:

التوصيلات من لوحة راسبيرى باى بيكو 2W :

•نقوم بتوصيل منفذ ال VBUS بلوحة راسبيرى باى بيكو2W   ← المنافذ الموجبة بلوحة التجارب

•منفذ ال GND بلوحة راسبيرى باى بيكو2W  ←المنافذ السالبة بلوحة التجارب

التوصيلات من حساس الحرارة والرطوبة :

• منفذ ال VCC  للحساس ← المنافذ الموجبة بلوحة التجارب

• منفذ ال GND  للحساس ← المنافذ السالبة بلوحة التجارب

•  منفذ الأشارة للحساس  ← منفذ رقم 27 فى لوحة راسبيرى باى بيكو 2W

التوصيلات من حساس جودة الهواء MQ135:

• منفذ الVCC لحساس جودة الهواء  ← المنافذ الموجبة للوحة التجارب

• منفذ ال GNDلحساس جودة الهواء ← المنافذ السالبة للوحة التجارب

• منفذ A0  لحساس جودة الهواء ← الطرف الحر للمقاومة ال10 كيلو أوم

• الطرف الأوسط بين المقاومة 10 كيلو اوم والمقاومة 20 كيلو اوم ← منفذ رقم 26 في بلوحة راسبيرى باى بيكو 2W

• الطرف الأخر للمقاومة ال 20 كيلو اوم ← المنافذ السالبة بلوحة التجارب

Coding

وظيفة الكود البرمجى التالى هى عرض درجة الحرارة ونسبة الرطوبة ومقياس جودة الهواء على صفحة ويب يمكن الوصول إليها من خلال أي حاسوب أو هاتف ذكي متصل بنفس شبكة الواي فاي المتصلة بها لوحة الراسبيري باي بيكو.

# استيراد الوحدات المطلوبة

import network

import socket

import time

from time import sleep

from machine import Pin, ADC

import dht

import sys

for i in range(3, 0, -1):

   print(f"⏳ {i}...")

   time.sleep(1)

print("✅ جاري بدء تشغيل محطة الطقس...\n")

# إعدادات WiFi

ssid = 'VOLTAAT' # اسم شبكتك

password = '12345678' # كلمة مرور WiFi

# تهيئة حساس DHT11

dht_pin = Pin(27, Pin.IN, Pin.PULL_UP)

sensor = dht.DHT11(dht_pin)

# تهيئة حساس MQ-135 لجودة الهواء (متصل بالمنفذ 26 - ADC0)

mq135_pin = ADC(Pin(26))  # تحويل المنفذ الرقمي إلى منفذ تماثلي

# في Pico، مدى ADC هو 0-3.3V ويعطي قيم من 0-65535 (16-bit)

# مؤشر LED مدمج للإشارة إلى حالة الاتصال

led = Pin("LED", Pin.OUT)

def read_mq135():

   """قراءة بيانات حساس جودة الهواء MQ-135"""

   try:

       # قراءة القيمة التماثلية (0-65535 في Pico)

       raw_value = 65535 - mq135_pin.read_u16()  # استخدام read_u16() بدلاً من read()

       

       # تحويل القيمة إلى نسبة مئوية (0-100%)

       # القيم الأعلى تعني تلوث أقل (هذا يعتمد على توصيل الحساس)

       air_quality_percent = (raw_value / 65535) * 100

       

       # تحديد مستوى جودة الهواء

       if air_quality_percent > 80:

           status = "ممتازة"

           icon = "🌟"

           color = "#00ff00"

           description = "الهواء نقي جداً"

       elif air_quality_percent > 60:

           status = "جيدة"

           icon = "👍"

           color = "#90ff00"

           description = "الهواء جيد ومنعش"

       elif air_quality_percent > 40:

           status = "متوسطة"

           icon = "😐"

           color = "#ffff00"

           description = "بعض الملوثات موجودة"

       elif air_quality_percent > 20:

           status = "سيئة"

           icon = "⚠️"

           color = "#ff9900"

           description = "ينصح بتجنب التعرض الطويل"

       else:

           status = "خطيرة"

           icon = "🚨"

           color = "#ff0000"

           description = "خطر! تجنب البقاء في هذا المكان"

       

       return {

           'raw_value': raw_value,

           'percentage': air_quality_percent,

           'status': status,

           'icon': icon,

           'color': color,

           'description': description

       }

   except Exception as e:

       print(f'خطأ في قراءة MQ-135: {e}')

       return None

def get_air_quality_text():

   """الحصول على نص جودة الهواء المنسق"""

   mq135_data = read_mq135()

   

   if mq135_data:

       # تحويل نسبة الجودة إلى مستوى تلوث (عكسي للعرض)

       pollution_level = 100 - mq135_data['percentage']

       

       # تحديد مستوى التلوث بالكلمات

       if pollution_level < 20:

           pollution_desc = "منخفض جداً"

       elif pollution_level < 40:

           pollution_desc = "منخفض"

       elif pollution_level < 60:

           pollution_desc = "متوسط"

       elif pollution_level < 80:

           pollution_desc = "مرتفع"

       else:

           pollution_desc = "مرتفع جداً"

       

       air_text = f"""

       <div style="margin-top: 10px;">

           <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;">

               <span style="font-size: 2em;">{mq135_data['icon']}</span>

               <span style="background: {mq135_data['color']}; padding: 5px 15px; border-radius: 20px; color: black; font-weight: bold;">

                   {mq135_data['status']}

               </span>

           </div>

           

           <div style="text-align: right; margin: 15px 0;">

               <div><strong>الوصف:</strong> {mq135_data['description']}</div>

               <div><strong>القيمة الخام:</strong> {mq135_data['raw_value']}</div>

               <div><strong>نقاء الهواء:</strong> {mq135_data['percentage']:.1f}%</div>

               <div><strong>نسبة التلوث:</strong> {pollution_level:.1f}% ({pollution_desc})</div>

           </div>

           

           <div style="width:100%; height:20px; background:#ddd; border-radius:10px; margin:15px 0; overflow:hidden;">

               <div style="width:{mq135_data['percentage']}%; height:100%; background:{mq135_data['color']}; border-radius:10px; transition: width 0.5s;"></div>

           </div>

           

           <div style="display: flex; justify-content: space-between; font-size: 0.8em; color: #ddd;">

               <span>تلوث مرتفع</span>

               <span>نقاء مرتفع</span>

           </div>

       </div>

       """

       return air_text

   else:

       return """

       <div style="text-align: center; color: #ff9999; padding: 20px;">

           <span style="font-size: 3em;">❌</span>

           <h3 style="margin: 10px 0;">خطأ في قراءة حساس جودة الهواء</h3>

           <p style="font-size: 0.9em;">تأكد من توصيل MQ-135 بالمنفذ 26 بشكل صحيح</p>

           <p style="font-size: 0.8em; background: rgba(255,0,0,0.2); padding: 5px; border-radius: 5px;">

               ⚡ يحتاج الحساس إلى جهد تغذية 5V

           </p>

       </div>

       """

def connect():

   """الاتصال بشبكة WiFi"""

   wlan = network.WLAN(network.STA_IF)

   wlan.active(True)

   

   # التأكد من عدم وجود اتصال سابق

   if wlan.isconnected():

       wlan.disconnect()

   

   print('جاري الاتصال بالشبكة...')

   wlan.connect(ssid, password)

   

   # وميض LED أثناء محاولة الاتصال

   timeout = 0

   while not wlan.isconnected() and timeout < 20:  # مهلة 20 ثانية

       led.toggle()

       print('.', end='')

       sleep(0.5)

       timeout += 1

   

   if wlan.isconnected():

       led.on()  # تشغيل LED عند نجاح الاتصال

       ip = wlan.ifconfig()[0]

       print(f'\nتم الاتصال بنجاح!')

       print(f'عنوان IP: {ip}')

       return ip

   else:

       print('\nفشل الاتصال بالشبكة')

       led.off()

       return None

def open_socket(ip):

   """فتح socket للاتصالات"""

   if ip is None:

       return None

   

   try:

       address = (ip, 80)

       connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

       connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

       connection.bind(address)

       connection.listen(1)

       print('تم فتح منفذ 80 للاتصالات')

       return connection

   except Exception as e:

       print(f'خطأ في فتح socket: {e}')

       return None

def webpage(reading, air_quality_html):

   """قالب صفحة HTML مع إضافة جودة الهواء"""

   html = f"""

   <!DOCTYPE html>

   <html dir="rtl">

   <head>

       <title>محطة الطقس وجودة الهواء - Raspberry Pi Pico 2W</title>

       <meta charset="UTF-8">

       <meta http-equiv="refresh" content="4">  <!-- تم التغيير من 10 إلى 4 -->

       <meta name="viewport" content="width=device-width, initial-scale=1">

       <style>

           body {{

               font-family: 'Segoe UI', Arial, sans-serif;

               margin: 0;

               padding: 20px;

               background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

               min-height: 100vh;

               color: white;

           }}

           .container {{

               max-width: 1000px;

               margin: 0 auto;

           }}

           h1 {{

               text-align: center;

               margin-bottom: 30px;

               font-size: 2.5em;

               text-shadow: 2px 2px 4px rgba(0,0,0,0.3);

           }}

           .sensors-grid {{

               display: grid;

               grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));

               gap: 25px;

               margin: 20px 0;

           }}

           .sensor-card {{

               background: rgba(255, 255, 255, 0.15);

               backdrop-filter: blur(10px);

               padding: 25px;

               border-radius: 20px;

               box-shadow: 0 8px 32px rgba(0,0,0,0.3);

               border: 1px solid rgba(255,255,255,0.2);

               transition: transform 0.3s;

           }}

           .sensor-card:hover {{

               transform: translateY(-5px);

           }}

           .sensor-card h2 {{

               margin-top: 0;

               font-size: 1.5em;

               border-bottom: 2px solid rgba(255,255,255,0.3);

               padding-bottom: 15px;

               text-align: center;

           }}

           .reading {{

               font-size: 1.2em;

               line-height: 2;

               text-align: right;

           }}

           .update-badge {{

               background: rgba(0,0,0,0.3);

               padding: 8px 20px;

               border-radius: 30px;

               font-size: 0.9em;

               display: inline-block;

               margin: 0 auto 20px;

               text-align: center;

           }}

           .footer {{

               text-align: center;

               margin-top: 30px;

               padding: 20px;

               background: rgba(0,0,0,0.2);

               border-radius: 15px;

               font-size: 0.9em;

           }}

           .note {{

               background: rgba(255,215,0,0.2);

               padding: 15px;

               border-radius: 10px;

               margin-top: 20px;

               font-size: 0.9em;

               border-right: 4px solid gold;

           }}

           .warning {{

               color: #ffd700;

               font-weight: bold;

           }}

           @media (max-width: 600px) {{

               .sensors-grid {{

                   grid-template-columns: 1fr;

               }}

               h1 {{

                   font-size: 1.8em;

               }}

           }}

       </style>

   </head>

   <body>

       <div class="container">

           <h1>🌡️ محطة الطقس وجودة الهواء</h1>

           

           <div style="text-align: center;">

               <div class="update-badge">

                   🔄 يتم التحديث كل 4 ثوانٍ  <!-- تم التغيير من 10 إلى 4 -->

               </div>

           </div>

           

           <div class="sensors-grid">

               <div class="sensor-card">

                   <h2>🌡️ حساس DHT11</h2>

                   <div class="reading">

                       {reading}

                   </div>

                   <div style="font-size:0.8em; color:#ddd; margin-top:15px; text-align:center;">

                       نطاق القياس: 0-50°C, 20-90%

                   </div>

               </div>

               

               <div class="sensor-card">

                   <h2>🌬️ حساس MQ-135</h2>

                   <div class="reading">

                       {air_quality_html}

                   </div>

                   <div style="font-size:0.8em; color:#ddd; margin-top:15px; text-align:center;">

                       يقيس: CO₂, الأمونيا, البنزين, الدخان, أكاسيد النيتروجين

                   </div>

               </div>

           </div>

           

           <div class="note">

               <span class="warning">⚠️ ملاحظات مهمة:</span><br>

               • DHT11 يحتاج إلى مقاومة سحب 10kΩ بين VCC و DATA<br>

               • MQ-135 يحتاج إلى 5V للتغذية (لا يكفي 3.3V من Pico)<br>

               • MQ-135 يحتاج 5-10 دقائق للتسخين بعد التشغيل للحصول على قراءات دقيقة<br>

               • قراءات MQ-135 نسبية وتحتاج معايرة حسب البيئة

           </div>

           

           <div class="footer">

               Raspberry Pi Pico 2W | آخر تحديث: {get_time_string()}<br>

               <span style="font-size:0.8em; opacity:0.7;">عنوان IP: {ip}</span>

           </div>

       </div>

   </body>

   </html>

   """

   return html

def read_dht11():

   """قراءة بيانات حساس DHT11 مع معالجة الأخطاء"""

   try:

       # قياس القراءات من الحساس

       sensor.measure()

       

       # الحصول على القراءات

       temp = sensor.temperature()

       humidity = sensor.humidity()

       

       # التحقق من صحة القراءات

       if humidity > 100 or humidity < 0:

           raise ValueError("قراءة رطوبة غير صحيحة")

       if temp > 60 or temp < -10:

           raise ValueError("قراءة حرارة غير صحيحة")

       

       # تنسيق القراءات مع أيقونات مناسبة

       weather_icon = "☀️" if humidity < 40 else "☁️" if humidity < 70 else "🌧️"

       

       # حساب نقطة الندى

       dew_point = temp - ((100 - humidity) / 5)

       

       reading = f"""

       <div style="text-align: right;">

           <div style="font-size: 3em; text-align: center; margin-bottom: 15px;">{weather_icon}</div>

           <table style="width:100%; border-spacing: 5px;">

               <tr>

                   <td>🌡️ درجة الحرارة:</td>

                   <td><strong>{temp}°C</strong></td>

               </tr>

               <tr>

                   <td>💧 الرطوبة:</td>

                   <td><strong>{humidity}%</strong></td>

               </tr>

               <tr>

                   <td>💦 نقطة الندى:</td>

                   <td><strong>{dew_point:.1f}°C</strong></td>

               </tr>

           </table>

       </div>

       """

       return reading

       

   except Exception as e:

       print(f'خطأ في قراءة الحساس: {e}')

       

       return f"""

       <div style="text-align: center; color: #ff9999; padding: 20px;">

           <span style="font-size: 3em;">⚠️</span>

           <h3>خطأ في قراءة DHT11</h3>

           <p>تأكد من توصيل الحساس بشكل صحيح</p>

           <p style="font-size:0.8em;">{str(e)}</p>

       </div>

       """

def get_time_string():

   """الحصول على نص الوقت الحالي"""

   try:

       import machine

       rtc = machine.RTC()

       current_time = rtc.datetime()

       return f"{current_time[3]}:{current_time[4]:02d}:{current_time[5]:02d}"

   except:

       return "غير متوفر"

def serve(connection):

   """تشغيل خادم الويب"""

   if connection is None:

       print('لا يمكن بدء الخادم بسبب خطأ في الاتصال')

       return

   

   print('\n' + '='*50)

   print('تم بدء تشغيل خادم الويب بنجاح!')

   print('='*50)

   print(f'📱 افتح المتصفح على العنوان: http://{ip}')

   print('='*50 + '\n')

   

   last_reading_time = 0

   reading = "بانتظار القراءة الأولى..."

   air_quality_html = get_air_quality_text()

   read_count = 0

   

   # اختبار أولي للحساسات

   print('🔍 فحص الحساسات:')

   print('   DHT11: ', end='')

   if "خطأ" in reading:

       print('❌ غير متصل')

   else:

       print('✓ متصل')

   

   print('   MQ-135: ', end='')

   if "خطأ" in air_quality_html:

       print('❌ غير متصل')

   else:

       print('✓ متصل')

   print()

   

   while True:

       try:

           # قراءة بيانات الحساسات كل دورة (كل ثانيتين)

           if read_count % 1 == 0:  # كل دورة = كل ثانيتين

               reading = read_dht11()

               air_quality_html = get_air_quality_text()

               print(f'📊 [{get_time_string()}] تم تحديث القراءات (كل ثانيتين)')

           

           # قبول اتصال جديد

           client, addr = connection.accept()

           print(f'👤 تم الاتصال من: {addr[0]}')

           

           # استقبال الطلب

           request = client.recv(1024)

           

           # إرسال صفحة الويب (التي يتم تحديثها كل 10 ثواني بواسطة meta refresh)

           html = webpage(reading, air_quality_html)

           client.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')

           client.send(html)

           client.close()

           

           read_count += 1

           sleep(2)  # انتظار ثانيتين قبل الدورة التالية

           

       except Exception as e:

           print(f'⚠️ خطأ في معالجة الطلب: {e}')

           try:

               client.close()

           except:

               pass

           sleep(1)

# البرنامج الرئيسي

print('='*50)

print('🌟 نظام محطة الطقس وجودة الهواء')

print('='*50)

print('\n⚙️  جاري بدء التشغيل...')

print('\n📌 ملاحظات هامة:')

print('   • DHT11 متصل بالمنفذ 27')

print('   • MQ-135 متصل بالمنفذ 26 (ADC)')

print('   • MQ-135 يحتاج 5V للتغذية')

print('   • انتظر 5-10 دقائق لتسخين MQ-135\n')

try:

   # الاتصال بشبكة WiFi

   ip = connect()

   

   if ip:

       # فتح socket

       connection = open_socket(ip)

       

       if connection:

           # بدء خادم الويب

           serve(connection)

       else:

           print('❌ فشل في فتح socket')

   else:

       print('❌ فشل في الاتصال بشبكة WiFi')

       print('   تأكد من صحة اسم الشبكة وكلمة المرور')

       

except KeyboardInterrupt:

   print('\n\n🛑 تم إيقاف البرنامج بواسطة المستخدم')

   led.off()

   try:

       connection.close()

   except:

       pass

   machine.reset()

   

except Exception as e:

   print(f'❌ خطأ غير متوقع: {e}')

   machine.reset()

Testing it Out

بعد تشغيل النص البرمجي، انتظر في خانة Shell حتى تتصل لوحة الراسبيري باي بيكو بشبكة الواي فاي الخاصة بك بنجاح. بعد ذلك سيظهر لك رابط الموقع الذي ستُعرض عليه حالة الطقس. قم بنسخ هذا الرابط ولصقه في أي متصفح، سواء على الحاسوب أو الهاتف، وستجد أنه يتم عرض درجة الحرارة ونسبة الرطوبة وحالة جودة الهواء على صفحة الويب.

Resources

No items found.