الاثنين، 12 أغسطس، 2013

اعادة التهيئة الذاتية للمتحكم WatchDog Timer الجزء الثالث


Watchdog Timer





في بعض التطبيقات قد نحتاج لعمل تهيئة"تصفير Reset " للمتحكم الأصغري Micro controller في حالة حدوث عطل في البرنامج Locked Up   او لبدء تنفيذ البرنامج من بدايته .

و الذي دفعني أكثر لكتابة هذه التدوينة ليس فقط إكمال سلسلة وضعية الإسبات في الأردوينو Sleep Mode بل نظراً لأنطباع بعض الأصدقاء عند نيتهم ترك البرمجة في ال PIC Microchip و اتجاهم نحو Arduino AVR بالقول أن الأردوينو " هم يخلطون بين الأردوينو كبيئة عمل متكاملة و بين المتحكم AVR "لا تملك المزايا الموجودة في ال PIC و من أهمها WatchDog Timer  , فجوابي لهم سيكون من خلال ما سأعرضه في هذه التدوينة و التي جوابها بأختصار : بلى يمكنها فعل كل ذلك و أكثر .




بالعودة للنشرة الفنية الخاصة بالمتحكم AVR ATmega328 وجدت كل المعلومات اللازمة عن طرق التصفير و التهيئة فيه و تقسم ل 3 أنواع :

1) التصفير الخارجي الذي عند وضع مدخل ال Reset في الوضع LOW طبعاً هذا هو المعروف لنا في العادة و في الأردوينو توجد كبسة صغيرة Reset button  .


Arduino Uno R3 و كبسة التصفير موجودة في الجهة اليسرى العلوية بالقرب من منفذ ال USB 


2) وضع يسمى "Brown Out Detection "BOD و هو قد يكون جديد على البعض لكنه ذو اهمية كبيرة اذا انه يضع المتحكم الأصغري Microcontroller في وضع التصفير اذا هبطت فولتية التغذية عن فولتية محددة "حسب 3 فولتيات مختلفة 4.3 و  2.7  و 1.8 فولت , في الأردوينو 2.7 فولت و لا يمكن الأستفادة منها فعلياً لعدة أسباب " و اذا سنحت الفرصة سأتحدث عنه في وقت أخر" .

3)وضعية ال Watchdog timer  . و هو ما سنتابع حديثنا عنه من الآن فصاعداً .


باختصار شديد يعمل هذا النظام على توليد نبضة صغيرة تقوم بتفعيل داخلي للتهيئة internal Reset مما يعيد عمل البرنامج من الصفر مجدداً بعد أن تنتهي دورة  التصفير المحددة مسبقاً TimeOut و المخطط الزمني لها كما في الشكل .




يعمل نظام ال Watchdog timer على كريستالة داخلية 128KHz  .



كما أن هتاك ميزة أخرى ألا و هي تحديد عامل prescale  لتحديد زمن دورة  وضع التصفير TimeOut بحيث ممكن ان يحدث التصفير بين 16mS إلى 8Sec و هذا ممتاز جداً إذا ما قارناه بالمؤقتات الداخلية التي لا تتجاوز 4s .

لا يعمل ال 
 Watchdog timer فقط على أعادة تهيئة البرنامج فقط بل يعمل ايضاً على مقاطعة وظيفة محددة و تنفيذها عند انقضاء زمن ال timOut او ممكن أن يقوم بوظيفة التصفير و المقاطعة في آن واحد , قد لا تفهم شيئاً من هذا لأنه موضوع جديد بعض الشيء و استخداماته متقدمة بعض الشيء, لكن أكمل باقي المقال حتى تتضح لك الفكرة بالأمثلة .

سنقوم  أولاً بعمل تهيئة للكود المكتوب بحيث أنه بعد 4 ثواني من تشغيل البرنامج يقوم بعمل تهيئة للبرنامج ليبدأ العمل من جديد .


البرامج بشكل عام و كيفية التعامل معها ستجدها في النشرة الفنية الكاملة ص 56 حيث الكودات مكتوبة بلغة الأسيمبلي و ال C .

