บทความนี้เป็นการเขียนโปรแกรมภาษา Python ของ MicroPython เพื่อตั้งค่า/อ่านค่าวันที่และเวลาของ pcf8583 ซึ่งเป็น RTC ที่พวกเราชอบใช้ ซึ่งพวกเราพบว่ามีตัวอย่างที่เป็นภาษาไพธอนค่อนข้างน้อยจึงนำโค้ดตัวอย่างที่ทำไว้ออกมาให้ได้ลองศึกษากัน
อุปกรณ์
อุปกรณ์สำหรับการทดลองในครั้งนี้ประกอบด้วย
pcf8583
ไอซี PCF8583 เป็นไอซีประเภทฐานนาฬิกาเวลาจริง (RTC: Real Time Clock) ที่ทำงานกับบัส I2C สามารถกำหนดค่าตำแหน่งของตัวเองได้ (บนบอร์ด ET-mini PCF8583 มีจัมเปอร์สำหรับเลือกค่าตำแหน่งของบอร์ด) รองรับการจัดเก็บวันที่และเวลา โดยวันที่นั้นเก็บค่าปีได้ 4 ปี (เก็บค่า 0,1,2 หรือ 3) ทำให้การเขียนโปรแกรมต้องตั้งใจเอาไว้ว่าปี 0 คือปีใด ซึ่งในตัวอย่างโปรแกรมที่เขียนนั้นตั้งเอาไว้ที่ปี 2020 ซึ่งรายละเอียดของการทำงานอ่านได้จากเอกสารของ PCF8583 นอกจากนี้สามารถตั้งเวลาให้บอร์ดแจ้งเตือนในช่วงเวลาที่กำหนดได้ คุณสมบัติของ pcf8583 คือ
- สื่อสารผ่านบัสแบบ I2C ต้องการแรงดันไฟฟ้ากระแสตรงในช่วง 2.5 V ถึง 6 V ในการทำงาน
- นาฬิกาทำงานที่แรงดัน 1.0 V ถึง 6.0 V ที่อุณหภูมิในช่วง 0 °C ถึง +70 °C
- มีหน่วยความจำแรม (RAM) ขนาด 8 บิต จำนวน 240 ตำแหน่ง ทำให้สามารถเก็บข้อมูลขณะที่ยังมีไฟเลี้ยงได้อีก 240 ไบต์
- ต้องการแรงดัน 1.0 Vถึง 6.0 V ในการเก็บข้อมูล
- ใช้กระแสสูงสุด 50 μA
- นาฬิกาทำงานได้ในช่วงเวลา 4 ปี
- รองรับรูปแบบเวลา 24 ชม. หรือ 12 ชม.
- รองรับสัญญาณนาฬิกา 32.768 kHz หรือ 50 Hz
- ตั้งค่าการเตือน ตัวตั้งเวลา และการสร้างสัญญาณการขัดจังหวะได้ (interrupt)
- ค่าตำแหน่งของการอ่านเป็น 0xA1 หรือ 0xA3 และตำแหน่งของการเขียนเป็น 0xA0 หรือ 0xA2
การเชื่อมต่อ
การเชื่อมต่อระหว่าง ESP8266 กับ PCF8583 เป็นดังนี้
PCF8583 | ESP8266 |
---|---|
Vcc | 5VDC (Vin) |
GND | GND |
SDA | D2 (GPIO4) |
SCL | D1 (GPIO5) |
INT | ไม่ได้ใช้ |
ตัวอย่างโปรแกรม
ตัวอย่างโปรแกรมต่อไปนี้เป็นการสั่งเริ่มต้นให้กับการทำงานของ PCF8583 หลังจากนั้นตั้งค่าันที่ผ่านทางฟังก์ชัน adjust() และทำการอ่านค่าวันที่และเวลาจากฟังก์ชัน now() เป็นจำนวน 10ครั้ง โดยวิธีการสั่งงานสามารถอ่านได้จากเอกสารของ PCF8583
###########################################
## (C) 2021, JarutEx
## https://www.jarutex.com
## https://docs.micropython.org/en/latest/library/machine.I2C.html
###########################################
import machine as mc
import time
SCL_PIN = mc.Pin(5)
SDA_PIN = mc.Pin(4)
i2c = mc.I2C(freq=2000000, scl=SCL_PIN, sda=SDA_PIN)
devices = i2c.scan()
PCF8583_ADDR = 0xA2 >> 1
RTC_CTRL = 0x00;
RTC_SEC_100 = 0x01
RTC_SEC = 0x02
ALM_CTRL = 0x08
RTC_YEAR_MEM_ADDR = 0x20
def int2bytes(x):
return x.to_bytes(2, 'big')
def bytes2int(x):
return int.from_bytes(x, 'big')
def dec2bcd(n):
return ((n // 10 * 16) + (n % 10))
def bcd2dec(n):
return ((n // 16 * 10) + (n % 16))
RTC_BEGIN_YEAR = 2020
rtc = [0,0,0,0,0,0,0]
dayOfWeek = ["sun","mon","tue","wed","thu","fri","sat"]
def begin():
i2c.writeto_mem(PCF8583_ADDR,RTC_CTRL, b'\x00')
i2c.writeto_mem(PCF8583_ADDR,ALM_CTRL, b'\x00')
beginYear = int2bytes(RTC_BEGIN_YEAR)
i2c.writeto_mem(PCF8583_ADDR,RTC_YEAR_MEM_ADDR,
bytearray([beginYear[0],beginYear[1]]))
def now():
buffer = i2c.readfrom_mem(PCF8583_ADDR,RTC_SEC,5)
i2c.writeto(PCF8583_ADDR,b'\x20') #RTC_YEAR_MEM_ADDR);
year = i2c.readfrom(PCF8583_ADDR, 2)
rtc[0] = bcd2dec(buffer[0]) # second
rtc[1] = bcd2dec(buffer[1]) # minute
rtc[2] = bcd2dec(buffer[2]) # hour
rtc[3] = bcd2dec(buffer[3]&0x3f) # day
rtc[4] = bcd2dec(buffer[4]&0x1f) # month
rtc[5] = bytes2int(year)+(buffer[3]>>6) # year
rtc[6] = buffer[4]>>5 # day of week
def show():
print("{}. {}/{}/{} {}:{}:{}".format(
dayOfWeek[rtc[6]],
rtc[3],
rtc[4],
rtc[5],
rtc[2],
rtc[1],
rtc[0]
))
def adjust(day,month,year,dow,hour,minute,second):
y = (year-RTC_BEGIN_YEAR)<<6
d = dow << 5
buffer = bytearray([0,0,0,0,0])
buffer[0] = dec2bcd(second)
buffer[1] = dec2bcd(minute)
buffer[2] = dec2bcd(hour)
buffer[3] = dec2bcd(day)+y
buffer[4] = dec2bcd(month)+d
i2c.writeto_mem(PCF8583_ADDR,RTC_SEC,buffer)
####################### main program ############################
if __name__=="__main__":
if not (PCF8583_ADDR in devices):
print("not found PCF8583!!!")
else:
begin()
adjust(9,6,2021,3,13,35,0)
cnt = 0
while cnt<10:
now()
show()
time.sleep_ms(1000)
cnt = cnt+1
จากโค้ดโปรแกรมจะพบว่า เนื่องจาก PCF8583 เก็บปีได้เพียง 4 ปี คือ ค่า 0,1,2 หรือ 3 ดังนั้น ผู้เขียนจึงจัดเก็บค่าปีเอาไว้ในหน่วยความจำ RAM ของ PCF8583 ในตำแหน่ง 0x20 เพื่อใช้สำหรับอ่านค่าปีมาบวกกับค่า 0 ถึง 3 ด้วยเหตุนี้เพมื่อเก็บปีเริ่มต้นเป็น 2020 เมื่อรวมกับค่า 1 จึงได้ผลลัพธ์เป็น 2021 และผลของการทำงานเป็นดังภาพที่ 4
สรุป
จากบทความนี้หวังว่าคงเป็นประโยชน์กับผู้ใช้งานบอร์ด ET-mini PCF8583 หรือผู้ที่เลือกใช้ rtc เป็นไอซี pcf8583 บ้างไม่มากก็น้อย สุดท้ายขอให้สนุกกับการเขียนโปรแกรมครับ
(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรับปรุงเมื่อ 2021-06-09, 2021-06-10, 2021-09-26