2020-06-21
md
I²C Clock and EEPROM Memory Module for Raspberry Pi
I²C Clock and EEPROM Memory Module in Rasberry Pi OS-> <-Various Hardware with Raspbian Buster Lite - Real-Time Clock

To replace a hardware clock with a dead battery, I chose another model based on the same DS3231 chip, but with a replaceable battery. This new device is not designed to be plugged directly into the Raspberry Pi GPIO header. To accommodate the battery holder the board is much larger which made it possible to add I²C flash memory. The 8 pin chip, beside the much bigger DS3231, is a 32K bit (4K bytes) AT24C32 EEPROM.

Instructions on how to connect the clock to the hardware I²C bus of the Raspberry Pi running Raspbian Buster and how to access the flash memory follow. The post also shows how to connect the module to I/O pins other than pins 2 and 3 used for the hardware I²C bus. This can be done with a software I²C bus. Finally, we can read the temperature of the DS3231 temperature sensor.

Hopefully, the information in this post is valid for the latest versions of Raspbian Buster. When preparing this post, I was mostly using the September 2019 version of Buster but I did some tests against the June 2019 and February 2020 versions. A few days ago, a reader from Norway kindly wrote to warn me that my description of I²C "seems to work on version 4.19.97-v7, but not on 4.19.118-v7". I think the later is the first version of the operating system from the Raspberry Pi Foundation to be released under the Raspberry Pi OS label, but it is still based on Debian 10 and the 4.19 Linux kernel. Rather than trying to patch this text, I decided to write a new version for the Raspberry Pi OS.

Table of content

  1. I²C on the Raspberry Pi
  2. Useful Software
  3. Using the Hardware Clock Connected to the Hardware I²C Bus
  4. Using the Flash Memory Connected to the Hardware I²C Bus
  5. Using the Hardware Clock Connected to a Software I²C Bus
  6. Using the Flash Memory Connected to the Software I²C Bus
  7. Multiples I²C Buses
  8. The Second Harware I²C Bus
  9. Reading the DS3231 Temperature Sensor
  10. RTC/EEPROM Module Backup Power

I²C on the Raspberry Pi toc

I²C (Inter-Integrated Circuit or TWI - Two Wire Interface) is a serial communication protocol frequently used to connect many devices such as clocks, displays, EEPROM memories, and sensors to a micro-controller. The communication, which is not very fast, is done using two signals and a connection to ground.

All Raspberry Pi models have a hardware I²C bus on pins 3 (SDA) and 5 (SCL) of GPIO connector which has 26 or 40 pins depending on the model. However, the bus is not enabled by default and until it is activated pins 3 and 5 are general I/O pins. If the GPIO connector of the Raspberry Pi has 40 pins, there is a second I²C hardware bus which is assigned to the identification of the extension cards (so called HATs) using pins 27 (ID_SD) and 28 (ID_SC). Unfortunately, use of this bus is not recommended even in the absence of a HAT. However, additional software I²C buses can be created by adding kernel modules.

While several devices can be connected to the I²C bus simultaneously, only two devices can exchange data at any given time. The device that initiates the connection is the master, the recipient is the slave. There can be more than one master on the bus, but data exchange between masters is impossible, as well as between slaves. In addition, a slave cannot initiate communication with a master. See Understanding the I²C Bus, Texas Instruments Application Report SLVA704, p. 3. by Jonathan Valdez and Jared Becker (juin 2015).

If the GPIO connector of the Raspberry Pi has 40 pins, there is a second I²C hardware bus which is assigned to the identification of the extension cards (so called HATs) using pins 27 (ID_SD) and 28 (ID_SC). Unfortunately, it is not possible to use this bus even in the absence of a HAT.

As one would expect in Linux, an I²C bus is represented by a file in the device directory /dev. As an example, there are three I²C buses activated on an Orange Pi PC 2.

opipc@orangepipc2:~$ ls -l /dev/i2* crw-rw---- 1 root i2c 89, 0 Feb 16 04:02 /dev/i2c-0 crw-rw---- 1 root i2c 89, 1 Feb 16 04:02 /dev/i2c-1 crw-rw---- 1 root i2c 89, 2 Feb 16 04:02 /dev/i2c-2

