====== lamaPLC: RP2040_ETH_Modul: Read BME 680/688 sensor data and store in Modbus input registers ====== The program reads the following data from the [[sensor:bmp_bme|BME680 sensor]] and displays it in the Modbus input registers: * Temperature: Provides ambient temperature readings. * Humidity: Measures relative humidity. * Barometric Pressure: Can be used to calculate altitude or track weather changes. * Gas (VOC): Features a heated metal-oxide sensor that detects Volatile Organic Compounds (VOCs) to estimate indoor air quality. The program is also suitable for reading the **BME688 sensor**. Important: The Ethernet module is accessible by **RP2040_ETH** via **UART1** with the following configuration: //uart1 = UART(1, baudrate=115200, tx=Pin(20), rx=Pin(21), timeout=50)// Required library: https://github.com/robert-hh/BME680-Micropython/blob/master/bme680.py from machine import UART, Pin, I2C import time import machine import bme680 # --- UART config --- uart1 = UART(1, baudrate=115200, tx=Pin(20), rx=Pin(21), timeout=50) # --- I2C config --- i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100000) # --- BME680 --- bme = bme680.BME680_I2C(i2c) # Initialize registers: 10 registers (index 0..9) # Values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 input_registers = [i + 1 for i in range(10)] def update_sensor_data(): """Reading and writing BME680 data to registers""" try: temp = bme.temperature humidity = bme.humidity pressure = bme.pressure gas = bme.gas # Handling signed values ​​and scaling to 16-bit integers input_registers[0] = int(temp * 100) & 0xFFFF # Ex: 23.45 °C -> 2345 input_registers[1] = int(humidity * 100) & 0xFFFF # Ex: 45.12 % -> 4512 input_registers[2] = int(pressure * 10) & 0xFFFF # Ex: 1013.2 hPa -> 10132 input_registers[3] = int(gas / 10) & 0xFFFF # Ex: 55000 Ohm -> 5500 input_registers[4] = int(-10) except Exception as e: print("Sensor reading error:", e) print(f"Modbus TCP Server starting... Registers: {input_registers}") last_sensor_update = time.ticks_ms() while True: current_time = time.ticks_ms() # Refresh sensor data every 2 seconds if time.ticks_diff(current_time, last_sensor_update) > 2000: update_sensor_data() last_sensor_update = current_time if uart1.any(): raw_data = uart1.read() # Modbus TCP minimum length: 12 bytes if len(raw_data) >= 12: header = raw_data[:6] # MBAP Header pdu = raw_data[6:] # UnitID + PDU unit_id = pdu[0] func_code = pdu[1] # Start Address (pdu[2:4]) és Quantity (pdu[4:6]) start_addr = (pdu[2] << 8) | pdu[3] quantity = (pdu[4] << 8) | pdu[5] # 03: Read Input Registers (4) if func_code == 4: # Check if the requested range is valid (between 0-9) if start_addr + quantity <= len(input_registers): # Assemble data bytes byte_count = quantity * 2 data_payload = bytearray() for i in range(start_addr, start_addr + quantity): val = input_registers[i] data_payload.append((val >> 8) & 0xFF) # High byte data_payload.append(val & 0xFF) # Low byte # PDU response: UnitID, Func, ByteCount, Data pdu_res = bytearray([unit_id, func_code, byte_count]) + data_payload # Update TCP Header (length: UnitID(1) + rest of PDU) res_header = bytearray(header) res_header[4] = 0x00 res_header[5] = len(pdu_res) uart1.write(res_header + pdu_res) print(f"Request: Addr {start_addr}, Qty {quantity} -> Response sent.") else: # Exception 02: Illegal Data Address (if the Master asks too much) pdu_res = bytearray([unit_id, func_code + 0x80, 0x02]) res_header = bytearray(header) res_header[5] = 3 uart1.write(res_header + pdu_res) print("Error: Invalid register address!") time.sleep(0.01) {{tag>code! micropython 2026 RP2040_ETH BME680 i2c sensor communication}} This page has been accessed for: Today: {{counter|today}}, Until now: {{counter|total}}