كل ما ستحتاجه هو فقط هو بطاقة الأردوينو لهذه التجربة و جهاز كمبيوتر .

الكود الأول سيكون لوضع التهيئة فقط .

// Mohannad Rawashdeh
// http://www.genotronex.com/

//Watchdog timer auto reset 

#include <avr/wdt.h>
int t= 250;
int const ledpin=13;

void setup()
{
  Serial.begin(9600);
  delay(100); //Allow for serial print to complete.

  pinMode(ledpin,OUTPUT);
  // Clear the reset flag. 
  MCUSR &= ~(1<<WDRF);
  
  WDTCSR |= (1<<WDCE) | (1<<WDE);

  // set watchdog timeout prescaler value = 4sec
  WDTCSR = (1<<WDE) | (1<<WDP3) ; 
  
  // Enable interrupt.
  WDTCSR |= (1<<WDIE);
  
  Serial.println("Auto Reset happened ! ");
  delay(100);
}



void loop() {
  digitalWrite(13,HIGH);
  delay(t);
  digitalWrite(13,LOW);
  delay(t); 
  // put your main code here, to run repeatedly: 
  
}



سنقوم هنا بجعل المتحكم في حالة سبات sleep mode و ثم عمل ايقاظ له wakeup بواسطة ال watchdog فور انتهاء الزمن المحدد Timeout .


الكود الثاني : وضع التهيئة و المقاطعة  معاً .

// Mohannad Rawashdeh
// http://www.genotronex.com/

//Watchdog timer auto reset 

#include <avr/wdt.h>
#include <avr/sleep.h>
int t= 250;
volatile int ResetFlag=1; // WDT Address 0x000C
int const ledpin=13;
boolean Status=false;
void setup()
{
  Serial.begin(9600);
  delay(100); //Allow for serial print to complete.

  pinMode(ledpin,OUTPUT);
  // Clear the reset flag. 
  MCUSR &= ~(1<<WDRF);
  
  WDTCSR |= (1<<WDCE) | (1<<WDE);

  // set watchdog timeout prescaler value = 4sec
  WDTCSR = (1<<WDE) | (1<<WDP3) ; 
  
  // Enable interrupt.
  WDTCSR |= (1<<WDIE);
  
  Serial.println("Auto Reset happened ! ");
  delay(100);
}

void SleepNow(void){
 // use one of those Sleep mode :
 /*
SLEEP_MODE_IDLE 
SLEEP_MODE_ADC
SLEEP_MODE_PWR_SAVE
SLEEP_MODE_STANDBY
SLEEP_MODE_PWR_DOWN 

Notice :  use SLEEP_MODE_STANDBY with extenal Resonater only
 */
 set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
 sleep_enable();
 sleep_mode();
 sleep_disable(); // The program will continue from here.
// you can detach interrup here , uncomment this line
}




void loop()
{
  if(ResetFlag == 0x01){
  digitalWrite(13,Status);
  Status=!Status;
  ResetFlag=0;
  delay(100);
  SleepNow();
}
 
  
}
 ISR(WDT_vect)
{
  if(ResetFlag == 0x00)
  {
    ResetFlag=0x01;
  }
}



في الكود أمر جديد ألا و هو أمر استدعاء التصفير للمؤقت ISR WDT_vector حيث يجب أعادة تصفير ال Register flag بعد كل عملية و هذا يتم داخل جملة المقاطعة للتفاصيل ص67 من النشرة الفنية .
هذه لمحة عن هذا النوع من المؤقتات , و كلما كتبت برامج أكثر فهمت أكثر مدى أهمية هذا النوع من المؤقتات و كيف توظفها في مشاريعك و دوائرك الكهربائية .

هناك مرجع مفيد لهذا الموضوع من اعداد المهندس عبد الله جلول حول عائلة ال AVR و بالتحديد ATMEGA32   باللغة العربية يمكن الأطلاع عليه من خلال الرابط هنا   و هنا 

طبعاً استفدت جداً في كتابة هذا المقال من Donal Morrissey و كتابته الرائعة حول هذا الموضوع 



تحياتي للجميع








0 التعليقات :

إرسال تعليق

 
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.