Here is the list of I²C devices on a Raspberry Pi 3 B whose hardware I²C bus has been enabled.

woopi@goldserver:~ $ ls -l /dev/i2c* crw-rw---- 1 root i2c 89, 1 Feb 10 22:17 /dev/i2c-1
As we can see the device i2c-0 (or is i2c-2 ?) that would be linked to the I²C bus used to recognize the expansion cards is not created.

Useful Software toc

Three software utilities are used below. There are i2cdetect and ic2get which are contained in the package i2c-tools. The first displays the address of the devices connected to an I²C bus. The second can read the registers of an I²C slave. Installing the package i2c-tools is very simple.

woopi@goldserver:~ $ sudo apt install -y i2c-tools

Installing the program eeprog that can write to and read from EEPROM is a little more complex. The utility must be compiled from the source code. In addition, several versions of eeprog are available on the Web. The only ones that work are based on the "tear" fork of eeprog developed by Kris Rusocki among which the version by Ján Sáreník on GitHub.

woopi@goldserver:~ $ wget https://github.com/jsarenik/eeprog/archive/master.zip --2020-01-29 19:10:06-- https://github.com/jsarenik/eeprog/archive/master.zip ... 2020-01-29 19:10:07 (268 KB/s) - ‘master.zip’ saved [19445] woopi@goldserver:~ $ unzip master.zip ... woopi@goldserver:~ $ mv eeprog-master eeprog woopi@goldserver:~ $ cd eeprog woopi@goldserver:~/eeprog $ make ...

The problem with the original versions of eeprog is that in writing they use too high a frequency. It has to be slowed down. The I²C frequency of the AT24C32 EEPROM depends on the voltage. It may be possible to save data to the EEPROM if running at 5 volts using the original version of eeprog. The synchronization signal (SCL) of the EEPROM can reach 400 KHz. However, the memory is connected to 3.3 volts to be compatible with Raspberry Pi GPIO that. The I²C operating frequency of the EEPROM decreases rapidly when the voltage is reduced. I don't know the exact value of this frequency at 3.3 volts, but at 2.7 volts the maximum frequency is reduced to 100 KHz.

Neither i2c-tools nor eeprog are needed for normal operation of the clock and flash memory. We can therefore eliminate everything later if desired. Here's how.

woopi@goldserver:~/some_dir/or_other $ cd ~ woopi@goldserver:~ $ rm eeprog-0.7.7_master.zip woopi@goldserver:~ $ rm -r eeprog woopi@goldserver:~ $ sudo apt purge i2c-tools -y

Using the Hardware Clock Connected to the Hardware I²C Bus toc

The connection of the module is easy since the connections are clearly labelled on the board. At a minimum, it is necessary to connect four pins from the latter to the corresponding pins of the Raspberry Pi GPIO connector: the power and ground (VCC and GND) and the data and synchronization signals (SDA and SCL) of the I²C bus. At this point, I did not install a battery, for reasons explained later.

Initially, the I²C and the clock drivers can be installed temporarily. A single command is sufficient to carry out these two tasks. Then, it is a simple matter to check that the devices have been created.

woopi@goldserver:~ $ sudo dtoverlay i2c-rtc ds3231 woopi@goldserver:~ $ ls -l /dev/i2c* /dev/rt* crw-rw---- 1 root i2c 89, 1 Jan 29 02:57 /dev/i2c-1 lrwxrwxrwx 1 root root 4 Jan 29 02:57 /dev/rtc -> rtc0 crw------- 1 root root 253, 0 Jan 29 02:57 /dev/rtc0

The i2c-1 decice (also called an I²C controller) was created, as well as the rtc0 device which communicates with the clock via the i2c-1 controller. The command i2cdetect displays the addresses of the I²C devices connected to the hardware bus.

woopi@goldserver:~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --

Two devices were found. The first is flash memory (EEPROM) at address 0x57 and the second is the clock at address 0x68. The UU displayed instead of the address 68 is an indication that a driver is handling the device.

woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580275162.357510 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/29 05:19:23 Hw clock time : 2020/01/29 05:19:23 = 1580275163 seconds since 1969 Time since last adjustment is 214992 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-29 01:19:22.840443-04:00

