الاثنين، 1 أبريل، 2013

الدارة المتكاملة DS1307

الدارة المتكاملة DS 1307



اليوم سنعرض موضوعاً جديداً و ممتعاً , سنلقي فيه الضوء على الدارة المتكاملة DS1307 التي تعمل كمؤقت ساعة real time  Clock , تستخدم الDS1307 البروتوكول التسلسي I2C  للتحكم بها , مما يمنحها ميزة كبيرة بالتحكم بها بواسطة خطين فقط من المتحكم .

الشكل الخارجي و التوصيل لهذه الدارة المتكاملة كما يلي :




تنبيه : قيمة المقاومتين هي 2200 أوم  و كريستالة قيمة ترددها 32.768 كيلو هيرتز 



تنبيه : قيمة المقاومتين هي 2200 أوم 

سنلقي الضوء على كيفية التحكم بها من خلال لغة أردوينو البرمجية , و كيفية عرض القيم المتعلقة بالوقت و التاريخ عليها .


في لغة أردوينو عندما نلقي نظرة على أوامر الوقت في هذه اللغة نرى أن أشهرها هي ;()deley و الذي نستخدمه عادة لعمل تأخير زمني بين كل أمر و الأخر , لكن هذا الأمر ليس دقيق ,و لا يستخدم في حالات العدّ الدقيق لأنه يعطي قراءات خاطئة .
  : millis(); أمر

هذا الأمر أكثر دقة من الأمر DELAY  و يعطي تأخير دقيق جداً , لكن قيمة العداد الذي يستخدم هذا الأمر تعود للصفرOverflow To zero بعد 56 يوم ! هذا الأمر أيضاً محدود باستمرار التغذية , في حال انقطاع التغذية عنها يتوقف العد و نعود للصفر من جديد , لذلك لا يستخدم الأمر millis في الساعات ذات العمل الطويل .
مبدأ عمل الدارة المتكاملة DS1307  سهل جداً , إذ ان هذه الدارة المتكاملة تعطي خرجاً للمتحكم بطول 8BIT لكل مسجل موجود داخل هذه الدارة المتكاملة .

من النشرة الفنية لهذه الدارة المتكاملة نرى الجدول التالي و الذي يبين الخرج لكل مسجل و بماذا يتحكم "في الثواني, الدقائق , الساعات ..ألخ "

مثلاً الدقائق نستطيع قراءتها من المسجل ذو العنوان 0x01 و لو أردنا قراءة السنوات نستطيع قراءتها من المسجل ذو العنوان0x06 و هكذا .


لتفاصيل أكثر , كل مسجل يحتوي 8bit و أول 4bit  تتحكم بالأحاد "Ones " و ال 4bit الأخرى تتحكم بالعشرات Tens
و هذا الجدول يوضح الفكرة .



الأمر المهم الآخر , هو أن الدارة المتكاملة DS1307 تعطي قيم الخرج بالنظام الثنائي"  Binary coded decimal"BCD لكن هذا ليس مشكلة بالنسبة لنا , فنحن نستطيع تحويل هذا الكود لقيم سهلة مقروءة للمستخدم بسهولة .

لذلك , و بعد هذا الشرح , تصبح فكرة عمل هذه الدارة سهلة و بسيطة , نقوم باستدعاء المسجل الذي يدل على اقتران معين"الوقت باجزاءها او التاريخ"  ثم نحول القيم التي نحصل عليها من Binary إلى أرقام عشارية Decimal .

المعدات:



سنحتاج لتنفيذ هذه التجربة إلى :

1) بطاقة اردوينو 
2) الدارة المتكاملة DS1307 .
3) بطارية CR 3v .
4) اسلاك توصيل
5) مهتز كريستالي 32.768KHz 
6) BreadBoard .
7) مقاومتين 2.2K .

هناك سؤالين مهمين سيتبادران لذهنك , ما فائدة الكريستالة 32.768KHz  و البطارية 3V ؟

الجواب على السؤال الأول هو ان هذه القيمة للكريستالة تعطي نبضة مرة كل ثانية تقريباً , و هذه النبضة الدقيقة جداً تعتبر مهمة لتغيير قيمة الساعة بشكل صحيح .

البطارية 3V تعمل كبطارية احتياطية تبقي الدارة في حالة عمل حتى و لو انقطعت التغذية الرئيسية عن الدارة , و تبقي الوقت صحيحاً لفترة طويلة .

