ĐỒNG HỒ THỜI GIAN THỰC SỬ DỤNG ARDUINO

Đồng hồ thời gian thực Arduino sử dụng Module DS1307 RTC và module LCD 16 × 2 để hiển thị.

Giới thiệu module DS1307

Bài này, chúng ta sẽ sử dụng module RTC DS1307 dựa trên giao thức I2C. Module cung cấp chi tiết cách điều chỉnh thời gian như thứ, phút, giờ, ngày trong tuần, ngày trong tháng, tháng và năm bao gồm cả sự điều chỉnh cho năm nhuận. Nó có thể hoạt động ở định dạng 12 giờ hoặc 24 giờ. Dòng tiêu thụ của module này rất nhỏ (vài nA). Chính vì vậy một nguồn Pin 3V cũng có thể cung cấp năng lượng cho nó trong 10 năm để duy trì đồng hồ chính xác và không có bất kỳ nguồn điện bên ngoài nào. DS1307 có bộ nhớ 64 byte trong đó 8 byte đầu tiên được dành làm vùng dữ liệu RTC và 56 byte còn lại là RAM sử dụng cho mục đích chung. Các chi tiết về ngày và thời gian hiện tại được lưu trữ trong RTC dưới dạng số thập phân mã hóa nhị phân. Module giao tiếp với vi điều khiển bằng giao thức giao tiếp nối tiếp I2C. Bus I2C bao gồm 2 dây là SDA và SCL. SDA là dòng dữ liệu nối tiếp và SCL là dòng nối tiếp. Mỗi thiết bị được kết nối với bus đều có địa chỉ thiết bị duy nhất của riêng nó, bất kể đó là module MCU hay RTC. Mỗi chip này có thể hoạt động như một máy thu hoặc máy phát, tùy thuộc vào chức năng.

DS1307 làm việc trong mạng truyền thông và bộ điều khiển chỉ có thể truy cập bằng cách khởi tạo một điều kiện bắt đầu cùng với địa chỉ thiết bị. I2C với các chân SDA và SCL được kết nối với các chân tương ứng của arduino. Về phần mềm, chúng ta sẽ sử dụng thư viện arduino có tên là Wire cho giao tiếp I2C. Thư viện này cho phép bạn giao tiếp với các thiết bị I2C / TWI.

Sơ đồ mạch

 

Chương trình

#include

#include

#define DS1307_ADDRESS 0x68

 

LiquidCrystal lcd(13,12,11,10,9,8);

 

boolean MODE = false;

 

byte Dec_To_BCD(byte dec){

return( (dec/10*16) + (dec%10) );

}

byte BCD_To_Dec(byte BCD){

return( (BCD/16*10) + (BCD%16) );

}

 

void Mode12(){

MODE=true;

}

 

void Mode24(){

MODE=false;

}

 

void setTime(byte SEC, byte MIN, byte HOUR, byte DOW, byte DOM, byte MONTH, byte YEAR)

{

 

Wire.beginTransmission(DS1307_ADDRESS);

Wire.write(0);

Wire.write(Dec_To_BCD(SEC));

Wire.write(Dec_To_BCD(MIN));

Wire.write(Dec_To_BCD(HOUR));

Wire.write(Dec_To_BCD(DOW));

Wire.write(Dec_To_BCD(DOM));

Wire.write(Dec_To_BCD(MONTH));

Wire.write(Dec_To_BCD(YEAR));

Wire.endTransmission();

}

void getTime(byte *SEC, byte *MIN, byte *HOUR)

{

Wire.beginTransmission(DS1307_ADDRESS);

Wire.write(0);

Wire.endTransmission();

Wire.requestFrom(DS1307_ADDRESS, 7);

 

*SEC = BCD_To_Dec(Wire.read()&0x7f);

*MIN = BCD_To_Dec(Wire.read());

*HOUR = BCD_To_Dec(Wire.read()&0x3f);

}

 

 

void getDate(byte *DOM, byte *MONTH, byte *YEAR)

{

Wire.beginTransmission(DS1307_ADDRESS);

Wire.write(4);

Wire.endTransmission();

Wire.requestFrom(DS1307_ADDRESS, 7);

 

*DOM = BCD_To_Dec(Wire.read());

*MONTH = BCD_To_Dec(Wire.read());

*YEAR = BCD_To_Dec(Wire.read());

}

 

byte getWeek()

{

Wire.beginTransmission(DS1307_ADDRESS);

Wire.write(3);

Wire.endTransmission();

Wire.requestFrom(DS1307_ADDRESS, 7);

 

return(BCD_To_Dec(Wire.read()));

}

 

 

String getTimeStr()

