[EN] ESP8266+PCF8583

This article is programming in MicroPython to set/read the date and time of pcf8583, our favorite RTC. We found quite a few examples in Python, so we’ve made some sample codes for you to try.

(Figure. 1 ET-mini PCF8583)

Equipments

The equipment for this experiment consisted of

  1. NodeMCU V2/V3
  2. ET-mini PCF8583
  3. ET-BASE NodeMCU

pcf8583

The PCF8583 IC is a Real-Time Clock IC that operates on the I2C bus. It can configure its address (the ET-mini PCF8583 has a jumper to select the board position), storing the date and time where the date can be stored up to four years (0,1,2 or 3), so the program has to focus on what year 0 is. In the example program, the year 2020 is set. Details of the operation can be read from the documentation of PCF8583. In addition, the board can be set to alert at a specified time. The features of pcf8583 are:

  1. Communicates via I2C bus, requires a DC voltage in the range of 2.5 V to 6 V to operate.
  2. The clock operates at a voltage of 1.0 V to 6.0 V at a temperature in the range of 0 °C to +70 °C.
  3. It has 240 addresses of 8-bit RAM, allowing it to store 240 bytes of data while it still has power.
  4. Requires 1.0 V to 6.0 V voltage for data storage.
  5. Use current up to 50 μA.
  6. The clock works in range of four years.
  7. Support 24h or 12h time format.
  8. Support 32.768 kHz or 50 Hz clock signal.
  9. Set alarms, timers, and interrupt signal generation.
  10. The read address value is 0xA1 or 0xA3 and the write address is 0xA0 or 0xA2.
(Figure. 2 Connecting wires from connectors on board ET-mini PCF8583)

Connection

The connection between ESP8266 and PCF8583 is as follows.

PCF8583ESP8266
Vcc5VDC (Vin)
GNDGND
SDAD2 (GPIO4)
SCLD1 (GPIO5)
INTNot in use
(Figure. 3 Connection at Board ET-BASE NodeMCU with NodeMCU installed)

Example Code

The following example starts the operation of PCF8583, then sets the time via adjust() and reads the date and time from now() function 10 times. Read the usage from PCF8583 documentation.

###########################################
## (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

From the code, we found that since PCF8583 can store only 4 years, i.e. 0,1,2 or 3, we have stored the year in the PCF8583’s RAM memory in address 0x20 to read the coming year. Add values 0 to 3. Thus, to store the default year as 2020, combined with the value 1, results in 2021, and the result of the operation is as shown in Figure 4.

(Figure. 4 Result from setting and reading data from ET-mini PCF8583)

Conclusion

From this article, we hope it will be useful to users of Board ET-mini PCF8583 or those who choose to use rtc as a pcf8583 IC more or less. Finally, have fun with programming.

If you want to discuss or talk with us, feel free to leave comments below!

(C) 2020-2021, By Jarut Busarathid and Danai Jedsadathitikul
Updated 2021-10-02