
In this small and quick guide, we demonstrate how to perform I2C write operations using MicroPython to update register values on a connected device. This includes writing new data to an I2C peripheral, such as an RTC module, based on specific conditions. Also, how to use random number generator library in micropython.
In this guide, we shall cover the following:
- Introduction.
- Firmware development.
- Results.
1. Introduction:
In this small and quick guide, we explore how to perform I2C write operations using MicroPython on an STM32F411 microcontroller. I2C (Inter-Integrated Circuit) is a widely used, two-wire communication protocol that allows microcontrollers to exchange data with various peripheral devices such as sensors, EEPROMs, and real-time clocks (RTCs). Understanding how to write data to these peripherals is essential for configuring device settings, controlling operations, or updating time and date values in modules like the DS3231 RTC.
This guide focuses on a practical example where we monitor the seconds value from an RTC and, upon meeting a specific condition, write new values back to the device. It demonstrates how to generate new data programmatically, convert it into a device-compatible format (like BCD), and perform an I2C write to update the corresponding registers. This hands-on approach not only shows how to implement write operations but also reinforces how to work effectively with real-world I2C devices in embedded systems.
2. Firmware Development:
We shall continue from this guide here.
We shall start by adding the random generator library as following:
import urandom
Next, declare the following function which will convert decimal to BCD as following:
def dec2bcd(dec): return ((dec // 10) << 4) | (dec % 10)
The function takes decimal value and return BCD value.
Next, a function that will write the time to DS3231 RTC as following:
def write_time(hours, minutes, seconds=0): data = bytearray(3) data[0] = dec2bcd(seconds) data[1] = dec2bcd(minutes) data[2] = dec2bcd(hours) i2c.writeto_mem(DS3231_ADDR, 0x00, data)
The function i2c.writeto_mem will write to a specific memory location of the I2C device, the function takes the following parameters:
- Address of the i2c slave.
- Memory address to be written.
- Data to be written.
Next, the while true loop as following:
while True: h, m, s = read_time() print(f"Time: {h:02}:{m:02}:{s:02}") if s == 5: new_hours = urandom.getrandbits(5) % 24 # 0–23 new_minutes = urandom.getrandbits(6) % 60 # 0–59 write_time(new_hours, new_minutes, 0) print(f"Time reset to: {new_hours:02}:{new_minutes:02}:00") time.sleep(1.5) # Wait a bit to avoid triggering multiple times time.sleep(1)
The steps as following:
- Read the RTC data and print them.
- If the seconds is 5 second, randomize the minutes and hours and set the seconds 0.
- Write the new data to the DS3231.
- Print the new values and wait for 1.5 seconds to prevent multiple trigger in case.
Hence, the entire code as following:
from machine import I2C import time import urandom # BCD helpers def bcd2dec(bcd): return (bcd >> 4) * 10 + (bcd & 0x0F) def dec2bcd(dec): return ((dec // 10) << 4) | (dec % 10) # I2C setup for STM32F411 (predefined bus 1) i2c = I2C(1) DS3231_ADDR = 0x68 def read_time(): data = i2c.readfrom_mem(DS3231_ADDR, 0x00, 3) seconds = bcd2dec(data[0]) minutes = bcd2dec(data[1]) hours = bcd2dec(data[2] & 0x3F) return hours, minutes, seconds def write_time(hours, minutes, seconds=0): data = bytearray(3) data[0] = dec2bcd(seconds) data[1] = dec2bcd(minutes) data[2] = dec2bcd(hours) i2c.writeto_mem(DS3231_ADDR, 0x00, data) while True: h, m, s = read_time() print(f"Time: {h:02}:{m:02}:{s:02}") if s == 5: new_hours = urandom.getrandbits(5) % 24 # 0–23 new_minutes = urandom.getrandbits(6) % 60 # 0–59 write_time(new_hours, new_minutes, 0) print(f"Time reset to: {new_hours:02}:{new_minutes:02}:00") time.sleep(1.5) # Wait a bit to avoid triggering multiple times time.sleep(1)
Click on run as following:

3. Results:
You should get the following the Shell:

Happy coding 😉
Add Comment