عيون العرب - ملتقى العالم العربي

عيون العرب - ملتقى العالم العربي (https://www.3rbseyes.com/)
-   تحميل كتب مجانية, مراجع للتحميل (https://www.3rbseyes.com/forum31/)
-   -   دورة تدريبية عملية على برمجة الميكروكونترولر PIC بلغة السى :تجاربLab ومشاريع Projects (https://www.3rbseyes.com/t275433.html)

ظل الكيو كو شن كاي 09-22-2011 06:21 PM

التدريب السابع مشروع مقياس درجة حرارة رقمى باستخدام حساس درجة الحرارة lm35
مقدمة :
مقياس الحرارة الرقمي هو اختيار جيد كمشروع للدخول إلى عالم الميكروكنترولر لأنه يوفر فرصة للتعرف على استخدام أجهزة الاستشعار لقياس اشارات العالم الحقيقى التناظرية .
يعتمد هذا المشروع على الميكروكونترولر pic16f877 وحساس درحة الحرارة من النوع lm35 . الحساس lm35 هو حساس تناظرى يقوم بتحويل درجة الحرارة المحيطة به إلى جهد تناظرى . يوصل خرج الحساس إلى أحد المداخل التناظرية للميكروكونترولر لاستخلاص قيمة معادلة لدرجة الحرارة في الشكل الرقمي. يتم عرض درجة الحرارة المحسوبة على شاشة وحدة عرض lcd من النوع 16x2 أى سطرين بكل سطر 16حرف في شكل مقياس مئوى°c ومقياس فهرنيت°f.

ظل الكيو كو شن كاي 09-22-2011 06:22 PM

المعلومات النظرية :
الحساس LM35 لا يحتاج إلى أى معايرة خارجية وجهد خرجه يتناسب مع درجة الحرارة . عامل مقياس scale factor التحويل من درجة حرارة إلى جهد هو 10 mV per °C "10 ملى فولت لكل درجة مئوية" .
توجد عدة أشكال من الحساس LM35 كما فى الشكل .



قياس درجة الحرارة السالبة الأقل من الصفر يحتاج لمصدر جهد سالب وهذا المشروع يتناول فقط قياس درجة الحرارة الموجبة من الصفر وحتى 100 درجة مئوية .
يتم يحويل جهد خرج الحساس إلى عدد رقمى مكون من 10 خانات باستخدام المحول ADC الداخلى بالميكروكونترولر .وحيث أن الجهد المراد قياسه بواسطة المحول ADC يكون فى المدى من صفر إلى واحد فولت (والمناظر لدرجة حرارة من صفر حتى 100 درجة مئوية لأن كل درجة مئوية تعطى خرج قدره 10 ملى فولت) فأن المحول ADC يحتاج إلى جهد مرجع منخفض (بدلا من جهد المنبع Vdd= 5V ) للتحويل من تناظرى لرقمى وذلك للحصول على دقة قياس أفضل . يمكن الحصول على جهد المرجع المنخفض باستخدام زنر دايود ومقاومات أو يمكن استخدام دايودات فقط . يمكنك الحصول على جهد مرجع قدره 1.2V بتوصيل دايودان ومقاومة على التوالى بين طرفى مصدر الجهد كما فى الشكل التالى .


ملحوظة :
بالقياس العملى للجهد عبر الدايودان وجد 1.196 V وقياسه عمليا هام للحصول على نتائج دقيقة .
كما يمكنك استخدام مقاومة 1K بدلا من المقاومة 3.6K .
نحتاج لبعض العمليات الرياضية للتحويل من تناظرى لرقمى :
جهد المرجع 1.196 V والمحول ADC بسعة 10-bit ، لذلك فإن أى جهد دخل فى المدى بين 0-1.196V سوف يتم تحويله إلى عدد رقمى فى المدى بين 0-1023 .
وتكون دقة التحويل ( خارج قسمة المدى الكامل للجهد على المدى الكامل لكود عدد التحويل ليعطى الجهد لكل قسم ) 1.196/1024 = 0.001168 V/Count.
لذلك يكون العدد الرقمى N للخرج المناظر لأى جهد دخل Vin هو N = Vin/0.001168.
مثال :
نفترض أن درجة الحرارة المحيطة هى 26.4 °C .
يكون جهد خرج الحساس 264 mV (0.264 V): .
ويكون كود العدد لخرج المحول ADC : 0.264/0.001168 = 226
إذا عكسنا العملية : أى أن كان لدينا فى خرج المحول ADC عدد رقمى قدره 226 يمكننا العودة للخلف بتحويله إلى جهد الدخل بضربه فى الدقة ثم نحول هذا الجهد إلى درجة الحرارة بالقسمة على عامل قياس الحساس وهو (10 mV/°C) كما يلى :
temperature = 226 * 0.001168 (V/Count) / 0.01 (V/°C) = 26.4 °C
لتجنب استخدام الأعداد الحقيقية التى تحتوى على علامة عشرية متحركة والتى تسمى floating فقط نستخدم عملية ضرب كما يلى (الدقة كعدد صحيح) :
temperature = 226 * 1168 = 263968
عند عرض النتيجة نحتاج لوضع علامة عشرية فى المكان الرابع من اليسار .لذلك تكون درجة الحرارة المحسوبة 26.3968°C والتى هى قريبة بالفعل من الفعلية .
فى هذا المشروع سوف يتم عرض درجة الحرارة بدقة كسر عشرى واحد أى نقوم بقسمة العدد العلوى على 1000 لنحصل على 263 ويتم بيان درجة الحرارة بالشكل 26.3 °C .
بعد اشتقاق درجة الحرارة بالدرجات المئوية يمكنك تحويلها إلى الفهرنيت باستخدام المعادلة البسيطة التالية :
temperature in °F = 9 x temperature in °C /5 + 32
فى هذه الحالة يتم ضرب درجة الحرارة المئوية فى 10 فتتحول 26.3 إلى263 (للتخلص من العلامة العشرية ) ويمكنك استخدام العلاقة :
temperature in °F = 9 x temperature in °C /5 + 320
وحيث إن العدد الذى يمثل درجة الحرارة المئوية قد لا يقبل القسمة على 5 بالضبط ( العدد 263 لا يقبل القسمة على 5 ( يمكنك مرة أخرى التخلص من العلامة العشرية بالضرب مرة أخرى فى 10 وتصبح المعادلة الجديدة :
temperature in °F = 9 x temperature in °C x 10 /5 + 3200
or,
temperature in °F = 18 x temperature in °C + 3200 = 18 x 263+3200 = 7934
أى أن 79.34 °F تكافىء 26.3 °C
فى هذا المشروع سوف يتم عرض النتيحة بالشكل 79.3 °F
الدائرة الكهربية :

ظل الكيو كو شن كاي 09-22-2011 06:23 PM

الدائرة الكهربية :


يتم توصيل جهد المرجع للطرف RA3 . ويوصل خرج الحساس LM35 إلى المدخل التناظرى RA0/AN0 .
تعرض درجة الحرارة على وحدة عرض LCD نوع 16X2 وتعمل فى نظام 4-bit . تستخدم المقاومة المتغيرة 5K للتحكم فى تباين الشاشة . يستخدم المذبذب الداخلى بتردد 4.0 MHz .
البرنامج :

ظل الكيو كو شن كاي 09-22-2011 06:24 PM

كود:

/*
 Digital Thermometer using PIC16F877 and LM35
 Oscillator @ 4MHz, MCLR Enabled, PWRT Enabled, WDT OFF
*/
// LCD module connections
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections
// Define Messages
char message0[] = "LCD Initialized";
char message1[] = "Room Temperature";
// String array to store temperature value to display
char *tempC = "000.0";
char *tempF = "000.0";
// Variables to store temperature values
unsigned int tempinF, tempinC;
unsigned long temp_value;
void Display_Temperature() {
 // convert Temp to characters
 if (tempinC/10000)
  // 48 is the decimal character code value for displaying 0 on LCD
  tempC[0] = tempinC/10000  + 48;
 else tempC[0] = ' ';
 tempC[1] = (tempinC/1000)%10 + 48;        // Extract tens digit
 tempC[2] =  (tempinC/100)%10 + 48;          // Extract ones digit
 // convert temp_fraction to characters
 tempC[4] =  (tempinC/10)%10 + 48;        // Extract tens digit
 // print temperature on LCD
 Lcd_Out(2, 1, tempC);
 if (tempinF/10000)
  tempF[0] = tempinF/10000  + 48;
 else tempF[0] = ' ';
 tempF[1] = (tempinF/1000)%10 + 48;            // Extract tens digit
 tempF[2] =  (tempinF/100)%10 + 48;
 tempF[4] =  (tempinF/10)%10  + 48;
 // print temperature on LCD
 Lcd_Out(2, 10, tempF);
}
void main() {
 ADCON0 = 0 ; // Connect AN0 to ADC module
 ADCON1 = 0b00000101; // Connect AN0, select Vref=AN3 = 1.19V
 TRISB = 0b00000000; // PORTC All Outputs
 TRISA = 0b00001001; // PORTA All Outputs, Except RA0and RA3
 Lcd_Init();                        // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);              // CLEAR display
 Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
 Lcd_Out(1,1,message0);
 Delay_ms(1000);
 Lcd_Out(1,1,message1);            // Write message1 in 1st row
 // Print degree character
 Lcd_Chr(2,6,223);
 Lcd_Chr(2,15,223);
 // Different LCD displays have different char code for degree symbol
 // if you see greek alpha letter try typing 178 instead of 223
 Lcd_Chr(2,7,'C');
 Lcd_Chr(2,16,'F');
 do {
  temp_value = ADC_Read(0);
  temp_value = temp_value*1168;
  tempinC = temp_value/1000;
  tempinC = tempinC*10;
  tempinF = 9*tempinC/5 + 3200;
  Display_Temperature();
  Delay_ms(1000);  // Temperature sampling at 1 sec interval
 } while(1);
}


ظل الكيو كو شن كاي 09-22-2011 06:30 PM

التعليق على البرنامج :

/*PIC16F877
Digital Thermometer using PIC16F688 and LM35
4MHz, MCLR Enabled, PWRT Enabled, WDT OFF
*/
1- التعريف بتوصيلات وحدة العرض LCD بالميكروكونترولر وتشمل :
// LCD module connections
· 6 أطراف توصيل بالمنفذ PORTC
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
· و6 خانات تحكم تناظرها فى سجل التحكم TRISC
·
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections
2- تعريف الرسائل والمتغيرات قبل بداية الدالة الرئيسية وتشمل :
// Define Messages
· الرسالة message0 مصفوفة حروف فى صف واحد وهى النص LCD Initialized
· والرسالة message1 مصفوفة حروف فى صف واحد وهى النص Room Temperature

char message0[] = "LCD Initialized";
char message1[] = "Room Temperature";
· الأشارة إلى سجل المتغير الذى سوف يتم فيه حفظ قيمة درجة الحرارة بالدرجات المئوية على شكل نص للعرض على الشاشة على شكل نص ذو 4 حروف بالصيغة "000.0"
· الأشارة إلى سجل المتغير الذى سوف يتم فيه حفظ قيمة درجة الحرارة بالدرجات الفهرنهيت على شكل نص للعرض على الشاشة

// String array to store temperature value to display
char *tempC = "000.0";
char *tempF = "000.0";
· متغيرات حفظ قيم درجات الحرارة فى المراحل المختلفة للمعالجة
// Variables to store temperature values
unsigned int tempinF, tempinC;
unsigned long temp_value;
3- فى البداية إنشاء دالة "عرض درجة الحرارة " بغرض تسهيل عملية فهم ومتابعة البرنامج فى الدالة الرئيسية وفيها :

void Display_Temperature() {
· تحويل درجة الحرارة إلى حروف
// convert Temp to characters
# اختبار وجود رقم صحيح فى الرقم (الخانة) الأول من اليسار أو الخامس من اليمين بالقسمة على 10000 وفى حالة وجود مثل هذا الرقم أى تحقق شرط if يتم الحصول عليه وتحويله إلى كود أسكى بإضافة العدد 48 إليه ونسخ النتيجة إلى العنصر رقم 0 بالمصفوفة النصية للعرض tempC[0 .
if (tempinC/10000)
// 48 is the decimal character code value for displaying 0 on LCD
tempC[0] = tempinC/10000 + 48;
# وأن لم يوجد مثل هذا الرقم فيوضع مكانه مكان فارغ فى العنصر رقم 0 فى المصفوفة النصية tempC[0]
else tempC[0] = ' ';
· الحصول على خانة العشرات : (القسمة على 1000 وايجاد باقى قسمة الناتح على 10 ) ثم تحويل النتيجة إلى كود أسكى بإضافة العدد 48 ونسخ النتيجة إلى العنصر رقم 1 بالمصفوفة النصية للعرض tempC[1] .

tempC[1] = (tempinC/1000)%10 + 48; // Extract tens digit
· نكرر للحصول على خانة الآحاد ( العنصر tempC[2] )
tempC[2] = (tempinC/100)%10 + 48; // Extract ones digit
· لاحظ أن العنصر tempC[3] متروك لنقطة العلامة العشرية كما فى التعريف
( char *tempC = "000.0"; )

· نكرر للحصول على الكسر العشرى
// convert temp_fraction to characters
tempC[4] = (tempinC/10)%10 + 48; // Extract tens digit
· إرسال (عرض ) درجة الحرارة المئوية بدءا من الصف الثانى والعامود الأول
// print temperature on LCD
Lcd_Out(2, 1, tempC);
· تكرار الخطوات السابقة لدرجات الحرارة بالفهرنهيت
if (tempinF/10000)
tempF[0] = tempinF/10000 + 48;
else tempF[0] = ' ';
tempF[1] = (tempinF/1000)%10 + 48; // Extract tens digit
tempF[2] = (tempinF/100)%10 + 48;
tempF[4] = (tempinF/10)%10 + 48;
// print temperature on LCD
Lcd_Out(2, 10, tempF);
}
4- بداية الدالة الرئيسية :

void main() {
· نبدأ بتهيئة الميكروكونترولر :
# توصيل الطرف RA0/AN0 كمدخل تناظرى ليعمل مع موديول المحول ADC .

ADCON0 = 0 ; // Connect AN0 to ADC module
# تخصيص المدخل AN2 ليعمل مع موديول المحول A/D واختيار توصيل جهد المرجع الخارجى

ADCON1 = 0b00000101; // Select AN0, select Vref=AN3 = 1.19V
# تهيئة جميع أطراف المنفذ PORTC كمخارج .
TRISB = 0b00000000; // PORTB All Outputs
# وتهيئة جميع أطراف المنفذ PORTA كمخارج فيما عدا الأطراف RA3 و RA2فتهىء كمداخل
TRISA = 0b00001001; // PORTA All Outputs, Except RA0 and RA3
· تهيئة وحدة العرض LCD للبدء
Lcd_Init(); // Initialize LCD
· مسح الشاشة
Lcd_Cmd(_LCD_CLEAR); // CLEAR display
· منع عرض المؤشر على الشاشة
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
· إرسال (عرض) الرسالة message0 بدءا من الصف الأول والعامود الأول والتى تنص على LCD Initialized " تم تهيئة وحدة العرض LCD " والتأخير 1 ثانية لاستقرار التهيئة
Lcd_Out(1,1,message0);
Delay_ms(1000);
· عرض الرسالة message1 بدءا من السطر الأول والعامود الأول وتنص على
Room Temperature "درجة حرارة الغرفة أو المحيط"
Lcd_Out(1,1,message1); // Write message1 in 1st row
// Print degree character
· كتابة رمز درجة الحرارة بدءا من السطر الثانى والعامود السادس (المئوية)وفى السطر الثانى والعامود الخامس عشر (الفهرنيت)
Lcd_Chr(2,6,223);
Lcd_Chr(2,15,223);
// Different LCD displays have different char code for degree symbol
// if you see greek alpha letter try typing 178 instead of 223
· كتابة الحرف C فى السطر الثانى والعامود السابع أى بعد رمزها وحرف F فى السطر الثانى والعامود السداس عشر أى بعد رمزها .
Lcd_Chr(2,7,'C');
Lcd_Chr(2,16,'F');
· الدخول إلى حلقة غير منتهية do{…..}while(1) حيث يتم تنفيذ :
do {
# قراءة القيمة التناظرية من المدخل RA0/AN0 وتحويله إلى عدد رقمى ونسخ هذه النتيجة لسجل المتغير temp_value .
temp_value = ADC_Read(0);
· ثم الضرب فى المعامل 1168 (كما تم ذكره بأعلى) ونسج النتيجة إلى المتغير temp_value
·
temp_value = temp_value*1168;
· القسمة على 1000 ونسخ النتيجة لسجل المتغير tempinC
tempinC = temp_value/1000;
· الضرب فى 10 ونسخ النتيجة لسجل المتغير tempinC
tempinC = tempinC*10;
· التحويل من مئوى إلى فهرنيت
tempinF = 9*tempinC/5 + 3200;
· أخيرا استدعاء دالة عرض درحة الحرارة التى سبق إنشاءها فى البداية والتأخير لزمن قدره 1 ثانية للسماح للمحول A/D من أخذ عينة جديدة ومعالجتها وتحديث النتائج وعرضها .
Display_Temperature();
Delay_ms(1000); // Temperature sampling at 1 sec interval
} while(1);
}
النتائج :


الساعة الآن 02:03 PM.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.

شات الشلة
Powered by: vBulletin Copyright ©2000 - 2006, Jelsoft Enterprises Ltd.
جميع الحقوق محفوظة لعيون العرب
2003 - 2011