Clearly the hardware clock is working. It may be surprising to see that the time is correct in the absence of a battery. The explanation is simple. The operating system, or more precisely the component systemd-timesync, obtains the current time from an SNTP reference server on the Web when the Raspberry Pi starts. As soon as the i2c-rtc module is installed, the system adjusts the hardware clock.

Since everything works, i2c-rtc can be installed permanently by adding the dtoverlay command used temporarly above in the operating system configuration file.

woopi@goldserver:~ $ sudo nano /boot/config.txt

... # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # For access to I2C RTC and other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 ...

It is not necessary to activate the I²C protocol with the raspi-config utility. Previously, I said that we also had to modify the script that adjusts the time of the hardware clock when the i2c-rtc module is loaded. Here's how.

woopi@goldserver:~ $ sudo nano /lib/udev/hwclock-set

Normally the script does nothing, because its execution is stopped by the initial test, at least in distributions using systemd including Raspbian. It is necessary to remove this test or to disable it by adding leading "#" at the start of the lines which transform them into comments.

#!/bin/sh # Reset the System Clock to UTC if the hardware clock from which it # was copied by the kernel was in localtime. dev=$1 #if [ -e /run/systemd/system ] ; then # exit 0 #fi ...

This is probably not a good idea. On the next update, the /lib/udev/hwclock-set script will be overwritten, replaced by the original version. See Debian Bug report logs - #855203 hwclock-set: Synchronize from hwclock despite systemd presence

Using the Flash Memory Connected to the Hardware I²C Bus toc

If you installed the clock as described in the previous section, you can immediately check that it is possible to write and read the AT24C32 EEPROM . Otherwise, the I²C bus is not yet enabled.

woopi@goldserver:~ $ sudo i2cdetect -l woopi@goldserver:~ $ ls /dev/i2* ls: cannot access '/dev/i2*': No such file or directory

The temporary installation of the i2c1 module that implements the hardware I²C bus on GPIO pins 2 and 3 is very simple.

woopi@goldserver:~ $ sudo dtoverlay i2c1 woopi@goldserver:~ $ ls -l /dev/i2c* crw-rw---- 1 root i2c 89, 1 Jan 29 02:57 /dev/i2c-1

If the addresses of the I²C devices connected to bus 1 are displayed when the bus is controlled by i2c1, at least two are observed.

woopi@goldserver:~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Address 0x57 is used by the AT24C32 EEPROM (in reality it is a default address that can be modified with some soldering). Address 0x68 is that of the hardware clock. Because only the I²C bus is activated and because there is no driver for the clock, i2detect shows the latter's address, 0x68 and not UU as in the previous section or below.

If the i2c-rtc module was installed rather than i2c1, then i2cdetect displays UU instead of 0x68 indicating that the clock driver is loaded.

woopi@goldserver:~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Since the I²C bus is enabled and the address of the EEPROM is known, one can write a string in the memory and then read it to make sure that access is possible.

woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-1 0x57 -r 0:29 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: read 29 bytes from offset 0, Output file: <stdout> Reading 29 bytes from 0x0 Lorem ipsum dolor si... woopi@goldserver:~ $ echo "This is working!" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-1 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-1 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 This is working!

Using the Hardware Clock Connected to a Software I²C Bus toc

Older Rapsberry Pi models have only one readily available I²C hardware bus; the exceptions are the Pi model 4 and the Compute module. If GPIO pin 2 or 3 is used for other purposes, a software I²C bus can be created with the module i2c-rtc-gpio to which the RTC can be connected using different GPIO pins.

