Real Time Clock DS3231
วันนี้เรานำเสนออุปกรณ์พื้นฐาน Real Time Clock กันครับ
ว่าไปแล้วโมดูล Real Time Clock (RTC) ก็คือ อุปกรณ์ที่ให้ค่าเวลาตามจริง ซึ่งทำงานโดยการจับสัญญานนาฬิกาที่ได้มาจาก Crystal นั่นเองครับ บางรุ่นก็จะมีถ่านสำรองมาให้ด้วย ทำหน้าที่ในการบันทึกเวลาอย่างต่อเนื่องถึงแม้ว่าจะไม่มีไฟเลี้ยงมาที่ตัวบอร์ด ตัวเวลาก็ยังคงนับได้ต่อ ทำให้ไม่ต้องเสียเวลามาตั้งเวลาใหม่หลังจากที่หยุดจ่ายไฟเลี้ยงครับ โมดูล RTC นี้จำเป็นอย่างยิ่งกับการใช้งานที่ต้องมีการบันทึกเวลา (Time Stamp) เช่น อุปกรณ์ Data logger ครับ
หลายคนก็อาจจะสงสัยว่าทำไมเราต้องการ RTC module นี้ในเมื่อ Arduino Board ของเราก็มีตัวจับเวลา เช่น millis() อยู่แล้ว คำตอบก็คือ ไม่โครโปรเซสเซอร์ที่เป็นหัวใจในการทำงานของ Arduino board ทั้งหลายนั้น ต้องทำงานสารพัดอย่างครับ ไม่ว่าจะเป็นคำสังพื้นฐาน เช่น บวก ลบ คูณ หาร ไปจนถึงการติดต่อกับอปุกรณ์ภายนอก คำสั่งที่มากมายซึ่งเราเป็นผู้เขียนลงใน Sketch นั้นจะทำงานแบบ อนุกรม (Serial) ว่าง่ายๆ ก็คือ ทำทีละบรรทัดครับ ทำให้การทำงานของคำสั่งจับเวลาก็จะถูกรบกวนไปด้วย จับได้บ้าง ไม่ได้บ้าง เดี๋ยวโดนสั่งไปทำโน่น โดยแทรก (Interrupt) ไปทำนี่ เวลาที่ได้จากการใช้คำสั่งนี้ ก็เลยไม่สามารถนำมาเป็นเวลาตามจริงที่ต้องการบันทึกไปพร้อมกับค่าอื่นๆ ที่ต้องการวัดได้ครับ
ดังนั้น ในการประยุกต์ใช้กับงานที่ต้องการเวลาที่แม่นยำ และเป็นเวลาตามนาฬิกา ที่บอก วันที่ เดือน ปี ชั่วโมง นาที วินาที ก็เลยจำเป็นต้องใช้อุปกรณ์ที่ทำหน้าที่จับเวลาแยก ซึ่งก็ทำให้ต้องมีสัญญาณนาฬิกาจาก Crystal แยกต่างหากด้วยเช่นกัน ฟังดูแล้วอาจจะคิดว่ามันช่างยุ่งยากเหลือเกิน แตไม่เลยครับ มีคนที่ออกแบบ Chip หลายแบบ ที่ทำหน้าที่นี้มาให้เราเรียบร้อยแล้ว วิธีใช้งานก็ง่ายๆ ติดต่อผ่านไปที่บอร์ดโดยใช้การสื่อสารแบบ I2C หรือ Inter - Integrated Circuit ที่ใช้ SDA SCL VCC และ GND เท่านั้นครับ
ทีนี้การที่มันมีหลายรุ่นก็ทำให้เกิดความงงกันได้ โมดูล RTC นั้นมีอยู่หลายแบบครับ เอาเฉพาะที่ร้าน Arduitronics ขายก็มี 3 รุ่นแล้วครับ ได้แก่ DS3231, DS1302, Tiny RTC I2C 24C32 DS1307 แต่ละรุ่นก็จะมีความต่างกันในเรื่องของความละเอียดในการจับเวลา การมีแบตเตอรี่สำรอง ขนาด และแน่นอนก็คือราคาครับ
ตัวที่ผมจะใช้ในการสาธิตการทำงานของโมดูล RTC วันนี้ก็คือ DS3231 ครับ ตัวนี้จะมีราคาสูงกว่าตัวอื่นนิดหน่อย (แต่ก็ไม่กี่สิบบาทหรอกครับ) แต่ข้อดีของมันก็คือ มีการชดเชยการเปลี่ยนแปลงของสัญญาณนาฬิกา เนื่องจากการเปลี่ยนแปลงของอุณหภูมิแวดล้อมครับ ว่าง่ายๆ ก็คือ เวลาอุณหภูมิเปลี่ยน สัญญาณนาฬิกาจาก Crystal ก็เปลี่ยน ทำให้เวลาก็เพี้ยนไปด้วย แต่โมดูลนี้ได้ทำการวัดค่าอุณหภูมิพร้อมทั้งชดเชยความเปลี่ยนแปลงนี้ไปด้วยแล้ว ทำให้เวลาที่ได้มีความแม่นยำสูงมาก
Data Sheet DS3231
คราวนี้มาถึงการใช้งานกันบ้างครับ ไม่ว่าจะเป็น RTC รุ่นไหน ก็ต้องเริ่มจากการตั้งเวลาครั้งแรกกันก่อนครับ แต่ละรุ่นก็จะมีวิธีการที่แตกต่างกันไป ผมขอเขียนตัวอย่างรุ่น DS3231 เท่านั้นนะครับ รุ่นอื่นก็จะหาได้จาก www.github.com ครับ
1. เริ่่มต้นจากการ Download Library ครับ (ในขณะที่ผมเขียนนี้ Sketch ทั้งหมดถูกทดสอบบน Arduino ide 1.0.5 นะครับ)
หลังจาก Download มาแล้ว ให้ไปใส่ไว้ใน Folder xxxx\arduino-1.0.x\libraries นะครับ
/*----------------------------------------------------------------------** Display the date and time from a DS3231 or DS3232 RTC every second. ** Display the temperature once per minute. (The DS3231 does a ** temperature conversion once every 64 seconds. This is also the ** default for the DS3232.) ** ** Set the date and time by entering the following on the Arduino ** serial monitor: ** year,month,day,hour,minute,second, ** ** Where ** year can be two or four digits, ** month is 1-12, ** day is 1-31, ** hour is 0-23, and ** minute and second are 0-59. ** ** Entering the final comma delimiter (after "second") will avoid a ** one-second timeout and will allow the RTC to be set more accurately. ** ** No validity checking is done, invalid values or incomplete syntax ** in the input will result in an incorrect RTC setting. ** ** Jack Christensen 08Aug2013 ** ** Tested with Arduino 1.0.5, Arduino Uno, DS3231/Chronodot, DS3232. ** ** This work is licensed under the Creative Commons Attribution- ** ShareAlike 3.0 Unported License. To view a copy of this license, ** visit http://creativecommons.org/licenses/by-sa/3.0/ or send a ** letter to Creative Commons, 171 Second Street, Suite 300, ** San Francisco, California, 94105, USA. **----------------------------------------------------------------------*/#include //http://github.com/JChristensen/DS3232RTC#include //http://arduiniana.org/libraries/streaming/#include //http://playground.arduino.cc/Code/Time#include //http://arduino.cc/en/Reference/Wirevoid setup(void){Serial.begin(115200);//setSyncProvider() causes the Time library to synchronize with the//external RTC by calling RTC.get() every five minutes by default.setSyncProvider(RTC.get);Serial << F("RTC Sync");if (timeStatus() != timeSet) Serial << F(" FAIL!");Serial << endl;}void loop(void){static time_t tLast;time_t t;tmElements_t tm;//check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,sif (Serial.available() >= 12) {//note that the tmElements_t Year member is an offset from 1970,//but the RTC wants the last two digits of the calendar year.//use the convenience macros from Time.h to do the conversions.int y = Serial.parseInt();if (y >= 100 && y < 1000)Serial << F("Error: Year must be two digits or four digits!") << endl;else {if (y >= 1000)tm.Year = CalendarYrToTm(y);else //(y < 100)tm.Year = y2kYearToTm(y);tm.Month = Serial.parseInt();tm.Day = Serial.parseInt();tm.Hour = Serial.parseInt();tm.Minute = Serial.parseInt();tm.Second = Serial.parseInt();t = makeTime(tm);RTC.write(tm);setTime(t);Serial << F("RTC set to: ");printDateTime(t);Serial << endl;//dump any extraneous inputwhile (Serial.available() > 0) Serial.read();}}t = now();if (t != tLast) {tLast = t;printDateTime(t);if (second(t) == 0) {float c = RTC.temperature() / 4.;float f = c * 9. / 5. + 32.;Serial << F(" ") << c << F(" C ") << f << F(" F");}Serial << endl;}}//print date and time to Serialvoid printDateTime(time_t t){printDate(t);Serial << ' ';printTime(t);}//print time to Serialvoid printTime(time_t t){printI00(hour(t), ':');printI00(minute(t), ':');printI00(second(t), ' ');}//print date to Serialvoid printDate(time_t t){printI00(day(t), 0);Serial << monthShortStr(month(t)) << _DEC(year(t));}//Print an integer in "00" format (with leading zero),//followed by a delimiter character to Serial.//Input value assumed to be between 0 and 99.void printI00(int val, char delim){if (val < 10) Serial << '0';Serial << _DEC(val);if (delim > 0) Serial << delim;return;} |
2. จากนั้นก็ต่อโมดูลกับ Arduino board ครับ วันนี้ผมใช้ Arduino UNO R3 นะครับ ก็ตามรูปเลยครับ
VCC -> 5 VDC
GND -> GND
SCL -> A5
SDA -> A4
3. จากนั้นก็ upload sketch ด้านบน หรือ เปิดใน Examples -> DS3231RTC -> SetSerial (อย่าลืมตััง baud rate ของ Serial monitor ให้ตรงกันด้วยนะครับ)
คราวนี้เวลาจะตั้งค่านาฬิกา ก็ไปที่ ช่อง Input ของ Serial monitor แล้วจัดไปตามนี้ครับ
รูปแบบ ปี, เดือน, วันที่, ชั่วโมง, นาที, วินาที
โดย
ปีอาจใช้เป็น 2 หรือ 4 ดิจิตก็ได้
เดือน 1-12
วัน 1-31
ชั่วโมง 0-23
นาทีและวินาที 0-59
ตัวอย่างนะครับ สมมุติว่าวันนี้เป็นวันที่ 1 มกราคม 2014 เวลา 10:10 am 30 วินาที
ให้พิมพ์ลงใน Serial monitor ว่า 2014,1,1,10,10,30
ง่ายๆ เท่านี้ เราก็สามารถบันทึกเวลาปัจจุบันให้กับ RTC DS3231 กันแล้วครับ คราวนี้ถ้าลองกดปุ่ม Reset ดูจะพบว่าเวลาที่เริ่มต้นแสดงก็ไม่ได้เปลี่ยนไปนับใหม่ แต่เป็นการแสดงค่าเวลา ณ ปัจจุบันต่อเนื่องไปเรื่อยๆ ครับ
ลองอีกตัวอย่างใน Examples นะครับ ตัวอย่างที่ชื่อว่า TimeRTC เริ่มจากการ upload sketch ลงไปแล้วเปิด Serial monitor ครับ
/** TimeRTC.pde* Example code illustrating Time library with Real Time Clock.* This example is identical to the example provided with the Time Library,* only the #include statement has been changed to include the DS3232RTC library.*/#include //http://github.com/JChristensen/DS3232RTC#include //http://www.arduino.cc/playground/Code/Time#include //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)void setup(void){Serial.begin(9600);setSyncProvider(RTC.get); // the function to get the time from the RTCif(timeStatus() != timeSet)Serial.println("Unable to sync with the RTC");elseSerial.println("RTC has set the system time");}void loop(void){digitalClockDisplay();delay(1000);}void digitalClockDisplay(void){// digital clock display of the timeSerial.print(hour());printDigits(minute());printDigits(second());Serial.print(' ');Serial.print(day());Serial.print(' ');Serial.print(month());Serial.print(' ');Serial.print(year());Serial.println();}void printDigits(int digits){// utility function for digital clock display: prints preceding colon and leading 0Serial.print(':');if(digits < 10)Serial.print('0');Serial.print(digits);} |
เรียบร้อยครับ เราสามาถนำเวลานี้ไปบันทึกลงในโมดูลอื่นๆ เช่น SD Card หรือ ส่งผ่าน Ethernet Shield ไปที่ Server ที่เขียนรอรับค่าได้ครับ
แถมอีกนิดครับ โมดูล RTC ส่วนใหญ่จะมีความสามารถในการปรับค่าวันที่ของเดือนที่มี 30 วันและ 31 วัน นอกจากนี้ยังปรับค่าปีที่มี 355 และ 356 วันให้เองโดยอัตโนมัติครับ ซึ่งจุดนี้แน่นอนว่าการเขียน Sketch บน Arduino board จะทำได้ค่อนข้างยาก เนื่องจากเวลาที่นานเป็นปีๆที่ต้องนับสัญญาญนาฬิกาจะทำให้เกิดความเพี้ยนแน่นอนครับ
วันนี้พอแค่นี้ครับ..... :)
โดย Mountain A
Share :
บทความการติดตั้งและใช้งาน Raspberry Pi
- การลงโปรแกรม
- Raspberry Pi - Media Center (ตอนที่ 1)
- Raspberry Pi - Media Center (ตอนที่ 2)
- Raspberry Pi - How to Cook Raspbian OS
- Raspberry Pi - Connect to the real world : Part 1
- Raspberry Pi -- Connect to the real world GPIO : Part 2
- Raspberry Pi กับ Shield ของ Arduino
- Raspberry Pi - Analog Input with ADC (MCP3208)
บทความการใช้งาน Arduino และอุปกรณ์ต่อพ่วงต่างๆ
- การลงโปรแกรมและไลบรารี่
- เรื่องของบอร์ด Arduino และ การใช้งานบอร์ด
- โมดูลเพื่อวัดค่าจากสิ่งแวดล้อม
- การใช้งาน DHT11 Humitdity and Temperature Sensor กับบอร์ด Arduino
- Ultrasonic Ranging Module HC-SR04
- Inertial Sensors: หามุม Pitch และ Roll จากเซ็นเซอร์วัดความเร่ง
- Real Time Clock DS3231
- Moisture Sensor on Arduino and Android over Bluetooth
- Moisture Sensor on Arduino and Android over Bluetooth: Part 2
- I2C Communication: Case study of GY-30 (Ambient Light Sensor)
- Inertial Measurement Unit - GY-80 Module for Arduino: Part 1 ADXL345
- Inertial Measurement Unit - GY-80 Module for Arduino: Part 2 L3G4200D
- โมดูลสื่อสาร
- การใช้งาน Motor และ Relay
- การแสดงค่าต่างๆ (แสง สี เสียง จอ)
- โมดูลเพื่อการบันทึกค่าและส่งค่า
- เรื่องของสัญญาณ
- เรื่องของ GPS และการประยุกต์ใช้
- เรื่องทั่วไปเกี่ยวกับ Arduino
ไม่มีความคิดเห็น:
แสดงความคิดเห็น