modbus_master.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /**
  2. * @Author: 李建
  3. * @Date: 2025/4/27 15:35
  4. * Description: 实现485主站
  5. * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
  6. */
  7. #include <esp_err.h>
  8. #include "modbus_master.h"
  9. #include "main.h"
  10. #include "mbcontroller.h"
  11. #define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
  12. static const char *TAG = "MODBUS_MASTER";
  13. enum {
  14. //
  15. MB_DEVICE_JS_ADDR = 7,
  16. MB_DEVICE_CS_ADDR = 20,
  17. };
  18. static void *master_handle = NULL;
  19. // The number of parameters that intended to be used in the particular control process
  20. #define MASTER_MAX_CIDS num_device_parameters
  21. // Number of reading of parameters from slave
  22. #define MASTER_MAX_RETRY (10)
  23. // Timeout to update cid over Modbus
  24. #define UPDATE_CIDS_TIMEOUT_MS (500)
  25. #define UPDATE_CIDS_TIMEOUT_TICS (UPDATE_CIDS_TIMEOUT_MS / portTICK_PERIOD_MS)
  26. // Timeout between polls
  27. #define POLL_TIMEOUT_MS (1)
  28. #define POLL_TIMEOUT_TICS (POLL_TIMEOUT_MS / portTICK_PERIOD_MS)
  29. // The macro to get offset for parameter in the appropriate structure
  30. #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1))
  31. #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1))
  32. // Discrete offset macro
  33. #define STR(fieldname) ((const char *)( fieldname ))
  34. mb_parameter_descriptor_t device_parameters[] = {
  35. // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
  36. {CID_CS_POWER, STR("cs_power"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  37. CS_POWER_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  38. {CID_JS_POWER, STR("js_power"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  39. JS_POWER_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  40. {CID_CS_MODE, STR("cs_mode"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  41. CS_MODE_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  42. {CID_JS_MODE, STR("js_mode"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  43. JS_MODE_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  44. {CID_CS_FAN_SPEED, STR("cs_fan_speed"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  45. FAN_CS_SPEED_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  46. {CID_JS_FAN_SPEED, STR("cs_fan_speed"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  47. FAN_JS_SPEED_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  48. {CID_JS_MIN_HUMIDITY, STR("js_min_humidity"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  49. JS_MIN_HUMIDITY_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  50. {CID_JS_MAX_HUMIDITY, STR("js_max_humidity"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  51. JS_MAX_HUMIDITY_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  52. {CID_CS_SET_HUMIDITY, STR("cs_set_humidity"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  53. CS_SET_HUMIDITY_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  54. {CID_CS_ERROR_CODE, STR("cs_error_code"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  55. CS_ERROR_CODE_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  56. {CID_JS_ERROR_CODE, STR("js_error_code"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  57. JS_ERROR_CODE_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  58. {CID_CS_INEFFICIENT_FILTER_SIGN, STR("inefficient_filter_sign"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  59. CS_INEFFICIENT_FILTER_SIGN_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  60. {CID_CS_HEPA_FILTER_SIGN, STR("hepa_filer_sigh"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  61. CS_HEPA_FILTER_SIGN_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  62. {CID_JS_EXTERNAL_HUMIDITY, STR("external_humidity"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  63. JS_EXTERNAL_HUMIDITY_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  64. {CID_JS_MOULD_PROOF_MODE_TIME, STR("proof_mode_time"), STR(""), MB_DEVICE_JS_ADDR, MB_PARAM_HOLDING,
  65. JS_MOULD_PROOF_MODE_TIME_ADDRESS_REGISTER, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  66. {CID_CS_INEFFICIENT_FILTER_SET_TIME, STR("inefficient_fileter_set"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  67. CS_INEFFICIENT_FILTER_SET_TIME, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  68. {CID_CS_HEPA_FILTER_SET_TIME, STR("hepa_fileter_set"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  69. CS_HEPA_FILTER_SET_TIME, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  70. {CID_CS_INEFFICIENT_FILTER_USED_TIME, STR("inefficient_fileter_used"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  71. CS_INEFFICIENT_FILTER_USED_TIME, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  72. {CID_CS_HEPA_FILTER_USED_TIME, STR("hepa_fileter_used"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  73. CS_HEPA_FILTER_USED_TIME, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  74. {CID_CS_INEFFICIENT_FILTER_RESET, STR("inefficient_fileter_reset"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  75. CS_INEFFICIENT_FILTER_RESET, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  76. {CID_CS_HEPA_FILTER_RESET, STR("hepa_fileter_reset"), STR(""), MB_DEVICE_CS_ADDR, MB_PARAM_HOLDING,
  77. CS_HEPA_FILTER_RESET, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  78. };
  79. // Calculate number of parameters in the table
  80. const uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0]));
  81. IRAM_ATTR static esp_err_t master_init() {
  82. // Initialize Modbus controller
  83. mb_communication_info_t comm = {
  84. .ser_opts.port = MB_PORT_NUM,
  85. .ser_opts.mode = MB_RTU,
  86. .ser_opts.baudrate = MB_DEV_SPEED,
  87. .ser_opts.parity = MB_PARITY_NONE,
  88. .ser_opts.response_tout_ms = 400,
  89. .ser_opts.data_bits = UART_DATA_8_BITS,
  90. .ser_opts.stop_bits = UART_STOP_BITS_1
  91. };
  92. ESP_LOGI(TAG, "Modbus controller initialized...");
  93. esp_err_t err = mbc_master_create_serial(&comm, &master_handle);
  94. MB_RETURN_ON_FALSE((master_handle != NULL), ESP_ERR_INVALID_STATE, TAG,
  95. "mb controller initialization fail.");
  96. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  97. "mb controller initialization fail, returns(0x%x).", (int) err);
  98. // Set UART pin numbers
  99. err = uart_set_pin(MB_PORT_NUM, MB_GPIO_TX, MB_GPIO_RX,
  100. UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  101. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  102. "mb serial set pin failure, uart_set_pin() returned (0x%x).", (int) err);
  103. err = mbc_master_start(master_handle);
  104. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  105. "mb controller start fail, returned (0x%x).", (int) err);
  106. // Set driver mode to Half Duplex
  107. err = uart_set_mode(MB_PORT_NUM, UART_MODE_UART);
  108. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  109. "mb serial set mode failure, uart_set_mode() returned (0x%x).", (int) err);
  110. vTaskDelay(5);
  111. err = mbc_master_set_descriptor(master_handle, &device_parameters[0], num_device_parameters);
  112. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  113. "mb controller set descriptor fail, returns(0x%x).", (int) err);
  114. ESP_LOGI(TAG, "Modbus master stack initialized...");
  115. return err;
  116. }
  117. //static void *master_get_param_data(const mb_parameter_descriptor_t *param_descriptor)
  118. //{
  119. // assert(param_descriptor != NULL);
  120. // void *instance_ptr = NULL;
  121. // if (param_descriptor->param_offset != 0) {
  122. // switch(param_descriptor->mb_param_type)
  123. // {
  124. // case MB_PARAM_HOLDING:
  125. // instance_ptr = ((void *)&holding_reg_params + param_descriptor->param_offset - 1);
  126. // break;
  127. // default:
  128. // instance_ptr = NULL;
  129. // break;
  130. // }
  131. // } else {
  132. // ESP_LOGE(TAG, "Wrong parameter offset for CID #%u", (unsigned)param_descriptor->cid);
  133. // assert(instance_ptr != NULL);
  134. // }
  135. // return instance_ptr;
  136. //}
  137. void modbus_master_task(void *arg) {
  138. vTaskDelay(5000 / portTICK_PERIOD_MS);
  139. ESP_LOGI(TAG, "Modbus master task started...");
  140. esp_err_t err = ESP_OK;
  141. uint8_t temp_data[2] = {0}; // temporary buffer to hold maximum CID size
  142. uint8_t type = 0;
  143. const mb_parameter_descriptor_t *param_descriptor = NULL;
  144. for (;;) {
  145. for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < 1; cid++) {
  146. err = mbc_master_get_cid_info(master_handle, cid, &param_descriptor);
  147. if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
  148. err = mbc_master_get_parameter(master_handle, param_descriptor->cid, (uint8_t *) temp_data, &type);
  149. if (err == ESP_OK) {
  150. ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %d read successful.",
  151. param_descriptor->cid,
  152. (char *) param_descriptor->param_key,
  153. (char *) param_descriptor->param_units,
  154. *(uint16_t *) temp_data);
  155. } else {
  156. ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
  157. param_descriptor->cid,
  158. (char *) param_descriptor->param_key,
  159. (int) err,
  160. (char *) esp_err_to_name(err));
  161. }
  162. }
  163. vTaskDelay(1000 / portTICK_PERIOD_MS);
  164. }
  165. vTaskDelay(5000 / portTICK_PERIOD_MS);
  166. }
  167. }
  168. void modbus_master_init() {
  169. ESP_LOGI(TAG, "Modbus master init...1");
  170. ESP_ERROR_CHECK(master_init());
  171. vTaskDelay(10);
  172. //xTaskCreatePinnedToCore(modbus_master_task, "modbus_master_task", 4 * 1024, NULL, 5, NULL, 1);
  173. }
  174. esp_err_t mm_set_param(uint16_t cid, uint8_t *value) {
  175. uint8_t type = PARAM_TYPE_U16;
  176. return mbc_master_set_parameter(master_handle, cid, value, &type);
  177. }
  178. esp_err_t mm_get_param(uint16_t cid, uint8_t *value) {
  179. uint8_t type = PARAM_TYPE_U16;
  180. return mbc_master_get_parameter(master_handle, cid, value, &type);
  181. }
  182. void modbus_master_destroy() {
  183. mbc_master_delete(master_handle);
  184. }