{

String ALL;

byte SEC, MIN, HOUR,AM_PM;

 

getTime(&SEC, &MIN, &HOUR);

if(!MODE)

{

if (HOUR

ALL=String(‘0’)+String(HOUR, DEC)+String(‘:’);

else

ALL=String(HOUR, DEC)+String(‘:’);

if (MIN

ALL+=String(‘0’);ALL+=String(MIN, DEC);

ALL+=String(‘:’);

if (SEC

ALL+=String(‘0’);ALL+=String(SEC, DEC);

}

Quảng cáo đặt hàng nhập

else

{

AM_PM=HOUR;

if(HOUR>12)

HOUR-=12;

if (HOUR

ALL=String(‘0’)+String(HOUR, DEC)+String(‘:’);

else

ALL=String(HOUR, DEC)+String(‘:’);

if (MIN

ALL+=String(‘0’);ALL+=String(MIN, DEC);

ALL+=String(‘:’);

if (SEC

ALL+=String(‘0’);ALL+=String(SEC, DEC);

ALL+=String(‘ ‘);

if(AM_PM>12)ALL+=String(“PM”);

else ALL+=String(“AM”);

}

 

return(ALL);

}

 

String getDateStr()

{

String ALL;

byte DOM, MONTH, YEAR;

 

getDate(&DOM, &MONTH,&YEAR);

 

if (DOM

ALL+=String(‘0’);ALL+=String(DOM, DEC);

ALL+=String(‘/’);

if (MONTH

ALL+=String(‘0’);ALL+=String(MONTH, DEC);

ALL+=String(‘/’);ALL+=String(YEAR, DEC);

ALL+=String(‘ ‘);

 

return(ALL);

}

 

 

String getWeekStr()

{

String ALL;

 

switch(getWeek())

{

case 1:ALL+=String(“Sunday”);break;

case 2:ALL+=String(“Monday”);break;

case 3:ALL+=String(“Tuesday”);break;

case 4:ALL+=String(“Wednesday”);break;

case 5:ALL+=String(“Thursday”);break;

case 6:ALL+=String(“Friday”);break;

case 7:ALL+=String(“Saturday”);break;

}

return(ALL);

}

 

void setup()

{

lcd.begin(16,2);

Wire.begin();

setTime(10,33,13,12,11,10,17);

}

 

void loop()

{

 

///// 24hr MODE /////

 

lcd.clear();

lcd.setCursor(0,0);

Mode24();

lcd.print(getTimeStr());lcd.print(‘ ‘);

lcd.setCursor(0,1);

lcd.print(getDateStr());lcd.print(‘ ‘);

lcd.print(getWeekStr());

delay(5000);

///// 12hr MODE /////

lcd.clear();

lcd.setCursor(0,0);

Mode12();

lcd.print(getTimeStr());lcd.print(‘ ‘);

lcd.setCursor(0,1);

lcd.print(getDateStr());lcd.print(‘ ‘);

lcd.print(getWeekStr());

delay(5000);

 

}

Đầu tiên chúng ta sẽ khai báo thư viện LiquidCrystal vào chương trình để sử dụng module LCD.

Ở đây chúng ta sẽ tập trung chủ yếu vào module RTC. Như đã đề cập trước đó, một thư viện có tên là Wire được sử dụng để kết nối I2C. Hàm Wire.begin () sẽ khởi tạo thư viện dây và được gọi ở đầu chương trình. Wire.beginTransmission () sử dụng để gửi địa chỉ thiết bị. Sau đó, hàm Wire.write () có chức năng gửi số lượng thanh ghi có giá trị cần truy cập.

Hàm Wire.endTransmission () kết thúc quá trình truyền. Hàm Wire.requestFrom () được sử dụng để yêu cầu byte từ module. Wire.read () sẽ đọc một byte được truyền từ nó sang Arduino sau khi gọi đến requestFrom ().

Trong DS1307, byte được lưu trữ dưới dạng số thập phân được mã hóa nhị phân. Vì vậy, trước khi viết các giá trị vào các thanh ghi, cần chuyển đổi nó thành BCD (Binary Coded Decimals). Dec_To_BCD () và BCD_To_Dec () là các hàm được sử dụng cho việc này.

Trước khi đọc các giá trị từ module RTC, chúng ta phải cài đặt ngày và giờ bằng cách dùng hàm setTime (). Chúng ta nên khởi tạo các giá trị thời gian thực tế là các tham số. Các giá trị giống như setTime (sec,min,hour,dow,dom,month,year); .

Ở đây chúng ta đang sử dụng DS1307 với định dạng 24 giờ. Vì vậy, chi tiết thời gian phải ở chế độ 24 giờ khi truyền đối số cho hàm setTime (). Sau khi tải lên chương trình, bạn nên tải lại mã bằng cách set hàm setTime (). Nếu không, hàm setTime () sẽ làm hỏng thời gian hiện tại khi mỗi lần bạn reset Arduino.

getTime (), getDate (), getWeek () là các hàm được sử dụng để truy cập bảy thanh ghi dữ liệu trong DS1307. Hàm getTime () sẽ cung cấp giá trị giờ và giây. getDate () cung cấp ngày, tháng và năm. Và getWeek () sẽ trả về ngày trong tuần. Chúng cung cấp dữ liệu dưới dạng số thập phân. Vì vậy, chúng ta nên chuyển đổi nó sang định dạng thời gian và như là chuỗi có thể sử dụng. getTimeStr () là hàm sẽ trả về thời gian hiện tại dưới dạng một chuỗi. tương tự, hàm getDateStr () sẽ trả về ngày hiện tại và getWeekStr () sẽ trả về ngày trong tuần dưới dạng chuỗi.

Bạn có thể hiển thị thời gian hiện tại trên màn hình LCD bằng cách gọi hàm getTimeStr () bên trong màn hình LCD.print (). Ví dụ: lcd.print (getTimeStr ());

Mode12 () và Mode24 () là các chức năng để chuyển đổi chế độ hiển thị thời gian. Nếu bạn muốn hiển thị thời gian hiện tại ở chế độ 12 giờ, bạn nên gọi hàm Mode12 () trước khi sử dụng getTimeStr ().

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *