بطاقات جمع البيانات ومعالجة الإشارة
Data Acquisition (DAQ) & Signal Processing
مفهوم DAQ، تحويل ADC/DAC، معدل أخذ العينات، ومصادر الضوضاء في الحقل (المضخات، الأسلاك الطويلة، الرطوبة) — ثم نبني فلاتر Moving Average و Median و EMA ونطبقها على قراءات رطوبة التربة قبل الإرسال.
نظرة عامة على السيشن
بنهاية السيشن ستكون قادراً على
- تشرح مكونات نظام DAQ: الحساس → التكييف → ADC → المعالجة → التخزين/الإرسال.
- تحسب دقة الـ ADC بالمللي فولت وتختار Sampling rate مناسباً للظاهرة الزراعية.
- تميز بين Random noise و Spikes وتختار الفلتر المناسب لكل منهما.
- تطبق Moving Average و Median و EMA على المتحكم بكفاءة ذاكرة.
- تقيس أثر الفلتر رقمياً (RMSE) وبصرياً (Serial Plotter).
التطبيق في مزرعة الكلية
تسجيل رطوبة التربة في حقل الخضر أثناء تشغيل مضخة الري وإطفائها، ومقارنة الإشارة الخام بالإشارة بعد الفلترة لتحديد أفضل فلتر وحجم نافذة لعقدنا.
المُخرج (Deliverable)
كود عقدة يطبق Median + Moving Average على قراءة التربة، مع رسم (Serial Plotter) يثبت تقليل التذبذب، وتوصية مكتوبة بحجم النافذة المناسب.
خطة السيشن (180 دقيقة)
- 0:00 مراجعة مراجعة: المعايرة ونتائج الصوبة 10 د
- 0:10 شرح ما هو DAQ؟ ADC/DAC، الدقة ومعدل العينات 30 د
- 0:40 شرح مصادر الضوضاء الزراعية والفلاتر البرمجية 30 د
- 1:10 محاكاة محاكي الفلاتر التفاعلي + Tinkercad 25 د
- 1:35 استراحة استراحة 10 د
- 1:45 تطبيق Lab: فلترة حقيقية + Serial Plotter + أثر المضخة 35 د
- 2:20 ميداني ميداني: رطوبة التربة أثناء دورة ري 30 د
- 2:50 تقييم اختبار سريع + الواجب 10 د
الأدوات والمكونات
قاموس المصطلحات (Glossary)
Data Acquisition — كل السلسلة من الحساس حتى الرقم المخزن.
عدد القراءات في الثانية (Hz).
لالتقاط تغير ما يجب أن نقرأ بسرعة ضعف سرعة التغير على الأقل.
يحول رقماً إلى جهد — ESP32 فيه DAC على GPIO 25/26.
Least Significant Bit — 3.3V / 4096 ≈ 0.8 mV في ESP32.
تذبذب عشوائي غير مرغوب فوق الإشارة الحقيقية.
قيمة منفردة بعيدة جداً (مثلاً عند تشغيل المضخة).
متوسط آخر N قراءات — ينعّم الضوضاء العشوائية.
القيمة الوسطى لآخر N قراءات — يزيل القفزات تماماً.
Exponential Moving Average — ذاكرة متغير واحد ووزن أكبر للأحدث.
تأخر الإشارة المفلترة عن الحقيقية — ثمن التنعيم.
دوائر قبل الـ ADC: مقسم جهد، مكثف تنعيم، تكبير.
ما هو DAQ؟
30 دقيقةسلسلة جمع البيانات في عقدة حقلية
-
Sensor
يحول الرطوبة لتغير في السعة الكهربية ثم إلى جهد.
-
Signal conditioning
سلك قصير، مكثف 100nF بين الطرف و GND لتنعيم الضوضاء عالية التردد، مقسم جهد إذا كان الخرج أعلى من 3.3V.
-
ADC
يأخذ عينة من الجهد ويحولها لرقم 0–4095.
-
Processing
فلترة + تحويل لوحدات (%) + كشف أخطاء.
-
Storage / Transmission
SD / EEPROM (السيشن 4) أو لاسلكي (السيشن 5+).
الدقة (Resolution)
ADC الـ ESP32: 3.3V / 4096 ≈ 0.8 mV لكل خطوة. ADC الـ Uno: 5V / 1024 ≈ 4.9 mV. لكن الدقة النظرية ≠ الدقة الفعلية: ADC الـ ESP32 غير خطي قرب الطرفين (أقل من 0.15V وأعلى من 3.1V)، لذلك نستخدم analogReadMilliVolts() التي تطبق معايرة المصنع.
كم مرة نقرأ؟ (Sampling rate)
رطوبة التربة تتغير ببطء (ساعات)، والحرارة خلال دقائق. لكن الضوضاء الكهربية سريعة. الاستراتيجية الذكية: نقرأ بسرعة (مثلاً 10 قراءات خلال ثانية)، نفلتر، ثم نخزن/نرسل قيمة واحدة كل 15 دقيقة. هذا يسمى Oversampling.
| المتغير الزراعي | سرعة التغير | فترة التسجيل المقترحة |
|---|---|---|
| رطوبة التربة | بطيء (ساعات) — سريع فقط وقت الري | 15 دقيقة (5 دقائق أثناء الري) |
| حرارة الهواء | متوسط (دقائق) | 5–10 دقائق |
| الإضاءة | سريع (سحب، ظل) | 1–5 دقائق (متوسط) |
| تدفق المياه / المضخة | سريع جداً | لحظي (Interrupt / عداد نبضات) |
الضوضاء والفلاتر البرمجية
30 دقيقة| المصدر | شكل الأثر | العلاج |
|---|---|---|
| تشغيل/إطفاء المضخة (موتور) | Spikes كبيرة لحظية | Median filter + Diode على الموتور + مصدر منفصل |
| سلك حساس طويل (> 2 م) | ضوضاء عشوائية مستمرة | سلك مجدول، مكثف 100nF، Moving Average |
| إرسال Wi-Fi من الـ ESP32 | قفزات صغيرة متكررة | القراءة قبل الإرسال أو أثناء إيقاف Wi-Fi |
| ماء على الإلكترونيات | انجراف (Drift) وقراءات خاطئة | عزل الدائرة — لا علاج برمجي |
| الفلتر | يعالج | الذاكرة | التأخر | متى نستخدمه |
|---|---|---|---|---|
| Moving Average (N) | الضوضاء العشوائية | N قيمة | N/2 عينة | إشارة هادئة بضوضاء صغيرة |
| Median (N فردي) | القفزات (Spikes) | N قيمة + ترتيب | N/2 عينة | بجوار مضخات ومحركات |
| EMA (α) | الضوضاء العشوائية | متغير واحد | يعتمد على α | متحكم صغير الذاكرة |
| Median ثم Average | الاثنين معاً | N + N | أكبر | الخيار الافتراضي لعقدنا الحقلية |
المفاضلة الأهم: التنعيم مقابل التأخر
نافذة كبيرة = إشارة ناعمة لكنها تتأخر في اكتشاف بداية الري. لو قراءتنا كل 10 ثوانٍ ونافذتنا 31 عينة، فنحن نتأخر ~2.5 دقيقة — مقبول لرطوبة التربة، وغير مقبول لكشف عطل مضخة.
Tinkercad: فلاتر على المتحكم
25 دقيقةثلاثة فلاتر على نفس الإشارة + ضوضاء مصطنعة
25 دقيقةنقرأ حساس التربة (أو Potentiometer) ونضيف ضوضاء وقفزات برمجياً لمحاكاة المضخة، ونطبع الإشارة الخام والمفلترة معاً بصيغة يفهمها Serial Plotter.
المكونات (Components)
- Arduino Uno R3
- Soil Moisture Sensor أو Potentiometer
- Wires
التوصيل (Wiring)
| من | إلى | ملاحظة |
|---|---|---|
| Sensor SIG | A1 | |
| VCC / GND | 5V / GND |
الصق الكود وشغّل المحاكاة. في Tinkercad اضغط أيقونة الرسم البياني في Serial Monitor لعرض المنحنيات.
غيّر قيمة الحساس فجأة (محاكاة ري) ولاحظ أي فلتر يستجيب أسرع.
عدّل
MA_Nإلى 30 ولاحظ زيادة التأخر.عدّل احتمال القفزات من 5% إلى 20% في السطر
random(100) < 5.
/*
Session 3 — DAQ & software filters for noisy soil-moisture readings (Arduino Uno / Tinkercad)
Soil Moisture Sensor (or a potentiometer to fake it) on A1.
Prints raw, Moving Average (N=10), Median (N=9) and Exponential (alpha=0.2) — open the Serial Plotter!
*/
const int SOIL_PIN = A1;
// ---- Moving average (circular buffer)
const int MA_N = 10;
int maBuf[MA_N];
int maIdx = 0;
long maSum = 0;
int movingAverage(int x) {
maSum -= maBuf[maIdx];
maBuf[maIdx] = x;
maSum += x;
maIdx = (maIdx + 1) % MA_N;
return maSum / MA_N;
}
// ---- Median of the last 9 samples (removes spikes completely)
const int MED_N = 9;
int medBuf[MED_N];
int medIdx = 0;
int median(int x) {
medBuf[medIdx] = x;
medIdx = (medIdx + 1) % MED_N;
int s[MED_N];
memcpy(s, medBuf, sizeof(s));
for (int i = 1; i < MED_N; i++) { // insertion sort (small N)
int k = s[i], j = i - 1;
while (j >= 0 && s[j] > k) { s[j + 1] = s[j]; j--; }
s[j + 1] = k;
}
return s[MED_N / 2];
}
// ---- Exponential moving average (1 variable of memory — good for tiny MCUs)
float ema = -1;
float expFilter(int x, float alpha = 0.2) {
ema = (ema < 0) ? x : alpha * x + (1 - alpha) * ema;
return ema;
}
void setup() {
Serial.begin(9600);
int first = analogRead(SOIL_PIN);
for (int i = 0; i < MA_N; i++) { maBuf[i] = first; maSum += first; }
for (int i = 0; i < MED_N; i++) medBuf[i] = first;
}
void loop() {
int raw = analogRead(SOIL_PIN);
if (random(100) < 5) raw += random(-300, 300); // inject field noise (pump motor, long cables)
raw = constrain(raw, 0, 1023);
Serial.print("raw:"); Serial.print(raw);
Serial.print(",ma10:"); Serial.print(movingAverage(raw));
Serial.print(",median9:");Serial.print(median(raw));
Serial.print(",ema:"); Serial.println(expFilter(raw), 1);
delay(100); // 10 Hz sampling
}
فلتر مركب: Median ثم Average
اكتب دالة int robustRead(int pin) تأخذ 15 قراءة سريعة (كل 10 ms)، ترتبها، تحذف أعلى 3 وأقل 3 قيم، ثم تعيد متوسط الـ 9 الباقية. هذا يسمى Trimmed mean وهو ما سنستخدمه في عقدة الحقل.
الحل (Solution)
int robustRead(int pin) {
int v[15];
for (int i = 0; i < 15; i++) { v[i] = analogRead(pin); delay(10); }
for (int i = 1; i < 15; i++) { // insertion sort
int k = v[i], j = i - 1;
while (j >= 0 && v[j] > k) { v[j + 1] = v[j]; j--; }
v[j + 1] = k;
}
long sum = 0;
for (int i = 3; i < 12; i++) sum += v[i]; // drop 3 lowest + 3 highest
return sum / 9;
}
Lab: أثر المضخة على القراءة
35 دقيقةقياس تشويش المضخة الحقيقي ومعالجته
- خط الأساس
اغرس الحساس في أصيص تربة رطبة، واقرأ 200 عينة (كل 50 ms) بدون مضخة. احسب الانحراف المعياري (Standard deviation) من البيانات في Excel.
- تشغيل المضخة
شغّل المضخة من نفس مصدر الـ USB ولاحظ القفزات في Serial Plotter.
- علاج كهربي
أضف Diode عكسي على أطراف المضخة (Flyback diode) ومكثف 100nF بين طرف الحساس و GND، وأعد القياس.
- علاج برمجي
طبق
robustRead()من التحدي وقارن الانحراف المعياري في الحالات الثلاث. - التوثيق
سجل جدولاً: الحالة × الانحراف المعياري × أكبر قفزة.
النتيجة المتوقعة: انخفاض الانحراف المعياري لأقل من 1% من المدى بعد العلاج الكهربي + البرمجي.
قاعدة مهندسي الحقل
عالج الضوضاء كهربياً أولاً (أرخص وأضمن)، ثم برمجياً. والأهم: لا تقرأ الحساس في نفس اللحظة التي تشغّل فيها المضخة أو ترسل Wi-Fi.
ميداني: رطوبة التربة أثناء الري
30 دقيقةالتقاط «حدث ري» حقيقي وفلترته
حقل الخضر — خط تنقيط واحد يُشغّل بإذن مشرف المزرعة
- التجهيز
اغرس حساسين: الأول على 10 سم من النقاط (Dripper)، والثاني في منتصف المسافة بين خطين.
- التسجيل
اجعل العقدة تسجل كل 10 ثوانٍ: raw + median9 + ma10 (اربط اللابتوب بالـ USB).
- الري
اطلب من المشرف تشغيل الري 10 دقائق ثم إيقافه، واستمر في التسجيل 10 دقائق بعده.
- التحليل
حدد: متى بدأ الحساس يستجيب؟ كم استغرق للوصول لأعلى قيمة؟ هل ظهرت قفزات عند تشغيل المضخة؟
| الوقت | حدث (بداية/نهاية ري) | حساس 1 خام | حساس 1 مفلتر | حساس 2 خام | حساس 2 مفلتر |
|---|---|---|---|---|---|
- الإلكترونيات داخل علبة بلاستيك أو كيس شفاف أثناء الري.
- اللابتوب على طاولة بعيداً عن الماء.
فكّر وناقش
لماذا تأخرت استجابة الحساس البعيد عن النقاط؟ ماذا يعني ذلك لموقع تركيب الحساس في الحقل؟
لو كانت عقدتنا تسجل كل 15 دقيقة فقط — هل كنا سنلاحظ حدث الري؟
اختبر فهمك
5 أسئلة · نتيجة فوريةالواجب والتسليم
الواجب الأسبوعي (Weekly Assignment)
نفذ
robustRead()على جهازك وارفع لقطة Serial Plotter (قبل/بعد).حلل بيانات حدث الري: احسب زمن الاستجابة لكل حساس واكتب توصية بمكان تركيب الحساس في الحقل.
جرّب في المحاكي التفاعلي: ما أصغر N يعطي RMSE أقل من 40 مع Spikes = 10%؟
قائمة التسليم (Submission Checklist)
مراجع ومصادر
استعد للسيشن القادمة
السيشن القادمة نجعل العقدة تعمل وحدها 24 ساعة: أحضر SD Card Module + بطاقة microSD (FAT32) + بطارية Li-ion 18650 بحاملها.