From 0837de970348b0d62f58b8846ed8d2d558814ffe Mon Sep 17 00:00:00 2001 From: Duke NUCem Date: Thu, 9 Sep 2021 18:11:11 +0200 Subject: [PATCH] Added T, RH readout --- fw/Core/Inc/modbus.h | 2 + fw/Core/Src/main.c | 75 ++++++++++++++++++++----------------- tests/minimalmodbus_test.py | 9 ++++- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/fw/Core/Inc/modbus.h b/fw/Core/Inc/modbus.h index 7eb2e4a..cd77c61 100644 --- a/fw/Core/Inc/modbus.h +++ b/fw/Core/Inc/modbus.h @@ -133,6 +133,8 @@ typedef struct { uint16_t buffer16b[MODBUS_MAX_RTU_FRAME_SIZE/2]; uint16_t input_registers[MODBUS_MAX_REGISTERS]; uint16_t holding_registers[MODBUS_MAX_REGISTERS]; + int16_t input_registers_signed[MODBUS_MAX_REGISTERS]; + int16_t holding_registers_signed[MODBUS_MAX_REGISTERS]; }; } modbus_transaction_t; diff --git a/fw/Core/Src/main.c b/fw/Core/Src/main.c index 82e98f4..392ce98 100644 --- a/fw/Core/Src/main.c +++ b/fw/Core/Src/main.c @@ -51,7 +51,7 @@ const uint16_t tim21_prescaler = 60000-1; // 100Hz const uint16_t tim21_period = 1200-1; // 6s //const uint16_t tim21_period = 200-1; // 1s -/* Input register memory map (just a suggestion, not implemented yet) +/* Input register memory map * (All registers are 16-bit) * ------------------------- * @@ -63,40 +63,21 @@ const uint16_t tim21_period = 1200-1; // 6s * 30013 : T [deg_C * 10] From SCD4x; unsigned value in range [0; 600]; e.g. 21.5 C => 215 * 30014 : RH [%] From SCD4x; unsigned value in range [0; 100] * - * Extended temperature range: + * Extended temperature range (signed values): * 30015 : T [deg_C * 10] From SHT4x; signed value (two's complement) in range [-400;1250] * 30016 : T [deg_C * 10] From SCD4x; signed value (two's complement) in range [-100;600]; e.g. -12.3 C => -123 * - * - * Notes: - * - * - je potreba uzivateli zpristupnit T a RH z SCD4x? Pripadne je tam nechat, ale pouze jako zalozni? - * - jaky pouzit format pro signed hodnoty? Two's complement (int16_t)? Nebo jich tam dat vic (one's complement)? - * - omezit rozsah? Pro mereni T v interieru nema smysl +125 deg C (na to uz jsou pozarni cidla, haha) - * - pocatecni cislo registru (30010) jsem si vymyslel. Muzeme pouzit jine, treba primo zacatek input registru (30001) - * */ /* Input registers memory map implementation */ -union { - struct { - uint16_t CO2; // 30010 - uint16_t T_SHT4x; // 30011 - uint16_t RH_SHT4x; // 30012 - uint16_t T_SCD4x; // 30013 - uint16_t RH_SCD4x; // 30014 - int16_t T_SHT4x_signed; // 30015 - int16_t T_SCD4x_signed; // 30016 - }; - struct { - uint16_t main_values[3]; // CO2, T_SHT4x, RH_SHT4x - uint16_t backup_values[2]; // T_SCD4x, RH_SCD4x - int16_t extended_range_values[2]; // T_SHT4x_signed, T_SCD4x_signed - }; - struct { - uint16_t unsigned_values[5]; - int16_t signed_values[2]; - }; -} measured_values; +enum { + REGISTER_NUM_CO2 = 30010, + REGISTER_NUM_T_SHT4x = 30011, + REGISTER_NUM_RH_SHT4x = 30012, + REGISTER_NUM_T_SCD4x = 30013, + REGISTER_NUM_RH_SCD4x = 30014, + REGISTER_NUM_T_SHT4x_SIGNED = 30015, + REGISTER_NUM_T_SCD4x_SIGNED = 30016 +} register_numbers; /* Variables to store the measured data */ int CO2, T_SCD4x, RH_SCD4x; @@ -118,14 +99,38 @@ void LPUART1_TX_Buffer(uint8_t* buffer_tx, uint8_t buffer_tx_len); /* USER CODE BEGIN 0 */ int8_t modbus_slave_callback(modbus_transaction_t *transaction) { + uint16_t register_number = transaction->register_number; if (transaction->function_code == MODBUS_READ_INPUT_REGISTERS) { - // TODO select reasonable register numbers and implement - // readout of all measured variables - if (transaction->register_number == 30010) { // register number 30010 (randomly selected) - transaction->input_registers[0] = CO2; - return MODBUS_OK; + for (int i = 0; i < transaction->register_count; i++, register_number++) { + switch (register_number) { + case REGISTER_NUM_CO2: + transaction->input_registers[i] = (uint16_t)CO2; + break; + case REGISTER_NUM_T_SHT4x: + transaction->input_registers[i] = (uint16_t)T_SHT4x; + break; + case REGISTER_NUM_RH_SHT4x: + transaction->input_registers[i] = (uint16_t)RH_SHT4x; + break; + case REGISTER_NUM_T_SCD4x: + transaction->input_registers[i] = (uint16_t)T_SCD4x; + break; + case REGISTER_NUM_RH_SCD4x: + transaction->input_registers[i] = (uint16_t)RH_SCD4x; + break; + case REGISTER_NUM_T_SHT4x_SIGNED: + transaction->input_registers_signed[i] = (int16_t)T_SHT4x; + break; + case REGISTER_NUM_T_SCD4x_SIGNED: + transaction->input_registers_signed[i] = (int16_t)T_SCD4x; + break; + default: + return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; + } } + return MODBUS_OK; } + /* Catch-all error */ return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; /* nothing implemented yet! TODO */ } diff --git a/tests/minimalmodbus_test.py b/tests/minimalmodbus_test.py index 3d14dda..0b01c42 100755 --- a/tests/minimalmodbus_test.py +++ b/tests/minimalmodbus_test.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from time import sleep import minimalmodbus import serial @@ -14,5 +15,11 @@ instrument.mode = minimalmodbus.MODE_RTU # rtu or ascii mode instrument.clear_buffers_before_each_transaction = True # read +T = 0 +RH = T CO2 = instrument.read_register(9, 1, functioncode=4) * 10 -print(CO2) +sleep(0.1) +T = instrument.read_register(10, 1, functioncode=4) +sleep(0.1) +RH = instrument.read_register(11, 1, functioncode=4) * 10 +print(f'CO2: {CO2} ppm\t\tT: {T} deg C\t\tRH: {RH} %')