sense_main.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * ESPRESSIF MIT License
  3. *
  4. * Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
  5. *
  6. * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case,
  7. * it is free of charge, to any person obtaining a copy of this software and associated
  8. * documentation files (the "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the Software is furnished
  11. * to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all copies or
  14. * substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. #include "string.h"
  25. #include "esp_log.h"
  26. #include "sense_modbus.h"
  27. static const char *TAG = "sense_main";
  28. // The number of parameters that intended to be used in the particular control process
  29. #define SENSE_MAX_CIDS 6
  30. // Timeout to update cid over Modbus if it is not updated by set/get request from mdf
  31. #define MODBUS_VALUE_UPDATE_TIMEOUT_US (10000000)
  32. #define MODBUS_GET_REQUEST_TIMEOUT (1000)
  33. #define INIT_DELAY_TICS (100 / portTICK_RATE_MS)
  34. #define TIMEOUT_UPDATE_CIDS_MS (1000)
  35. #define TIMEOUT_UPDATE_CIDS_TICS (TIMEOUT_UPDATE_CIDS_MS / portTICK_RATE_MS)
  36. #define SENSE_TRIGGER_TASK_STACK_SIZE (1024 * 4)
  37. #define SENSE_TRIGGER_TASK_PRIO (6)
  38. #define SENSE_MAIN_TAG "SENSE_MAIN"
  39. #define SENS_MAIN_CHECK(a, ret_val, str, ...) \
  40. if (!(a)) { \
  41. ESP_LOGE(SENSE_MAIN_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
  42. return (ret_val); \
  43. }
  44. // Characteristic information table
  45. static characteristic_descriptor_t* cid_table[SENSE_MAX_CIDS] = { 0 };
  46. static uint16_t cid_counter = SENSE_MAX_CIDS;
  47. // User operational task to trigger event when cid value exceeds limit
  48. static void trigger_operation_task(void *arg)
  49. {
  50. float value;
  51. uint64_t timeout = 0;
  52. uint16_t temp_value = 0;
  53. bool alarm_state = false;
  54. bool relay_state = false;
  55. characteristic_descriptor_t cid_data = { 0 };
  56. while (1) {
  57. alarm_state = false;
  58. for (int cid = 0; cid < (CID_RELAY_P2); cid++)
  59. {
  60. // Get cid data
  61. ESP_ERROR_CHECK_WITHOUT_ABORT(sense_modbus_get_cid_data(cid, &cid_data));
  62. assert(cid_data.param_key != NULL);
  63. assert(cid_data.instance_ptr != NULL);
  64. // If value is not updated during 10 seconds then update it
  65. timeout = esp_timer_get_time();
  66. value = *(float*)cid_data.instance_ptr;
  67. // Check limits to set alarm if exceeded limit
  68. if (((value > cid_data.param_opts.max) ||
  69. (value < cid_data.param_opts.min)) &&
  70. (cid != CID_RELAY_P1)) {
  71. alarm_state = true;
  72. }
  73. if (timeout > (cid_data.timestamp + MODBUS_VALUE_UPDATE_TIMEOUT_US)) {
  74. // The value is not updated during timeout then update it
  75. // The actual value is saved in the instance storage
  76. value = 0;
  77. esp_err_t error = sense_modbus_read_value(cid, (void*)&value);
  78. if (error != ESP_OK) {
  79. ESP_LOGE(SENSE_MAIN_TAG, "Update failed for cid: %u, %s(%s) = %d, %s",
  80. (uint16_t)cid,
  81. (char*)cid_data.param_key,
  82. (char*)cid_data.param_units,
  83. *(int*)cid_data.instance_ptr,
  84. (char*)esp_err_to_name(error));
  85. } else {
  86. // Update state of alarm
  87. if (cid == CID_RELAY_P1) {
  88. // Get actual relay state
  89. relay_state = (*(uint16_t*)(cid_data.instance_ptr)
  90. & (uint16_t)(cid_data.param_opts.opt1));
  91. const char* relay_state_str = relay_state ? "ON" : "OFF";
  92. ESP_LOGI(SENSE_MAIN_TAG, "cid: %u, (%s) = %s", (uint16_t)cid,
  93. (char*)cid_data.param_key,
  94. (const char*)relay_state_str);
  95. } else {
  96. // Update read value
  97. ESP_LOGI(SENSE_MAIN_TAG, "cid: %u, %s(%s) = %.2f", (uint16_t)cid,
  98. (char*)cid_data.param_key,
  99. (char*)cid_data.param_units,
  100. (float)value);
  101. }
  102. }
  103. }
  104. }
  105. // Check all characteristics if they exceed limits and set alarm accordingly
  106. if (!alarm_state) {
  107. if (relay_state == true) {
  108. ESP_LOGI(SENSE_MAIN_TAG, "The values within the limit, then release relay.");
  109. temp_value = 0;
  110. // Release the relay in IO slave device
  111. // Do not check an error in this example (IO slave may be not configured)
  112. (void)sense_modbus_send_value(CID_RELAY_P1, &temp_value);
  113. relay_state = false;
  114. }
  115. } else {
  116. if (!relay_state) {
  117. ESP_LOGI(SENSE_MAIN_TAG, "The value exceeds limit, then set relay.");
  118. temp_value = 0x00FF;
  119. (void)sense_modbus_send_value(CID_RELAY_P1, &temp_value); // Set the relay
  120. relay_state = true;
  121. }
  122. }
  123. vTaskDelay(TIMEOUT_UPDATE_CIDS_TICS);
  124. }
  125. vTaskDelete(NULL);
  126. }
  127. static void sense_device_init()
  128. {
  129. // Initialize and start Modbus controller
  130. sense_modbus_init();
  131. }
  132. void app_main()
  133. {
  134. esp_err_t result = ESP_OK;
  135. // Initialization of device peripheral and objects
  136. sense_device_init();
  137. // Get all supported modbus characteristics from modbus controller
  138. result = sense_modbus_get_characteristics(&cid_table[0], &cid_counter);
  139. assert((result == ESP_OK) && (cid_counter >= 1));
  140. ESP_LOGI(TAG, "Found (%u) characteristics in the table.", cid_counter);
  141. characteristic_descriptor_t* sid_descr_ptr = { 0 };
  142. float value = 0;
  143. esp_err_t err = ESP_OK;
  144. int cid_registered = 0;
  145. // Read all found characteristics
  146. for (uint16_t cid = 0; cid < cid_counter; cid++) {
  147. sid_descr_ptr = cid_table[cid];
  148. // Initially read of Modbus values and check status
  149. err = sense_modbus_read_value(cid, (void*)&value);
  150. if (err == ESP_OK) {
  151. ESP_LOGI(TAG, "Characteristic (%s) data = 0x%.4x read successful.",
  152. (char*)sid_descr_ptr->param_key, (unsigned int)value);
  153. cid_registered++;
  154. } else {
  155. ESP_LOGE(TAG, "Characteristic (%s) read value fail, err = %d (%s).",
  156. (char*)sid_descr_ptr->param_key,
  157. (int)err,
  158. (char*)esp_err_to_name(err));
  159. }
  160. }
  161. // Starts operation task to check values and trigger an event
  162. xTaskCreate(trigger_operation_task, "trigger_operation_task",
  163. SENSE_TRIGGER_TASK_STACK_SIZE, NULL, SENSE_TRIGGER_TASK_PRIO, NULL);
  164. }