from machine import Pin, I2C
from utime import sleep
def test_ds3231_features(i2c, addr):
"""
More thoroughly test if the device is actually a DS3231
Returns: (is_ds3231, error_message)
"""
try:
# Test 1: Check control and status registers with specific masks
# DS3231 control register (0x0E) should have bits 6,5,4,2 readable/writable
# Other bits should be 0
control = i2c.readfrom_mem(addr, 0x0E, 1)[0]
if control & 0x83 != 0: # Bits 7,1,0 should be 0
return False, "Control register pattern doesn't match DS3231"
# Test 2: Status register (0x0F) should only have bits 7,3,2,1,0 possibly set
status = i2c.readfrom_mem(addr, 0x0F, 1)[0]
if status & 0x70 != 0: # Bits 6,5,4 should be 0
return False, "Status register pattern doesn't match DS3231"
# Test 3: Try temperature register consistency check
# Read temperature twice with a forced conversion between
temp1 = i2c.readfrom_mem(addr, 0x11, 2)
# Force conversion
control |= (1 << 5) # Set CONV bit
i2c.writeto_mem(addr, 0x0E, bytes([control]))
sleep(0.01) # Wait for conversion
temp2 = i2c.readfrom_mem(addr, 0x11, 2)
# The readings should be similar and in a reasonable range (-40°C to +85°C)
msb1 = temp1[0]
msb2 = temp2[0]
# Check if temperatures are in valid range
if abs(msb1) > 85 or abs(msb2) > 85:
return False, "Temperature readings out of valid range"
return True, "DS3231 verified"
except Exception as e:
return False, f"Error testing DS3231 features: {str(e)}"
def identify_rtc():
"""
Identify whether the RTC is a DS1307 or DS3231
"""
# Initialize I2C
i2c = I2C(0, sda=Pin(8), scl=Pin(9), freq=100000)
RTC_ADDR = 0x68
# First check if any device is present
devices = i2c.scan()
if RTC_ADDR not in devices:
return "No RTC found at address 0x68"
# Test for DS3231 features
is_ds3231, message = test_ds3231_features(i2c, RTC_ADDR)
if is_ds3231:
# Get temperature if it's really a DS3231
try:
temp_msb = i2c.readfrom_mem(RTC_ADDR, 0x11, 1)[0]
temp_lsb = i2c.readfrom_mem(RTC_ADDR, 0x12, 1)[0] >> 6
if temp_msb & 0x80:
temp_msb = -(~temp_msb & 0x7F) - 1
temp_c = temp_msb + ((temp_lsb & 0x03) * 0.25)
temp_f = (temp_c * 9/5) + 32
return f"DS3231 found! Current temperature: {temp_c:.2f}°C ({temp_f:.2f}°F)"
except Exception as e:
return f"DS3231 found but error reading temperature: {str(e)}"
else:
# Test for DS1307
try:
# DS1307 has a unique control register at 0x07
# It should only have bit 4 (OUT) possibly set
control = i2c.readfrom_mem(RTC_ADDR, 0x07, 1)[0]
if control & 0xEF == 0: # All bits except bit 4 should be 0
return "DS1307 found!"
else:
return "Found RTC at 0x68 but cannot definitively identify type"
except:
return "Unknown RTC device type"
def main():
print("\nRTC Identifier")
print("-" * 40)
result = identify_rtc()
print(result)
if __name__ == "__main__":
main()