كتابة البرنامج :


بالنسبة للبرنامج فإننا سنقوم بكتابة الكود بطريقتين :

1) مباشرة باستخدام مكتبة Wire.h الخاصة بالبروتوكول I2C
2) باستخدام مكتبة RTClib.h الخاصة بالمؤقتات الزمنية .




الطريقة الأولى :
 مباشرة باستخدام مكتبة Wire.h الخاصة بالبروتوكول I2C

في هذه الطريقة سنقوم بكتابة عنوان ال DS1307  , ليكون كخادم slave يعطينا البيانات المطلوبة منه في حالة استدعاءه .

ثم سنكتب له القيم التي نريد أن تكون بداية الزمن , ثم نقرأ القيم التي يعطينا إياها الDS1307   في كل مرة نقوم بها باستدعائه .
الكود موجود في الأسفل , يمكننك قراءاته و تطبيقه على المتحكم .

//This code taken from bilder blog http://bildr.org/2011/03/ds1307-arduino/

//Modified By Mohannad Rawashdeh for http://genotronex.blogspot.com/

#include "Wire.h"
#define ADDRESS 0x68
byte Reset = 0x00; //workaround for issue #527


void setup(){
  Wire.begin();
  Serial.begin(9600);
  setDateTime(); //This function where we Put Adjust the time and Date
}

void loop(){
  printDate();//Print the Time and the Date on Serial Monitor
  delay(1000);
}

void setDateTime(){

  byte second =      00; //0-59
  byte minute =      00; //0-59
  byte hour =        17; //0-23
  byte weekDay =     1; //1-7
  byte monthDay =    11; //1-31
  byte month =       2; //1-12
  byte year  =       12; //0-99

  Wire.beginTransmission(ADDRESS);
  Wire.write(Reset); //stop Oscillator

  Wire.write(DecToBcd(second));
  Wire.write(DecToBcd(minute));
  Wire.write(DecToBcd(hour));
  Wire.write(DecToBcd(weekDay));
  Wire.write(DecToBcd(monthDay));
  Wire.write(DecToBcd(month));
  Wire.write(DecToBcd(year));

  Wire.write(Reset); //start 

  Wire.endTransmission();

}

