|
@@ -0,0 +1,205 @@
|
|
|
|
+/**
|
|
|
|
+ * @Author: 李建
|
|
|
|
+ * @Date: 2025/4/27 15:35
|
|
|
|
+ * Description: 实现485主站
|
|
|
|
+ * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
|
|
|
|
+ */
|
|
|
|
+#include <esp_err.h>
|
|
|
|
+#include "modbus_master.h"
|
|
|
|
+#include "mbcontroller.h"
|
|
|
|
+
|
|
|
|
+#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
|
|
|
|
+static const char *TAG = "MODBUS_MASTER";
|
|
|
|
+
|
|
|
|
+enum {
|
|
|
|
+ // 分风箱主板从站号
|
|
|
|
+ MB_DEVICE_FFX_ADDR = 1,
|
|
|
|
+ // 分控一从站号
|
|
|
|
+ MB_DEVICE_FK_1_ADDR = 2,
|
|
|
|
+ // 分控二从站号
|
|
|
|
+ MB_DEVICE_FK_2_ADDR = 3,
|
|
|
|
+ // 分控三从站号
|
|
|
|
+ MB_DEVICE_FK_3_ADDR = 4,
|
|
|
|
+ // 分控四从站号
|
|
|
|
+ MB_DEVICE_FK_4_ADDR = 5,
|
|
|
|
+};
|
|
|
|
+static void *master_handle = NULL;
|
|
|
|
+
|
|
|
|
+#define STR(fieldname) ((const char *)( fieldname ))
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const mb_parameter_descriptor_t device_parameters[] = {
|
|
|
|
+ // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
|
|
|
|
+ {CID_POWER, STR("power"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ POWER_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_MODE, STR("mode"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ WORK_MOD_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_MODE, STR("fan_mode"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_MODE_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_SPEED, STR("fan_speed"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_LEVEL_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_1_DEGREE, STR("fan_1_degree"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_VALVE_1_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_2_DEGREE, STR("fan_2_degree"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_VALVE_2_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_3_DEGREE, STR("fan_3_degree"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_VALVE_3_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_4_DEGREE, STR("fan_4_degree"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_VALVE_4_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_FAN_5_DEGREE, STR("fan_5_degree"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ FAN_VALVE_5_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_SET_TEMP, STR("set_temp"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ SET_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_VOLTAGE_1, STR("voltage_1"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ VOLTAGE_1_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_VOLTAGE_2, STR("voltage_2"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ VOLTAGE_2_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_VOLTAGE_3, STR("voltage_3"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ VOLTAGE_3_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_VOLTAGE_4, STR("voltage_4"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ VOLTAGE_4_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_VOLTAGE_5, STR("voltage_5"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ VOLTAGE_5_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_ENV_TEMP, STR("env_temp"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ ENV_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_ENV_HUMIDITY, STR("env_humidity"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ ENV_HUMIDITY_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+ {CID_PM25, STR("pm25"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ PM25_NUMBER_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ},
|
|
|
|
+ {CID_CO2, STR("co2"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ CO2_NUMBER_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ},
|
|
|
|
+ {CID_INNER_ADDR, STR("addr"), STR(""), MB_DEVICE_FFX_ADDR, MB_PARAM_HOLDING,
|
|
|
|
+ GMV_INTERNAL_NUMBER_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
|
|
|
|
+
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+// Calculate number of parameters in the table
|
|
|
|
+const uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0]));
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+IRAM_ATTR static esp_err_t master_init() {
|
|
|
|
+ // Initialize Modbus controller
|
|
|
|
+ mb_communication_info_t comm = {
|
|
|
|
+ .ser_opts.port = MB_PORT_NUM,
|
|
|
|
+ .ser_opts.mode = MB_RTU,
|
|
|
|
+ .ser_opts.baudrate = MB_DEV_SPEED,
|
|
|
|
+ .ser_opts.parity = MB_PARITY_NONE,
|
|
|
|
+ .ser_opts.response_tout_ms = 1000,
|
|
|
|
+ .ser_opts.data_bits = UART_DATA_8_BITS,
|
|
|
|
+ .ser_opts.stop_bits = UART_STOP_BITS_1
|
|
|
|
+ };
|
|
|
|
+ ESP_LOGI(TAG, "Modbus controller initialized...");
|
|
|
|
+ esp_err_t err = mbc_master_create_serial(&comm, &master_handle);
|
|
|
|
+ MB_RETURN_ON_FALSE((master_handle != NULL), ESP_ERR_INVALID_STATE, TAG,
|
|
|
|
+ "mb controller initialization fail.");
|
|
|
|
+ MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
|
|
|
|
+ "mb controller initialization fail, returns(0x%x).", (int) err);
|
|
|
|
+
|
|
|
|
+ // Set UART pin numbers
|
|
|
|
+ err = uart_set_pin(MB_PORT_NUM, MB_GPIO_TX, MB_GPIO_RX,
|
|
|
|
+ UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
|
|
|
+ MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
|
|
|
|
+ "mb serial set pin failure, uart_set_pin() returned (0x%x).", (int) err);
|
|
|
|
+
|
|
|
|
+ err = mbc_master_start(master_handle);
|
|
|
|
+ MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
|
|
|
|
+ "mb controller start fail, returned (0x%x).", (int) err);
|
|
|
|
+
|
|
|
|
+ // Set driver mode to Half Duplex
|
|
|
|
+ err = uart_set_mode(MB_PORT_NUM, UART_MODE_UART);
|
|
|
|
+ MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
|
|
|
|
+ "mb serial set mode failure, uart_set_mode() returned (0x%x).", (int) err);
|
|
|
|
+
|
|
|
|
+ vTaskDelay(5);
|
|
|
|
+ err = mbc_master_set_descriptor(master_handle, &device_parameters[0], num_device_parameters);
|
|
|
|
+ MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
|
|
|
|
+ "mb controller set descriptor fail, returns(0x%x).", (int) err);
|
|
|
|
+ ESP_LOGI(TAG, "Modbus master stack initialized...");
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//static void *master_get_param_data(const mb_parameter_descriptor_t *param_descriptor)
|
|
|
|
+//{
|
|
|
|
+// assert(param_descriptor != NULL);
|
|
|
|
+// void *instance_ptr = NULL;
|
|
|
|
+// if (param_descriptor->param_offset != 0) {
|
|
|
|
+// switch(param_descriptor->mb_param_type)
|
|
|
|
+// {
|
|
|
|
+// case MB_PARAM_HOLDING:
|
|
|
|
+// instance_ptr = ((void *)&holding_reg_params + param_descriptor->param_offset - 1);
|
|
|
|
+// break;
|
|
|
|
+// default:
|
|
|
|
+// instance_ptr = NULL;
|
|
|
|
+// break;
|
|
|
|
+// }
|
|
|
|
+// } else {
|
|
|
|
+// ESP_LOGE(TAG, "Wrong parameter offset for CID #%u", (unsigned)param_descriptor->cid);
|
|
|
|
+// assert(instance_ptr != NULL);
|
|
|
|
+// }
|
|
|
|
+// return instance_ptr;
|
|
|
|
+//}
|
|
|
|
+void modbus_master_task(void *arg) {
|
|
|
|
+ vTaskDelay(5000 / portTICK_PERIOD_MS);
|
|
|
|
+ ESP_LOGI(TAG, "Modbus master task started...");
|
|
|
|
+ esp_err_t err = ESP_OK;
|
|
|
|
+ uint8_t temp_data[2] = {0}; // temporary buffer to hold maximum CID size
|
|
|
|
+ uint8_t type = 0;
|
|
|
|
+ const mb_parameter_descriptor_t *param_descriptor = NULL;
|
|
|
|
+ for (;;) {
|
|
|
|
+ mb_param_request_t req = {
|
|
|
|
+ .slave_addr = 0x05,
|
|
|
|
+ .reg_size = 10,
|
|
|
|
+ .reg_start = 0x23,
|
|
|
|
+ .command = 0x10
|
|
|
|
+ };
|
|
|
|
+ uint16_t data[20] = {0, 1 , 2, 3, 4, 5, 6, 7, 8, 9};
|
|
|
|
+ send_request(&req, &data[0]);
|
|
|
|
+ err = mbc_master_get_cid_info(master_handle, 55, ¶m_descriptor);
|
|
|
|
+ for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < 1; cid++) {
|
|
|
|
+ err = mbc_master_get_cid_info(master_handle, cid, ¶m_descriptor);
|
|
|
|
+ if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
|
|
|
|
+ err = mbc_master_get_parameter(master_handle, param_descriptor->cid, (uint8_t *) temp_data, &type);
|
|
|
|
+ if (err == ESP_OK) {
|
|
|
|
+ ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %d read successful.",
|
|
|
|
+ param_descriptor->cid,
|
|
|
|
+ (char *) param_descriptor->param_key,
|
|
|
|
+ (char *) param_descriptor->param_units,
|
|
|
|
+ *(uint16_t *) temp_data);
|
|
|
|
+ } else {
|
|
|
|
+ ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
|
|
|
|
+ param_descriptor->cid,
|
|
|
|
+ (char *) param_descriptor->param_key,
|
|
|
|
+ (int) err,
|
|
|
|
+ (char *) esp_err_to_name(err));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
|
|
+ }
|
|
|
|
+ vTaskDelay(5000 / portTICK_PERIOD_MS);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ void modbus_master_init() {
|
|
|
|
+ ESP_LOGI(TAG, "Modbus master init...");
|
|
|
|
+ ESP_ERROR_CHECK(master_init());
|
|
|
|
+ vTaskDelay(10);
|
|
|
|
+ xTaskCreatePinnedToCore(modbus_master_task, "modbus_master_task", 4 * 1024, NULL, 5, NULL, 1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+esp_err_t mm_set_param(uint16_t cid, uint8_t *value) {
|
|
|
|
+ uint8_t type = PARAM_TYPE_U16;
|
|
|
|
+ return mbc_master_set_parameter(master_handle, cid, value, &type);
|
|
|
|
+}
|
|
|
|
+esp_err_t mm_get_param(uint16_t cid, uint8_t *value) {
|
|
|
|
+ uint8_t type = PARAM_TYPE_U16;
|
|
|
|
+ return mbc_master_get_parameter(master_handle, cid, value, &type);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+esp_err_t send_request(mb_param_request_t *request, void * data_prt) {
|
|
|
|
+ return mbc_master_send_request(master_handle, request, data_prt);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void modbus_master_destroy() {
|
|
|
|
+ mbc_master_delete(master_handle);
|
|
|
|
+}
|