woopi@goldserver:~ $ sudo dtoverlay -h i2c-rtc-gpio Name: i2c-rtc-gpio Info: Adds support for a number of I2C Real Time Clock devices using the software i2c controller Usage: dtoverlay=i2c-rtc-gpio,<param>=<val> Params: abx80x Select one of the ABx80x family: AB0801, AB0803, AB0804, AB0805, AB1801, AB1803, AB1804, AB1805 ds1307 Select the DS1307 device ds1339 Select the DS1339 device ds3231 Select the DS3231 device m41t62 Select the M41T62 device mcp7940x Select the MCP7940x device mcp7941x Select the MCP7941x device pcf2127 Select the PCF2127 device pcf2129 Select the PCF2129 device pcf8523 Select the PCF8523 device pcf8563 Select the PCF8563 device rv3028 Select the Micro Crystal RV3028 device addr Sets the address for the RTC. Note that the device must be configured to use the specified address. trickle-diode-type Diode type for trickle charge - "standard" or "schottky" (ABx80x only) trickle-resistor-ohms Resistor value for trickle charge (DS1339, ABx80x, RV3028) wakeup-source Specify that the RTC can be used as a wakeup source backup-switchover-mode Backup power supply switch mode. Must be 0 for off or 1 for Vdd < VBackup (RV3028 only) i2c_gpio_sda GPIO used for I2C data (default "23") i2c_gpio_scl GPIO used for I2C clock (default "24") i2c_gpio_delay_us Clock delay in microseconds (default "2" = ~100kHz)

As you can see, GPIO23 and GPIO24 will be used for the SDA and SCL signals respectively. If the i2c-rtc module had been added to the configuration file /boot/config.txt, it must be removed and the Pi must be restarted. If the module had been temporarily loaded, it can be removed with dtoverlay. As soon as you know there is no more device for the clock, you can install i2c-rtc-gpio.

