Enable non-standard I2C RTC module (DS3231) on RPi 4

I have balenaOS 2.48.0+rev1 running on my Raspberry Pi 4 fine. But I need to have a RTC module on it (DS3231), which would be fine in standard configuration (just enable the dtoverlay command). The issue is that I have to use a different i2c driver (i2c-gpio) because the built-in hardware i2c in the RPi doesn’t handle clock stretching that my slave devices require. I can enable i2c-gpio perfectly fine, my devices run through docker and life it great. But that means the i2c bus moves to another device id, so the i2c-rtc dtoverlay doesn’t work (can’t find the RTC clock). I can manually “fix” this by writing to the new_device via the i2c-adapter, the rtc clock is found and communicated to perfectly fine. But how can I persist this with balenaCloud? On a standard RPi OS I’ve created a new unit file for systemd, it works great, it gets loaded and the rtc clock is found. But how do I do that in balenaOS?

Hello @HakanL!
Welcome to our community!
In most linux environments, using this kind of low level communication requires enabling a kernel module. In balena containers this can be done in a similar way because the containers are run in --priviledged mode. To enable I2C communication in your projects you will need to add the command modprobe i2c-dev to your package.json or Dockerfile. In our documentation you can read more about how to do that.
Please let me know if that helps and I’ll be glad to assist you with any further questions.


Yea, but I2C is already enabled, the issue is with the RTC module, which is for the host (so the host will have the correct time).

Hey there,

Are you able to give us a little bit information about the unit file you have created for systemd? Could you elaborate on what you mean when you talk about writing to the new device via the i2c-adapter?

Could the unit file be expressed as a service in the docker-compose file instead?


Sure, I was using this guide: https://www.willhughes.name/post/ds3231_raspi3/
You assign a module to the i2c address by writing to new_device (see link above).
I need to set this prior to the start of the docker containers so the host has the correct time, normally it would’ve been done with dtoverlay, but the i2c-rtc driver for dtoverlay doesn’t seem to support an alternative bus-id/address, so that’s why I enable it using the systemd unit file.

Hi there

Thanks for the information. Probably the most simple way would be to have it as another service in your docker-compose.yml and a very simple container with the CMD /bin/bash -c "echo ds1307 0x68 | tee /sys/class/i2c-adapter/i2c-1/new_device && sleep infinity" This has the added advantage that you can add depends_on values for your other services so you can make sure that the RTC is set up before your other services start.
Happy to walk you through this solution if you need more information.