byte DecToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void printDate(){

  // Reset the register pointer
  Wire.beginTransmission(ADDRESS);
  Wire.write(Reset);
  Wire.endTransmission();

  Wire.requestFrom(ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print the date EG  11/2/2013  17:00:00
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

}



كل ما قمنا بعمله في هذا الكود هو كتابة قيم و تخزينها في مسجلات الDS1307 ثم نقوم باستدعاء كل اقتران على حدا .

عيوب هذه الطريقة هي عدم القدرة على الإحتفاظ بقيمة الوقت السابقة حتى بوجود البطارية الإحتياطية , و السبب هو ..


void setDateTime(){

التي تعمل على تعديل قيمة الوقت في كل مرة نشغل بها البرنامج .

الطريقة الثانية : 

باستخدام مكتبة RTClib.h الخاصة بالمؤقتات الزمنية :

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

هذه المكتبة أسهل بكثير و أكثر مرونة و قوة "بالنسبة لي على الأقل " , هناك أمرين في البرنامج سوف اتحدث عنهم اسفل الكود


الكود موجود هنا :
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//This program Modified By : Mohannad Rawashdeh http://genotronex.blogspot.com/
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;

void setup () {
    Serial.begin(9600);
    Wire.begin();
    RTC.begin();

  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}

void loop () {
    DateTime now = RTC.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" since midnight 1/1/1970 = ");
    Serial.println(now.unixtime());
    delay(3000);
}
الأمرالأول المهم في الكود هو التعليمة :


 RTC.adjust(DateTime(__DATE__, __TIME__)):

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


now.unixtime():

يتم ضبط الوقت باستخدام نظام يسمى نظام Unix يقوم على حساب الوقت بالثواني منذ منتصف ليلة 1\1\1970 , و على اساسه نعرف التاريخ الذي نحن فيه الآن .

بعد تحميلك للبرنامج , افتح الSerial Monitor لترى الوقت و التاريخ 

يمكنك عرض النتائج التي تظهر معاك على اي وسيلة عرض"Seven segment,LCD,Etc " .

ارجو أن تكون هذه التدوينة مفيدة لكم , تحياتي 





8 التعليقات :

  1. يعطيك العافية ... يا مهندس ..

    بس عندي استفسار .. اذا ممكن ..
    انا جربت الدائرة مع الاردوينو وكل شي تمام .. بس المشكلة انها بتعلق .. وبدون اي سبب !! يعني الوقت بيوقف .. فجأة .
    فتوقعت السبب يكون من الفولتية مثلا تأثر على الكريستالة ..
    فأضفنا فلتر .. تأثر الوضع واستمرت لفترة اطول لكن بالنهاية رجعت وعلقت ..!

    فلو تكرمت وافدتنا بالموضوع !
    م. حارث زايد
    harthzayed@hotmail.com

    ردحذف
    الردود
    1. اهلاص وسهلاً , بداية أنا لست مهندساً .

      اذا توقف الوقت فهناك عدة اسباب , قد يكون متعلقاً بالبرمجة او متعلقاً بالتوصيل .

      بالنسبة للبرمجة فالأمر
      DateTime now = RTC.now();
      هو المسؤول عن تحديث الوقت في المكتبة , اذا لم تكن قد شبكت اي شيء اضافي مع الأردوينو و قمت فقط بتجربة ال RTC لوحده فالسبب قد يكون مختلفاً .

      بالنسبة للتوصيل و هو الأهم , هو ان قيمة الكريستالة يجب ان تكون دقيقة و هي 32.768KHz غير ذلك ستكون التحديثات للوقت غير صحيحة , اضف لذلك ان ال Backup battery ان لم تكن تنوي بتوصيلها فعليك ان توصلها مع المصدر الرئيسي VCC و لا تتركها بدون توصيل لانها في كثير من الأحيان تنتج اخطاءاً مع هذه المكتبة

      و لا تنسى اضافة ال Pull up resistor و اظن انك قد وصلت بين ال DS1307 و الأردوينو باسلاك طويلة , و هذا يسبب تعليقاً Locked up لأن البروتوكول I2C يتأثر بشكل كبير جداً بطول السلك لذلك يجب ان يكون طول السلك قصيراً قدر الأمكان و ان استمرت المشكلة فاستخدم مقاومتين 10K بدلاً من 2.2k

      حذف
    2. نعم هذه النقاط مأخوذة في الحسبان ...
      .. طبعا اذا اعدنا برمجتها تعمل من جديد .. بدون مشاكل
      لكن يتوقف الوقت بعد عدة ايام ..
      ....
      هل الدائرة مجربة .. ومضمونة ؟ لوقت طويل ؟
      يوجد في المساجد جهاز لتوقيت الصلاة والاذان ..
      هل هي نفس نوع الدي اس ؟ ام تختلف !

      حذف
    3. مفروض ان لا يتوقف الوقت ابداً , و عمرها الأفتراضي منذ بدء التشغيل 20 سنه ! و انا جربتها لمشروع على مدى أكثر من 8 اشهر و لم تعطيني اي اخطاء .

      جهاز الجوامع مغاير تماماً من حيث القطعة المستخدمة و لكن الوظيفة واحدة , كما ان التي بالجوامع لها برامج خاصة لتحويل الوقت من ميلادي لهجري و تتبع تغيير مواقيت الصلاة اعتماداً على خطوط الطول و العرض .

      حذف
  2. كلامك مشجع اخي ..
    الدارة التي نستعملها يوجد بها مرحل .. فهل من الممكن ان يؤثر ذلك عليها ..
    * كيف افصل تأثير تغذية ..دارة الاردوينو عن دارة الدي اس ، ام انها من المفترض ان لا تؤثر عليها ؟؟...وشكرا اخي لردودك ..

    ردحذف
    الردود
    1. يرجع حسب تصميمك , في حالة ال PCB فالتصميم الجيد هو الأساس , و عموماً لا تعد مشكلة اذا كان التصميم فعّالاً

      سهلة عن طريق ال Backup battery فبوضعها تصبح دارة المؤقت مستقلة بذاتها و لا تتأثر بانقطاع التغذية عن الأردوينو

      حذف
  3. اسلام عليكم استاذ مهند بدي اسالك اذا ممكن استخدم DS1307 ATMEGA8 LCD motordc h bridge في نظام ملاحقة شمسية لانه هو مشروع تخرجي اذا ممكن تساعدني في الكود ارجوك اتساعدني
    هذا عنوان Gmail
    blakjak65036@gmail.com

    ردحذف

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