woopi@goldserver:~ $ sudo dtoverlay -l Overlays (in load order): 0: i2c-rtc ds3231=true woopi@goldserver:~ $ sudo dtoverlay -r 0 woopi@goldserver:~ $ ls /dev/rtc ls: cannot access '/dev/rtc': No such file or directory woopi@goldserver:~ $ sudo dtoverlay i2c-rtc-gpio ds3231 Message from syslogd@goldserver at Jan 30 14:18:16 ... kernel:[45446.974763] Internal error: Oops - BUG: 0 [#1] SMP ARM Message from syslogd@goldserver at Jan 30 14:18:16 ... kernel:[45447.002358] Process dtoverlay (pid: 3690, stack limit = 0xb07f204f) ... Message from syslogd@goldserver at Jan 30 14:18:16 ... kernel:[45447.108343] Code: 1a000003 e5932004 e3120001 1a000000 (e7f001f2) Segmentation fault

That clearly does not work. Indeed, I never managed to install the device tree module at run-time, but it does work if the system configuration file is modified.

woopi@goldserver:~ $ sudo nano /boot/config.txt

# Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on ... # for access to I2C RTC and other I2C devices on software I2C bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-rtc-gpio,ds3231 ...

After a reboot, the software I²C bus and the clock device are installed correctly.

woopi@goldserver:~ $ sudo i2cdetect -l i2c-3 i2c i2c-gpio-rtc@0 I2C adapter woopi@goldserver:~ $ sudo i2cdetect -y 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580409344.320549 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/30 18:35:45 Hw clock time : 2020/01/30 18:35:45 = 1580409345 seconds since 1969 Time since last adjustment is 349174 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-30 14:35:44.845273-04:00

Using the Flash Memory Connected to the Software I²C Bus toc

If the i2c-rtc-gpio module has been installed as explained in the previous section, then you can communicate with flash memory at address 0x57 on device i2c-3. If there is the flash memory is used without a hardware clock, then add the i2c-gpio module.

woopi@goldserver:~ $ dtoverlay -h i2c-gpio Name: i2c-gpio Info: Adds support for software i2c controller on gpio pins Usage: dtoverlay=i2c-gpio,<param>=<val> Params: i2c_gpio_sda GPIO used for I2C data (default "23") i2c_gpio_scl GPIO used for I2C clock (default "24") i2c_gpio_delay_us Clock delay in microseconds (default "2" = ~100kHz) bus Set to a unique, non-zero value if wanting multiple i2c-gpio busses. If set, will be used as the preferred bus number (/dev/i2c-<n>). If not set, the default value is 0, but the bus number will be dynamically assigned - probably 3.

The module can be installed directly in this case and obviously, the i2c-rtc-gpio module not be loaded.

woopi@goldserver:~ $ sudo dtoverlay i2c-gpio woopi@goldserver:~ $ sudo i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter woopi@goldserver:~ $ sudo i2cdetect -y 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

The 0x68 address will not be shown if there is no I²C clock. The EEPROM can be accessed as before but the I²C bus must be adjusted; it is now i2c-3.

woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-3 0x57 -r 0:29 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: read 29 bytes from offset 0, Output file: <stdout> Reading 29 bytes from 0x0 Lorem ipsum dolor si... woopi@goldserver:~ $ echo "* A new EEPROM *" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-3 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-3 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 * A new EEPROM *

Multiples I²C Busses toc

It is possible to have more than one I²C bus enabled. Here is the relevant part of the /boot/config.txt file that creates the hardware bus and a software bus.

... # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 # For access to I2C devices other than RTC on software i2c bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-gpio ...


woopi@goldserver:~ $ ls /dev/i2c* /dev/i2c-1 /dev/i2c-3 woopi@goldserver:~ $ sudo i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter woopi@goldserver:~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ sudo i2cdetect -y 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580420342.707524 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/30 21:39:04 Hw clock time : 2020/01/30 21:39:04 = 1580420344 seconds since 1969 Time since last adjustment is 360173 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-30 17:39:03.151299-04:00 woopi@goldserver:~ $ echo "Hardware I2C bus" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-1 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ echo "Software I2C bus" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-3 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-1 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 Hardware I2C bus 4woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-3 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 Software I2C bus

Contrary to comments read on the forums, there does not seem to be any constraints on the I²C bus number or on the bus creation sequence.

... # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on dtoverlay=i2c-gpio,bus=6,i2c_gpio_sda=27,i2c_gpio_scl=22 # For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 # For access to I2C devices other than RTC on software i2c bus (SDA on GPIO23, SCL on GPIO24 by defa$ dtoverlay=i2c-gpio ...

woopi@goldserver:~ $ sudo i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter i2c-6 i2c 6.i2c I2C adapter

... # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # For access to I2C devices other than RTC on software i2c bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-gpio # For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 dtoverlay=i2c-gpio,bus=9,i2c_gpio_sda=27,i2c_gpio_scl=22

woopi@goldserver:~ $ sudo i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter i2c-9 i2c 9.i2c I2C adapter

The only constraint is that the bus number cannot be 0 or 2.

The Second Hardware I²C Bus toc

If the Raspberry Pi GPIO connector has 40 pins, there is a second hardware I²C bus which identifies expansion cards (HAT) using pins 27 (ID_SD) and 28 (ID_SC). In principle, this bus should not be used. There are many warnings about this. The Raspberry Foundation says it not once but twice in its instructions on designing expansion cards. In the paragraphs entitled GPIO Requirements and ID EEPROM there is the same passage:

Within the set of pins available on the GPIO header, ID_SC and ID_SD (GPIO0/SCL and GPIO1/SDA) are reserved for board detection / identification. The only allowed connections to the ID_ pins are an ID EEPROM plus 3.9K pull up resistors. Do not connect anything else to these pins!

The same warning is on the schematics of the various models. In a tutorial on the I²C protocol, Sparkfun adds "It's only there to talk to EEPROMs at addresses 0x50 during boot time. User access at runtime is problematic. If you want a general purpose I²C bus on the B +, you'll need to use I2C-1, on pins 3 and 5 of the 40-pin connector ”. However, the tutorial continues with the procedure for using the bus. It requires i2c_vc module that can be loaded with the dtparam utility. Before installing it, let's see the information that the utility displays about this module.

woopi@goldserver:~ $ sudo dtparam -h i2c_vc i2c_vc Set to "on" to enable the i2c interface usually reserved for the VideoCore processor (default "off") woopi@goldserver:~ $ sudo dtparam i2c_vc=on woopi@goldserver:~ $ ls /dev/i2* /dev/i2c-0

Since the device is in place, I took the chance to connect the clock module with flash memory to pins 27 (SDA) and 28 (SCL) of the second I²C bus (and also to ground and to 3.3 volts of course) taking care to turn off the power before proceeding. After that it was easy to verify that it was possible to use flash memory.

woopi@goldserver:~ $ sudo i2cdetect -y 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-0 0x57 -r 0:29 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit Operation: read 29 bytes from offset 0, Output file: <stdout> Reading 29 bytes from 0x0 Lorem ipsum dolor si... woopi@goldserver:~ $ echo "eeprom on i2c-0 " | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-0 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-0 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 eeprom on i2c-0

There does not seem to be a module that supports the clock with this I²C bus. However, I was able to verify that it was possible to access the DS3231 chip with a Python script which is described in more detail in another post.

woopi@goldserver:~ $ ve rtcpy (rtcpy) woopi@goldserver:~ $ ./rtc -i 0 -bash: ./rtc: No such file or directory (rtcpy) woopi@goldserver:~ $ rtcpy/rtc -i 0 Sat Feb 22 20:53:42 2020 (rtcpy) woopi@goldserver:~ $ rtcpy/rtc -i 0 -u -s "2138-12-09 12:13:14" (rtcpy) woopi@goldserver:~ $ rtcpy/rtc -i 0 Tue Dec 9 12:13:27 2138

To install a controler for this hardware I²C bus permanently, add a line in the configuration file.

woopi@goldserver:~ $ sudo nano /boot/config.txt

# Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on dtparam=i2c_vc=on

I have not tested the use of this bus with the other hardware I²C bus or other software buses, but I think it should work. That said, it is definitely not recommended and may not even be possible to use the i2c0 controller. As indicated at the end of the general help command of the dtparam utility, there could be a conflict with the Pi camera.

woopi@goldserver:~ $ sudo dtparam -h ... N.B. It is recommended to only enable those interfaces that are needed. Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.)

