modbus rtu exception handling

pull/2/head
Mateusz Lubecki 2020-09-28 21:50:06 +02:00
rodzic bad16f5a44
commit 5ab37f1bba
9 zmienionych plików z 143 dodań i 16 usunięć

Wyświetl plik

@ -29,6 +29,7 @@
#ifdef _MODBUS_RTU
#include "modbus_rtu/rtu_register_data_t.h"
#include "modbus_rtu/rtu_exception_t.h"
#endif
@ -107,6 +108,10 @@ extern davis_loop_t rte_wx_davis_loop_content;
extern rtu_register_data_t rte_wx_modbus_rtu_f4;
#endif
extern rtu_exception_t rte_wx_last_modbus_exception;
extern uint32_t rte_wx_last_modbus_rx_error_timestamp;
extern uint32_t rte_wx_last_modbus_exception_timestamp;
#endif
#ifdef __cplusplus

Wyświetl plik

@ -76,6 +76,10 @@ davis_loop_t rte_wx_davis_loop_content;
rtu_register_data_t rte_wx_modbus_rtu_f4;
#endif
rtu_exception_t rte_wx_last_modbus_exception;
uint32_t rte_wx_last_modbus_exception_timestamp;
uint32_t rte_wx_last_modbus_rx_error_timestamp;
#endif
void rte_wx_init(void) {
@ -91,6 +95,10 @@ void rte_wx_init(void) {
for (i = 0; i < 4; i++) {
rte_wx_pressure_history[i] = 0.0f;
}
rte_wx_last_modbus_exception_timestamp = 0;
rte_wx_last_modbus_rx_error_timestamp = 0;
rte_wx_last_modbus_exception = RTU_EXCEPTION_OK;
}
void rte_wx_update_last_measuremenet_timers(uint16_t parameter_type) {

Wyświetl plik

@ -268,6 +268,12 @@ void wx_pool_anemometer(void) {
uint16_t scaled_windspeed = 0;
#if defined(_UMB_MASTER)
rte_wx_average_winddirection = umb_get_winddirection();
rte_wx_average_windspeed = umb_get_windspeed();
rte_wx_max_windspeed = umb_get_windgusts();
#else
#ifdef _ANEMOMETER_ANALOGUE
// this windspeed is scaled * 10. Example: 0.2 meters per second is stored as 2
scaled_windspeed = analog_anemometer_get_ms_from_pulse(rte_wx_windspeed_pulses);
@ -278,11 +284,9 @@ void wx_pool_anemometer(void) {
rte_wx_winddirection_last = tx20_get_wind_direction();
#endif
#if defined(_UMB_MASTER)
rte_wx_average_winddirection = umb_get_winddirection();
rte_wx_average_windspeed = umb_get_windspeed();
rte_wx_max_windspeed = umb_get_windgusts();
#else
#ifdef _MODBUS_RTU
#endif
// check how many times before the pool function was called
if (wx_wind_pool_call_counter < WIND_AVERAGE_LEN) {

Wyświetl plik

@ -0,0 +1,72 @@
/*
* rtu_exception_t.h
*
* Created on: 28.09.2020
* Author: mateusz
*/
#ifndef INCLUDE_MODBUS_RTU_RTU_EXCEPTION_T_H_
#define INCLUDE_MODBUS_RTU_RTU_EXCEPTION_T_H_
#include <stdint.h>
typedef enum rtu_exception {
RTU_EXCEPTION_OK,
RTU_EXCEPTION_ILLEGAL_FUNCTION,
RTU_EXCETPION_ILLEGAL_ADDRESS,
RTU_EXCEPTION_ILLEGAL_VALUE,
RTU_EXCEPTION_SLAVE_FAIL,
RTU_EXCEPTION_ACK,
RTU_EXCEPTION_BUSY,
RTU_EXCEPTION_NACK,
RTU_EXCEPTION_PARITY_ERR,
RTU_EXCEPTION_GW_NAVAIBLE,
RTU_EXCEPTION_GW_TARGET_NAVAIBLE
} rtu_exception_t;
inline rtu_exception_t rtu_exception_from_frame_data(uint8_t in) {
rtu_exception_t out = RTU_EXCEPTION_OK;
if (in == 0x01) {
out = RTU_EXCEPTION_ILLEGAL_FUNCTION;
}
else if (in == 0x02) {
out = RTU_EXCETPION_ILLEGAL_ADDRESS;
}
else if (in == 0x03) {
out = RTU_EXCEPTION_ILLEGAL_VALUE;
}
else if (in == 0x04) {
out = RTU_EXCEPTION_SLAVE_FAIL;
}
else if (in == 0x05) {
out = RTU_EXCEPTION_ACK;
}
else if (in == 0x06) {
out = RTU_EXCEPTION_BUSY;
}
else if (in == 0x07) {
out = RTU_EXCEPTION_NACK;
}
else if (in == 0x08) {
out = RTU_EXCEPTION_PARITY_ERR;
}
else if (in == 0x0A) {
out = RTU_EXCEPTION_GW_NAVAIBLE;
}
else if (in == 0x0B) {
out = RTU_EXCEPTION_GW_TARGET_NAVAIBLE;
}
else {
;
}
return out;
}
#endif /* INCLUDE_MODBUS_RTU_RTU_EXCEPTION_T_H_ */

Wyświetl plik

@ -9,9 +9,10 @@
#define INCLUDE_MODBUS_RTU_RTU_PARSER_H_
#include <modbus_rtu/rtu_register_data_t.h>
#include <modbus_rtu/rtu_exception_t.h>
#include <stdint.h>
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output);
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output, rtu_exception_t* exception);
#endif /* INCLUDE_MODBUS_RTU_RTU_PARSER_H_ */

Wyświetl plik

@ -10,7 +10,7 @@
#include <stdint.h>
#define MODBUS_RTU_MAX_REGISTERS_AT_ONCE 16 // according to RTU standard 125
#define MODBUS_RTU_MAX_REGISTERS_AT_ONCE 8 // according to RTU standard 125
typedef struct __attribute__((packed)) rtu_register_data {

Wyświetl plik

@ -13,5 +13,6 @@
#define MODBUS_RET_TOO_SHORT 1
#define MODBUS_RET_WRONG_FUNCTION 2
#define MODBUS_RET_REQUEST_GEN_ERR 3
#define MODBUS_RET_GOT_EXCEPTION 4
#endif /* INCLUDE_MODBUS_RTU_RTU_RETURN_VALUES_H_ */

Wyświetl plik

@ -10,7 +10,7 @@
#define MODBUS_RTU_MIN_03_04_RESP_LN 7 // one register to read
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output) {
int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_register_data_t* output, rtu_exception_t* exception) {
uint32_t retval = MODBUS_RET_UNINITIALIZED;
uint16_t data = 0;
@ -32,7 +32,7 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
}
else {
// fetch slave address
data = *input << 8 | *(input + 1);
data = *input;
// store slave address
output->slave_address = data;
@ -40,8 +40,17 @@ int32_t rtu_parser_03_04_registers(uint8_t* input, uint16_t input_ln, rtu_regist
// fetch function code
data = *(input + 1);
// if the exception flag is set
if ((data & 0x80) > 0) {
// parse the exception value
*exception = rtu_exception_from_frame_data(data);
// and set the return value
retval = MODBUS_RET_GOT_EXCEPTION;
}
// check if the function code is correct or not
if (data == 0x03 || data == 0x04) {
else if (data == 0x03 || data == 0x04) {
// fetch the function result lenght in bytes
data = *(input + 2);

Wyświetl plik

@ -23,6 +23,23 @@
#define INTERFRAME_SP 20
#ifndef _RTU_SLAVE_LENGHT_1
#define _RTU_SLAVE_LENGHT_1 0x1
#endif
#ifndef _RTU_SLAVE_LENGHT_2
#define _RTU_SLAVE_LENGHT_2 0x1
#endif
#ifndef _RTU_SLAVE_LENGHT_3
#define _RTU_SLAVE_LENGHT_3 0x1
#endif
#ifndef _RTU_SLAVE_LENGHT_4
#define _RTU_SLAVE_LENGHT_4 0x1
#endif
typedef enum rtu_pool_state {
RTU_POOL_IDLE,
RTU_POOL_TRANSMITTING,
@ -111,7 +128,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
rte_wx_modbus_rtu_f1.slave_address = _RTU_SLAVE_ID_1;
rte_wx_modbus_rtu_f1.base_address = _RTU_SLAVE_ADDR_1;
rte_wx_modbus_rtu_f1.number_of_registers = 1;
rte_wx_modbus_rtu_f1.number_of_registers = _RTU_SLAVE_LENGHT_1;
#endif
#ifdef _RTU_SLAVE_ID_2
@ -120,7 +137,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
rte_wx_modbus_rtu_f2.slave_address = _RTU_SLAVE_ID_2;
rte_wx_modbus_rtu_f2.base_address = _RTU_SLAVE_ADDR_2;
rte_wx_modbus_rtu_f2.number_of_registers = 1;
rte_wx_modbus_rtu_f2.number_of_registers = _RTU_SLAVE_LENGHT_2;
#endif
#ifdef _RTU_SLAVE_ID_3
@ -129,7 +146,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
rte_wx_modbus_rtu_f3.slave_address = _RTU_SLAVE_ID_3;
rte_wx_modbus_rtu_f3.base_address = _RTU_SLAVE_ADDR_3;
rte_wx_modbus_rtu_f3.number_of_registers = 1;
rte_wx_modbus_rtu_f3.number_of_registers = _RTU_SLAVE_LENGHT_3;
#endif
#ifdef _RTU_SLAVE_ID_4
@ -138,7 +155,7 @@ int32_t rtu_serial_init(rtu_pool_queue_t* queue) {
rte_wx_modbus_rtu_f4.slave_address = _RTU_SLAVE_ID_4;
rte_wx_modbus_rtu_f4.base_address = _RTU_SLAVE_ADDR_4;
rte_wx_modbus_rtu_f4.number_of_registers = 1;
rte_wx_modbus_rtu_f4.number_of_registers = _RTU_SLAVE_LENGHT_4;
#endif
#endif
@ -268,12 +285,13 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
;
}
else if (serial_context->srl_rx_state == SRL_RX_DONE) {
// parse the response from RTU slave
// parse the response from RTU slave // here there is a problem with changing slave address
if (queue->function_id[queue->it] == 0x03 || queue->function_id[queue->it] == 0x04) {
result = rtu_parser_03_04_registers(
serial_context->srl_rx_buf_pointer,
serial_context->srl_rx_bytes_counter,
((rtu_register_data_t*)queue->function_parameter[queue->it]));
((rtu_register_data_t*)queue->function_parameter[queue->it]),
&rte_wx_last_modbus_exception);
}
else {
retval = MODBUS_RET_WRONG_FUNCTION;
@ -287,6 +305,13 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
// switch the state to inter-frame silence period
rtu_pool = RTU_POOL_WAIT_AFTER_RECEIVE;
}
else if (result == MODBUS_RET_GOT_EXCEPTION) {
// in case of an excetpion store the current timestamp
rte_wx_last_modbus_exception_timestamp = main_get_master_time();
// switch the state to inter-frame silence period
rtu_pool = RTU_POOL_WAIT_AFTER_RECEIVE;
}
else {
// Receive error state will switch to the next function
rtu_pool = RTU_POOL_RECEIVE_ERROR;
@ -300,6 +325,8 @@ int32_t rtu_serial_pool(rtu_pool_queue_t* queue, srl_context_t* serial_context)
// in case of any error during data reception or the serial driver have fallen into unknown & unexpected
// state
else {
rte_wx_last_modbus_rx_error_timestamp = main_get_master_time();
rtu_pool = RTU_POOL_RECEIVE_ERROR;
}
break;