diff --git a/fw/Core/Inc/main.h b/fw/Core/Inc/main.h index d1fec8e..2a8b4f7 100644 --- a/fw/Core/Inc/main.h +++ b/fw/Core/Inc/main.h @@ -96,6 +96,7 @@ int8_t uart_enable_interrupts(void); #endif /* USER CODE BEGIN Private defines */ #define MEASUREMENT_PERIOD_MS 600000 +#define RESET_MAGIC_NUMBER 0xABCD extern uint16_t usart2_rx_message_index; extern uint16_t usart2_rx_message_len; diff --git a/fw/Core/Src/main.c b/fw/Core/Src/main.c index f2e0ecc..7e451ae 100644 --- a/fw/Core/Src/main.c +++ b/fw/Core/Src/main.c @@ -89,7 +89,8 @@ enum REGISTER_NUM_CO2_ALERT_LIMIT2 = 40005, REGISTER_NUM_SCD4x_T_OFFSET = 40006, REGISTER_NUM_MODBUS_ADDR = 40007, - REGISTER_NUM_BAUDRATE = 40008 + REGISTER_NUM_BAUDRATE = 40008, + REGISTER_NUM_RESET_DEVICE = 40100 } config_registers_numbers; enum @@ -931,6 +932,14 @@ int8_t modbus_slave_callback(modbus_transaction_t *transaction) sensor_config.baudrate_index = (uint16_t) (transaction->holding_registers[i]); baudrate_changed = 1; break; + case REGISTER_NUM_RESET_DEVICE: + if (transaction->holding_registers[i] == 0xABCD) { + /* software reset */ + NVIC_SystemReset(); + } else { + return MODBUS_ERROR_OUT_OF_BOUNDS; + } + break; default: return MODBUS_ERROR_FUNCTION_NOT_IMPLEMENTED; } diff --git a/tests/query_device.py b/tests/query_device.py index 0e1fd0a..98d0662 100755 --- a/tests/query_device.py +++ b/tests/query_device.py @@ -8,7 +8,7 @@ f'''{argv[0]} ADDR [BAUDRATE] [{{read [REGISTER ...] | write VALUE REGISTER}}] where: - ADDR is Modbus address (use 0 for broadcast; note that only write can be broadcast) - BAUDRATE is (optional) baud rate; default value is 19200 - - action can be "read", "write" or can be omitted (defaults to "read all") + - action can be "read", "write", "reset" or it can be omitted completely (defaults to "read all") - REGISTER can be either human-friendly register name (e.g. "CO2") or register number (30001) - read may have list of REGISTER arguments (combining both register numbers and names) - VALUE is 16-bit integer in decimal format @@ -78,7 +78,7 @@ while arg_index < len(argv): # sanity check if not action: action = 'all' -if action != 'read' and action != 'write' and action != 'all': +if action != 'read' and action != 'write' and action != 'all' and action != 'reset': print(f'Unknown action {action}') exit(-4) if action == 'write' and value == None: @@ -140,4 +140,11 @@ elif action == 'write': except ValueError: print(f'Register number {reg_number} cannot be written') exit(-9) -exit(0) +elif action == 'reset': + if not s.reset(): + # reset should throw NoResponse; if it doesn't, reset failed + print('Device reset failed!') + else: + print('---- Device reset ----') + +exit(0) diff --git a/tests/sensor.py b/tests/sensor.py index d0ac3d3..a77aad4 100644 --- a/tests/sensor.py +++ b/tests/sensor.py @@ -27,6 +27,8 @@ class Sensor(): 'SCD4x_temperature_offset': 40006, \ 'MODBUS_address': 40007, \ 'baudrate': 40008 } + reset_register = 40100 + reset_magic_number = 0xABCD # readout and error counters readout_total = 0 readout_error_invalid_response = 0 # checksum error: bus transmission corrupted? @@ -49,6 +51,12 @@ class Sensor(): def close(self): self.serial.serial.close() self.serial = None + def reset(self): + try: + self.write_register(self.reset_register, self.reset_magic_number) + return False # got answer => failed to reset + except minimalmodbus.NoResponseError: + return True # no answer => reset successful # High level read functions @property def CO2(self):