Similarly, it is very likely that there would be a conflict with any I²C device connected to this bus if it uses address 0x50.

Reading the DS3231 Temperature Sensor toc

To ensure accuracy, the DS3231 chip protects against variations caused by temperature changes. Therefore, it incorporates a temperature sensor which can be accessed. The temperature of the chip is in registers 0x11 and 0x12 which can be read with the i2cget utility .

woopi@goldserver:~ $ sudo i2cget -y 1 0x68 0x11 Error: Could not open file `/dev/i2c-1' or `/dev/i2c/1': No such file or directory woopi@goldserver:~ $ i2cget -y 1 0x68 0x11 Error: Could not set address to 0x68: Device or resource busy

The problem is that the rtc0 device which owns ic2-1. The device module is named rtc_ds1307.

woopi@goldserver:~ $ lsmod | grep rtc rtc_ds1307 24576 0 hwmon 16384 2 rtc_ds1307,raspberrypi_hwmon

Removing that module will give access to the DS3231 through I²C bus.

woopi@goldserver:~ $ sudo rmmod rtc_ds1307 woopi@goldserver:~ $ sudo i2cget -y 1 0x68 0x11 0x14 woopi@goldserver:~ $ sudo i2cget -y 1 0x68 0x12 0x40

Register 0x11 contains the integer part of the temperature in degrees Celsius, while the two most significant bits of register 0x12 contain the fractional part of the temperature in quarter degrees Celsius. Now 0x40 = 01000000 of which the two most significant bits are 01. So the temperature is 20 + 1 * (1/4) = 20.25 °C which was reasonable.

The rtc_ds1307 module can be reinstalled and the clock will work again.

woopi@goldserver:~ $ sudo modprobe rtc_ds1307 woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580085041.982210 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/27 00:30:43 Hw clock time : 2020/01/27 00:30:43 = 1580085043 seconds since 1969 Time since last adjustment is 24872 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-26 20:30:42.444318-04:00

RTC/EEPROM Module Backup Power toc

The module includes support for a button battery cell whose function is to keep the clock running when there's no power. There is a rather basic circuit to constantly charge the battery when power is supplied to the module. Initially the rechargeable LIR2032 was supplied with these modules. Unsurprisingly, the modules I got from two vendors lately didn't have batteries included. The new regulations regarding the transportation of lithium-ion batteries are much more severe so that sellers avoid shipping them.

There is an Arduino Forum discussion about the backup battery which begins in November 2014 and which remains active. Let me sum up this long debate.

For these reasons, at least one dealer removes the 200 ohm resistor to deactivate the circuit and recommends the use of a non-rechargeable CR2032 lithium battery. Since it is difficult to find the LIR2032 locally at a reasonable price and since I highly doubt the efficacy of the circuit to charge the battery when the module is supplied at 3.3 volts, I followed the dealer lead with the modules in my possession.

I²C Clock and EEPROM Memory Module in Rasberry Pi OS-> <-Various Hardware with Raspbian Buster Lite - Real-Time Clock