diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index c4640a5..22126f9 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,26 +1,32 @@ set(SRCS - "main.c" - "utils.c" - "./modbus/ModbusS.c" - "./modbus/uart0_modbus_slave.c" - "./peripheral/led.c" - "./peripheral/config/fram.c" - "./peripheral/config/config.c" - "./peripheral/flow/ads1220.c" - "./peripheral/flow/input_type2.c" - "./peripheral/flow/flow.c" - "./peripheral/bl0939.c" - "./peripheral/depth.c" - "./peripheral/depth_.c" + "uart_example.c" + "main.c" + "modbus-tcp.c" + "can_network.c" + "./stm32/ads1220.c" + "./stm32/bl0939.c" + "./stm32/capture.c" + "./stm32/comm.c" + "./stm32/depth.c" + "./stm32/fram.c" + "./stm32/flow.c" + "./stm32/utils.c" + "./stm32/config.c" + "./stm32/ModbusS.c" + "./stm32/ModbusM.c" + "./stm32/uart0_modbus_slave.c" + "./stm32/pile_id.c" + "./stm32/led.c" + + "./communication_pad/wifi_softap.c" + "./communication_pad/tcp_server.c" + "./communication_pad/ble_gatts_server.c" + "./communication_pad/communication_pad.c" + + #"C:\Espressif\frameworks\esp-idf-v4.4.5\components\bt\include" ) -set(INCLUDE_DIRS - "." "./inc" - "./modbus/inc" - "./peripheral/inc" - "./peripheral/flow/inc" - "./peripheral/config/inc" -) +set(INCLUDE_DIRS "." "./communication_pad/inc") idf_component_register(SRCS ${SRCS} INCLUDE_DIRS ${INCLUDE_DIRS}) \ No newline at end of file diff --git a/main/can_network.c b/main/can_network.c new file mode 100644 index 0000000..ccc0ab6 --- /dev/null +++ b/main/can_network.c @@ -0,0 +1,257 @@ +/* TWAI Network Slave Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +/* + * The following example demonstrates a slave node in a TWAI network. The slave + * node is responsible for sending data messages to the master. The example will + * execute multiple iterations, with each iteration the slave node will do the + * following: + * 1) Start the TWAI driver + * 2) Listen for ping messages from master, and send ping response + * 3) Listen for start command from master + * 4) Send data messages to master and listen for stop command + * 5) Send stop response to master + * 6) Stop the TWAI driver + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "driver/twai.h" + +#include "can_network.h" + +/* --------------------- Definitions and static variables ------------------ */ +// Example Configuration +#define DATA_PERIOD_MS 50 +#define NO_OF_ITERS 3 +#define ITER_DELAY_MS 1000 +#define RX_TASK_PRIO 41 // Receiving task priority +#define TX_TASK_PRIO 42 // Sending task priority +#define CTRL_TSK_PRIO 10 // Control task priority +#define TX_GPIO_NUM 17 +#define RX_GPIO_NUM 18 +#define TAG "CAN" + +#define ID_MASTER_STOP_CMD 0x0A0 +#define ID_MASTER_START_CMD 0x0A1 +#define ID_MASTER_PING 0x0A2 +#define ID_SLAVE_STOP_RESP 0x0B0 +#define ID_SLAVE_DATA 0x0B1 +#define ID_SLAVE_PING_RESP 0x0B2 + +typedef enum +{ + TX_SEND_PING_RESP, + TX_SEND_DATA, + TX_SEND_STOP_RESP, + TX_TASK_EXIT, +} tx_task_action_t; + +typedef enum +{ + RX_RECEIVE_PING, + RX_RECEIVE_START_CMD, + RX_RECEIVE_STOP_CMD, + RX_TASK_EXIT, +} rx_task_action_t; + + + +static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS(); +static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); +static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL); + +// static const twai_message_t ping_resp = {.identifier = ID_SLAVE_PING_RESP, .data_length_code = 0, .data = {0, 0, 0, 0, 0, 0, 0, 0}}; +// static const twai_message_t stop_resp = {.identifier = ID_SLAVE_STOP_RESP, .data_length_code = 0, .data = {0, 0, 0, 0, 0, 0, 0, 0}}; +// Data bytes of data message will be initialized in the transmit task +// twai_message_t data_message = {.identifier = ID_SLAVE_DATA, .data_length_code = 8, .data = {0, 0, 0, 0, 0, 0, 0, 0}}; + +// static QueueHandle_t tx_task_queue; +// static QueueHandle_t rx_task_queue; +// static SemaphoreHandle_t ctrl_task_sem; +// static SemaphoreHandle_t stop_data_sem; +// static SemaphoreHandle_t done_sem; + +/* --------------------------- Tasks and Functions -------------------------- */ + +static void twai_receive_task(void *arg) +{ + twai_message_t rx_msg; + int i; + while (1) + { + char msg_data_str[32]; + int index = 0; + esp_err_t err = twai_receive(&rx_msg, portMAX_DELAY); + if (err == ESP_OK) + { + for (i = 0; i < rx_msg.data_length_code; i++) + { + index += sprintf(&msg_data_str[i], "%02x ", rx_msg.data[i]); + } + ESP_LOGI(TAG, "recive msg id=%lx,len=%u,data=[%s]", rx_msg.identifier, rx_msg.data_length_code, msg_data_str); + } + } +} + +// static void twai_transmit_task(void *arg) +// { +// while (1) +// { +// tx_task_action_t action; +// xQueueReceive(tx_task_queue, &action, portMAX_DELAY); + +// if (action == TX_SEND_PING_RESP) +// { +// // Transmit ping response to master +// twai_transmit(&ping_resp, portMAX_DELAY); +// ESP_LOGI(EXAMPLE_TAG, "Transmitted ping response"); +// xSemaphoreGive(ctrl_task_sem); +// } +// else if (action == TX_SEND_DATA) +// { +// // Transmit data messages until stop command is received +// ESP_LOGI(EXAMPLE_TAG, "Start transmitting data"); +// while (1) +// { +// // FreeRTOS tick count used to simulate sensor data +// uint32_t sensor_data = xTaskGetTickCount(); +// for (int i = 0; i < 4; i++) +// { +// data_message.data[i] = (sensor_data >> (i * 8)) & 0xFF; +// } +// twai_transmit(&data_message, portMAX_DELAY); +// ESP_LOGI(EXAMPLE_TAG, "Transmitted data value %d", sensor_data); +// vTaskDelay(pdMS_TO_TICKS(DATA_PERIOD_MS)); +// if (xSemaphoreTake(stop_data_sem, 0) == pdTRUE) +// { +// break; +// } +// } +// } +// else if (action == TX_SEND_STOP_RESP) +// { +// // Transmit stop response to master +// twai_transmit(&stop_resp, portMAX_DELAY); +// ESP_LOGI(EXAMPLE_TAG, "Transmitted stop response"); +// xSemaphoreGive(ctrl_task_sem); +// } +// else if (action == TX_TASK_EXIT) +// { +// break; +// } +// } +// vTaskDelete(NULL); +// } + +// static void twai_control_task(void *arg) +// { +// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); +// tx_task_action_t tx_action; +// rx_task_action_t rx_action; + +// for (int iter = 0; iter < NO_OF_ITERS; iter++) +// { +// ESP_ERROR_CHECK(twai_start()); +// ESP_LOGI(EXAMPLE_TAG, "Driver started"); + +// // Listen of pings from master +// rx_action = RX_RECEIVE_PING; +// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); +// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); + +// // Send ping response +// tx_action = TX_SEND_PING_RESP; +// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); +// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); + +// // Listen for start command +// rx_action = RX_RECEIVE_START_CMD; +// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); +// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); + +// // Start sending data messages and listen for stop command +// tx_action = TX_SEND_DATA; +// rx_action = RX_RECEIVE_STOP_CMD; +// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); +// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); +// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); + +// // Send stop response +// tx_action = TX_SEND_STOP_RESP; +// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); +// xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); + +// // Wait for bus to become free +// twai_status_info_t status_info; +// twai_get_status_info(&status_info); +// while (status_info.msgs_to_tx > 0) +// { +// vTaskDelay(pdMS_TO_TICKS(100)); +// twai_get_status_info(&status_info); +// } + +// ESP_ERROR_CHECK(twai_stop()); +// ESP_LOGI(EXAMPLE_TAG, "Driver stopped"); +// vTaskDelay(pdMS_TO_TICKS(ITER_DELAY_MS)); +// } + +// // Stop TX and RX tasks +// tx_action = TX_TASK_EXIT; +// rx_action = RX_TASK_EXIT; +// xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); +// xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); + +// // Delete Control task +// xSemaphoreGive(done_sem); +// vTaskDelete(NULL); +// } + + +void can_init(void) +{ + // Add short delay to allow master it to initialize first + + // Create semaphores and tasks + // tx_task_queue = xQueueCreate(1, sizeof(tx_task_action_t)); + // rx_task_queue = xQueueCreate(1, sizeof(rx_task_action_t)); + // ctrl_task_sem = xSemaphoreCreateBinary(); + // stop_data_sem = xSemaphoreCreateBinary();; + // done_sem = xSemaphoreCreateBinary();; + ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config)); + ESP_LOGI(TAG, "Driver installed"); + + xTaskCreatePinnedToCore(twai_receive_task, "CAN_rx", 1024, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY); + twai_start(); + // xTaskCreatePinnedToCore(twai_transmit_task, "TWAI_tx", 4096, NULL, TX_TASK_PRIO, NULL, tskNO_AFFINITY); + // xTaskCreatePinnedToCore(twai_control_task, "TWAI_ctrl", 4096, NULL, CTRL_TSK_PRIO, NULL, tskNO_AFFINITY); + + // Install TWAI driver, trigger tasks to start + // ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config)); + + // xSemaphoreGive(ctrl_task_sem); // Start Control task + // xSemaphoreTake(done_sem, portMAX_DELAY); // Wait for tasks to complete + + // //Uninstall TWAI driver + // ESP_ERROR_CHECK(twai_driver_uninstall()); + // ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled"); + + // //Cleanup + // vSemaphoreDelete(ctrl_task_sem); + // vSemaphoreDelete(stop_data_sem); + // vSemaphoreDelete(done_sem); + // vQueueDelete(tx_task_queue); + // vQueueDelete(rx_task_queue); +} diff --git a/main/can_network.h b/main/can_network.h new file mode 100644 index 0000000..0b90067 --- /dev/null +++ b/main/can_network.h @@ -0,0 +1,19 @@ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __CAN_NETWORK_H +#define __CAN_NETWORK_H + +#ifdef __cplusplus +extern "C" { +#endif + + + +void can_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __HELLOWERLOD_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/main/communication_pad/ble_gatts_server.c b/main/communication_pad/ble_gatts_server.c new file mode 100644 index 0000000..3e753be --- /dev/null +++ b/main/communication_pad/ble_gatts_server.c @@ -0,0 +1,687 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +/**************************************************************************** +* +* This demo showcases creating a GATT database using a predefined attribute table. +* It acts as a GATT server and can send adv data, be connected by client. +* Run the gatt_client demo, the client demo will automatically connect to the gatt_server_service_table demo. +* Client demo will enable GATT server's notify after connection. The two devices will then exchange +* data. +* +****************************************************************************/ + + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_bt.h" + +#include "esp_gap_ble_api.h" +#include "esp_gatts_api.h" +#include "esp_bt_main.h" +#include "ble_gatts_server.h" +#include "esp_gatt_common_api.h" + +#include "stm32/config.h" +#include "stm32/ModbusS.h" +#include "inc/communication_pad.h" + +#define GATTS_TABLE_TAG "BLE_GATTS_SERVER" + +#define PROFILE_NUM 1 +#define PROFILE_APP_IDX 0 +#define ESP_APP_ID 0x55 +#define SAMPLE_DEVICE_NAME "ESP_GATTS_DEMO" +#define SVC_INST_ID 0 + +/* The max length of characteristic value. When the GATT client performs a write or prepare write operation, +* the data length must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX. +*/ +#define GATTS_DEMO_CHAR_VAL_LEN_MAX 500 +#define PREPARE_BUF_MAX_SIZE 1024 +#define CHAR_DECLARATION_SIZE (sizeof(uint8_t)) + +#define ADV_CONFIG_FLAG (1 << 0) +#define SCAN_RSP_CONFIG_FLAG (1 << 1) + +static uint8_t adv_config_done = 0; + +uint16_t ble_gatts_handle_table[IDX_NB]; + +typedef struct { + uint8_t *prepare_buf; + int prepare_len; +} prepare_type_env_t; + +static prepare_type_env_t prepare_write_env; + +#define CONFIG_SET_RAW_ADV_DATA +#ifdef CONFIG_SET_RAW_ADV_DATA +static uint8_t raw_adv_data[] = { + /* flags */ + 0x02, 0x01, 0x06, + /* tx power*/ + 0x02, 0x0a, 0xeb, + /* service uuid */ + 0x03, 0x03, 0xFF, 0x00, + /* device name */ + 0x0f, 0x09, 'E', 'S', 'P', '_', 'G', 'A', 'T', 'T', 'S', '_', 'D','E', 'M', 'O' +}; +static uint8_t raw_scan_rsp_data[] = { + /* flags */ + 0x02, 0x01, 0x06, + /* tx power */ + 0x02, 0x0a, 0xeb, + /* service uuid */ + 0x03, 0x03, 0xFF,0x00 +}; + +#else +static uint8_t service_uuid[16] = { + /* LSB <--------------------------------------------------------------------------------> MSB */ + //first uuid, 16bit, [12],[13] is the value + 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, +}; + +/* The length of adv data must be less than 31 bytes */ +static esp_ble_adv_data_t adv_data = { + .set_scan_rsp = false, + .include_name = true, + .include_txpower = true, + .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec + .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec + .appearance = 0x00, + .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, + .p_manufacturer_data = NULL, //test_manufacturer, + .service_data_len = 0, + .p_service_data = NULL, + .service_uuid_len = sizeof(service_uuid), + .p_service_uuid = service_uuid, + .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), +}; + +// scan response data +static esp_ble_adv_data_t scan_rsp_data = { + .set_scan_rsp = true, + .include_name = true, + .include_txpower = true, + .min_interval = 0x0006, + .max_interval = 0x0010, + .appearance = 0x00, + .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN, + .p_manufacturer_data = NULL, //&test_manufacturer[0], + .service_data_len = 0, + .p_service_data = NULL, + .service_uuid_len = sizeof(service_uuid), + .p_service_uuid = service_uuid, + .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), +}; +#endif /* CONFIG_SET_RAW_ADV_DATA */ + +static esp_ble_adv_params_t adv_params = { + .adv_int_min = 0x20, + .adv_int_max = 0x40, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +struct gatts_profile_inst { + esp_gatts_cb_t gatts_cb; + uint16_t gatts_if; + uint16_t app_id; + uint16_t conn_id; + uint16_t service_handle; + esp_gatt_srvc_id_t service_id; + uint16_t char_handle; + esp_bt_uuid_t char_uuid; + esp_gatt_perm_t perm; + esp_gatt_char_prop_t property; + uint16_t descr_handle; + esp_bt_uuid_t descr_uuid; +}; + +static void gatts_profile_event_handler(esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); + +/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */ +static struct gatts_profile_inst ble_gatts_profile_tab[PROFILE_NUM] = { + [PROFILE_APP_IDX] = { + .gatts_cb = gatts_profile_event_handler, + .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ + }, +}; + +/* Service */ +static const uint16_t GATTS_SERVICE_UUID = 0x00FF; +static const uint16_t GATTS_DATA_READ_WRITE_UUID = 0xFF01; +static const uint16_t GATTS_DATA_NOTIFY_UUID = 0xFF02; + + +static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE; +static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE; +static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; +static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY; +static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY; +static const uint8_t data_read_write_value[4] = {0x00}; +static const uint8_t data_read_write_ccc[2] = {0x00, 0x00}; +static const uint8_t data_notify_val[4] = {0x00}; +static const uint8_t data_notify_ccc[2] = {0x00, 0x00}; + +bool data_notify_enable = false; /* 是否允许数据上报 */ +bool is_connected = false; /* 蓝牙是否连接 */ +static uint16_t ble_gatts_conn_id = 0xffff; +static esp_gatt_if_t ble_gatts_if = 0xff; + +/* Full Database Description - Used to add attributes into the database */ +static const esp_gatts_attr_db_t gatt_db[IDX_NB] = +{ + // Service Declaration + [IDX_SVC] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, + sizeof(uint16_t), sizeof(GATTS_SERVICE_UUID), (uint8_t *)&GATTS_SERVICE_UUID}}, + + /* Characteristic Declaration */ + [IDX_DATA_READ_WRITE_CHAR] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, + CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}}, + + /* Characteristic Value */ + [IDX_DATA_READ_WRITE_VAL] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_DATA_READ_WRITE_UUID, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(data_read_write_value), (uint8_t *)data_read_write_value}}, + + /* Client Characteristic Configuration Descriptor */ + [IDX_DATA_READ_WRITE_CFG] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + sizeof(uint16_t), sizeof(data_read_write_ccc), (uint8_t *)data_read_write_ccc}}, + + + //SPP - data notify characteristic Declaration + [IDX_DATA_NOTIFY_CHAR] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, + CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}}, + + //SPP - data notify characteristic Value + [IDX_DATA_NOTIFY_VAL] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_DATA_NOTIFY_UUID, ESP_GATT_PERM_READ, + GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(data_notify_val), (uint8_t *)data_notify_val}}, + + //SPP - data notify characteristic - Client Characteristic Configuration Descriptor + [IDX_DATA_NOTIFY_CFG] = + {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, + sizeof(uint16_t),sizeof(data_notify_ccc), (uint8_t *)data_notify_ccc}}, +}; + +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + #ifdef CONFIG_SET_RAW_ADV_DATA + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: + adv_config_done &= (~ADV_CONFIG_FLAG); + if (adv_config_done == 0){ + esp_ble_gap_start_advertising(&adv_params); + } + break; + case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: + adv_config_done &= (~SCAN_RSP_CONFIG_FLAG); + if (adv_config_done == 0){ + esp_ble_gap_start_advertising(&adv_params); + } + break; + #else + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + adv_config_done &= (~ADV_CONFIG_FLAG); + if (adv_config_done == 0){ + esp_ble_gap_start_advertising(&adv_params); + } + break; + case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: + adv_config_done &= (~SCAN_RSP_CONFIG_FLAG); + if (adv_config_done == 0){ + esp_ble_gap_start_advertising(&adv_params); + } + break; + #endif + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + /* advertising start complete event to indicate advertising start successfully or failed */ + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTS_TABLE_TAG, "advertising start failed"); + }else{ + ESP_LOGI(GATTS_TABLE_TAG, "advertising start successfully"); + } + break; + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTS_TABLE_TAG, "Advertising stop failed"); + } + else { + ESP_LOGI(GATTS_TABLE_TAG, "Stop adv successfully\n"); + } + break; + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d", + param->update_conn_params.status, + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); + break; + default: + break; + } +} + + +void example_prepare_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param) +{ + ESP_LOGI(GATTS_TABLE_TAG, "prepare write, handle = %d, value len = %d", param->write.handle, param->write.len); + esp_gatt_status_t status = ESP_GATT_OK; + if (prepare_write_env->prepare_buf == NULL) { + prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t)); + prepare_write_env->prepare_len = 0; + if (prepare_write_env->prepare_buf == NULL) { + ESP_LOGE(GATTS_TABLE_TAG, "%s, Gatt_server prep no mem", __func__); + status = ESP_GATT_NO_RESOURCES; + } + } else { + if(param->write.offset > PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_OFFSET; + } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_ATTR_LEN; + } + } + /*send response when param->write.need_rsp is true */ + if (param->write.need_rsp){ + esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t)); + if (gatt_rsp != NULL){ + gatt_rsp->attr_value.len = param->write.len; + gatt_rsp->attr_value.handle = param->write.handle; + gatt_rsp->attr_value.offset = param->write.offset; + gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; + memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len); + esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp); + if (response_err != ESP_OK){ + ESP_LOGE(GATTS_TABLE_TAG, "Send response error"); + } + free(gatt_rsp); + }else{ + ESP_LOGE(GATTS_TABLE_TAG, "%s, malloc failed", __func__); + } + } + if (status != ESP_GATT_OK){ + return; + } + memcpy(prepare_write_env->prepare_buf + param->write.offset, + param->write.value, + param->write.len); + prepare_write_env->prepare_len += param->write.len; + +} + +void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ + if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC && prepare_write_env->prepare_buf){ + esp_log_buffer_hex(GATTS_TABLE_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len); + ble_read_data(prepare_write_env->prepare_buf, prepare_write_env->prepare_len); + }else{ + ESP_LOGI(GATTS_TABLE_TAG,"ESP_GATT_PREP_WRITE_CANCEL"); + } + if (prepare_write_env->prepare_buf) { + free(prepare_write_env->prepare_buf); + prepare_write_env->prepare_buf = NULL; + } + prepare_write_env->prepare_len = 0; +} + + +static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ + switch (event) { + case ESP_GATTS_REG_EVT:{ + esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME); + if (set_dev_name_ret){ + ESP_LOGE(GATTS_TABLE_TAG, "set device name failed, error code = %x", set_dev_name_ret); + } + #ifdef CONFIG_SET_RAW_ADV_DATA + esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data)); + if (raw_adv_ret){ + ESP_LOGE(GATTS_TABLE_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret); + } + adv_config_done |= ADV_CONFIG_FLAG; + esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_scan_rsp_data, sizeof(raw_scan_rsp_data)); + if (raw_scan_ret){ + ESP_LOGE(GATTS_TABLE_TAG, "config raw scan rsp data failed, error code = %x", raw_scan_ret); + } + adv_config_done |= SCAN_RSP_CONFIG_FLAG; + #else + //config adv data + esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data); + if (ret){ + ESP_LOGE(GATTS_TABLE_TAG, "config adv data failed, error code = %x", ret); + } + adv_config_done |= ADV_CONFIG_FLAG; + //config scan response data + ret = esp_ble_gap_config_adv_data(&scan_rsp_data); + if (ret){ + ESP_LOGE(GATTS_TABLE_TAG, "config scan response data failed, error code = %x", ret); + } + adv_config_done |= SCAN_RSP_CONFIG_FLAG; + #endif + esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, IDX_NB, SVC_INST_ID); + if (create_attr_ret){ + ESP_LOGE(GATTS_TABLE_TAG, "create attr table failed, error code = %x", create_attr_ret); + } + } + break; + case ESP_GATTS_READ_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT"); + // esp_gatt_rsp_t rsp; + // memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + // rsp.attr_value.handle = param->read.handle; + // rsp.attr_value.len = 4; + // rsp.attr_value.value[0] = 0xde; + // rsp.attr_value.value[1] = 0xed; + // rsp.attr_value.value[2] = 0xbe; + // rsp.attr_value.value[3] = 0xef; + // esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, + // ESP_GATT_OK, NULL); + break; + case ESP_GATTS_WRITE_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT, need_rsp=%d", param->write.need_rsp); + + if (!param->write.is_prep){ + // the data length of gattc write must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX. + ESP_LOGI(GATTS_TABLE_TAG, "GATT_WRITE_EVT, handle = %d, value len = %d, value :", param->write.handle, param->write.len); + esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len); + if (ble_gatts_handle_table[IDX_DATA_READ_WRITE_VAL] == param->write.handle) + { + ble_read_data(param->write.value, param->write.len); + } + if (ble_gatts_handle_table[IDX_DATA_NOTIFY_CFG] == param->write.handle && param->write.len == 2){ + uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0]; + if (descr_value == 0x0001){ + ESP_LOGI(GATTS_TABLE_TAG, "notify enable"); + data_notify_enable = true; + }//else if (descr_value == 0x0002){ + // ESP_LOGI(GATTS_TABLE_TAG, "indicate enable"); + // } + else if (descr_value == 0x0000){ + ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable "); + data_notify_enable = false; + }else{ + ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value"); + esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len); + } + + } + /* send response when param->write.need_rsp is true*/ + if (param->write.need_rsp){ + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + } + }else{ + /* handle prepare write */ + example_prepare_write_event_env(gatts_if, &prepare_write_env, param); + } + break; + case ESP_GATTS_EXEC_WRITE_EVT: + // the length of gattc prepare write data must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX. + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_EXEC_WRITE_EVT"); + example_exec_write_event_env(&prepare_write_env, param); + break; + case ESP_GATTS_MTU_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu); + break; + case ESP_GATTS_CONF_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONF_EVT, status = %d, attr_handle %d", param->conf.status, param->conf.handle); + break; + case ESP_GATTS_START_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle); + break; + case ESP_GATTS_CONNECT_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id); + esp_log_buffer_hex(GATTS_TABLE_TAG, param->connect.remote_bda, 6); + esp_ble_conn_update_params_t conn_params = {0}; + memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); + /* For the iOS system, please refer to Apple official documents about the BLE connection parameters restrictions. */ + conn_params.latency = 0; + conn_params.max_int = 0x20; // max_int = 0x20*1.25ms = 40ms + conn_params.min_int = 0x10; // min_int = 0x10*1.25ms = 20ms + conn_params.timeout = 400; // timeout = 400*10ms = 4000ms + //start sent the update connection parameters to the peer device. + esp_ble_gap_update_conn_params(&conn_params); + is_connected = true; + ble_gatts_conn_id = param->connect.conn_id; + ble_gatts_if = gatts_if; + break; + case ESP_GATTS_DISCONNECT_EVT: + ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_DISCONNECT_EVT, reason = 0x%x", param->disconnect.reason); + esp_ble_gap_start_advertising(&adv_params); + is_connected = false; + break; + case ESP_GATTS_CREAT_ATTR_TAB_EVT:{ + if (param->add_attr_tab.status != ESP_GATT_OK){ + ESP_LOGE(GATTS_TABLE_TAG, "create attribute table failed, error code=0x%x", param->add_attr_tab.status); + } + else if (param->add_attr_tab.num_handle != IDX_NB){ + ESP_LOGE(GATTS_TABLE_TAG, "create attribute table abnormally, num_handle (%d) \ + doesn't equal to IDX_NB(%d)", param->add_attr_tab.num_handle, IDX_NB); + } + else { + ESP_LOGI(GATTS_TABLE_TAG, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle); + memcpy(ble_gatts_handle_table, param->add_attr_tab.handles, sizeof(ble_gatts_handle_table)); + esp_ble_gatts_start_service(ble_gatts_handle_table[IDX_SVC]); + } + break; + } + case ESP_GATTS_STOP_EVT: + case ESP_GATTS_OPEN_EVT: + case ESP_GATTS_CANCEL_OPEN_EVT: + case ESP_GATTS_CLOSE_EVT: + case ESP_GATTS_LISTEN_EVT: + case ESP_GATTS_CONGEST_EVT: + case ESP_GATTS_UNREG_EVT: + case ESP_GATTS_DELETE_EVT: + default: + break; + } +} + + +static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ + /* If event is register event, store the gatts_if for each profile */ + if (event == ESP_GATTS_REG_EVT) { + if (param->reg.status == ESP_GATT_OK) { + ble_gatts_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if; + } else { + ESP_LOGE(GATTS_TABLE_TAG, "reg app failed, app_id %04x, status %d", + param->reg.app_id, + param->reg.status); + return; + } + } + do { + int idx; + for (idx = 0; idx < PROFILE_NUM; idx++) { + /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */ + if (gatts_if == ESP_GATT_IF_NONE || gatts_if == ble_gatts_profile_tab[idx].gatts_if) { + if (ble_gatts_profile_tab[idx].gatts_cb) { + ble_gatts_profile_tab[idx].gatts_cb(event, gatts_if, param); + } + } + } + } while (0); +} + + +void ble_gatts_server_init(void) +{ + esp_err_t ret; + + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_init(&bt_cfg); + if (ret) { + ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); + if (ret) { + ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_init(); + if (ret) { + ESP_LOGE(GATTS_TABLE_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_bluedroid_enable(); + if (ret) { + ESP_LOGE(GATTS_TABLE_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret)); + return; + } + + ret = esp_ble_gatts_register_callback(gatts_event_handler); + if (ret){ + ESP_LOGE(GATTS_TABLE_TAG, "gatts register error, error code = %x", ret); + return; + } + + ret = esp_ble_gap_register_callback(gap_event_handler); + if (ret){ + ESP_LOGE(GATTS_TABLE_TAG, "gap register error, error code = %x", ret); + return; + } + + ret = esp_ble_gatts_app_register(ESP_APP_ID); + if (ret){ + ESP_LOGE(GATTS_TABLE_TAG, "gatts app register error, error code = %x", ret); + return; + } + + esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500); + if (local_mtu_ret){ + ESP_LOGE(GATTS_TABLE_TAG, "set local MTU failed, error code = %x", local_mtu_ret); + } +} + + +/* + * 上报长度过长,则分包,这里限制长度最大20,分包协议: + * [0] ‘#’,分包标识 + * [1] 总包个数 + * [2] 当前包号,从0开始 + * ... 包数据 + */ +static uint16_t gatts_mtu_size = 23; +void ble_write_data(int id, uint8_t *data, int len) +{ + ESP_LOGI(GATTS_TABLE_TAG, "ble_write_data %d:", len); + esp_log_buffer_hex(GATTS_TABLE_TAG, data, len); + if (len <= gatts_mtu_size - 3) /* 包数据可以一次完整发送 */ + { + esp_ble_gatts_send_indicate(ble_gatts_if, ble_gatts_conn_id, ble_gatts_handle_table[id], len, data, false); + } + else /* 需要分包发送 */ + { + int total_num = 0; + uint8_t buf[gatts_mtu_size - 3]; + if ((len % (gatts_mtu_size - 6)) == 0){ + total_num = len / (gatts_mtu_size - 6); + } + else{ + total_num = len / (gatts_mtu_size - 6) + 1; + } + // ESP_LOGI(GATTS_TABLE_TAG, "notify packet has %d", total_num); + + int i = 0; + buf[0] = '#'; + buf[1] = total_num; + for (i = 0; i < total_num - 1; i++) + { + buf[2] = i; + memcpy(buf + 3, data + i * (gatts_mtu_size - 6), gatts_mtu_size - 6); + esp_ble_gatts_send_indicate(ble_gatts_if, ble_gatts_conn_id, ble_gatts_handle_table[id],gatts_mtu_size - 3, buf, false); + } + /* 最后一个包 */ + buf[2] = i; + memcpy(buf + 3, data + i * (gatts_mtu_size - 6), len % (gatts_mtu_size - 6)); + esp_ble_gatts_send_indicate(ble_gatts_if, ble_gatts_conn_id, ble_gatts_handle_table[id], (len % (gatts_mtu_size - 6)) + 3, buf, false); + // ESP_LOGI(GATTS_TABLE_TAG, "notify packet send end!"); + } +} + +// 注意,该函数不是线程安全了,因为假设包是按顺序接受的,无法同时处理多个包的交替发送 +void ble_read_data(uint8_t *data, int len) +{ + ESP_LOGI(GATTS_TABLE_TAG, "ble_read_data"); + static uint8_t buf[1024]; // 注意,这里大小没处理 + static int buflen = 0; + static int total_num = 0; + static int next_packet_id = 0; + uint8_t *txbuf = NULL; + int txlen = 0; + + if (len <= 0) return; + if (data[0] == '#') // 分包数据 + { + if (len < 3) return; + if ((buflen != 0 && data[1] != total_num) || data[2] != next_packet_id) // 包错误,全部丢弃 + { + ESP_LOGE(GATTS_TABLE_TAG, "ble packet err!"); + buflen = 0; + next_packet_id = 0; + return; + } + if (buflen == 0) total_num = data[1]; + + memcpy(buf + buflen, data + 3, len - 3); + buflen += len - 3; + next_packet_id++; + if (next_packet_id == data[1]) // 接收完成 + { + ESP_LOGI(GATTS_TABLE_TAG, "ble paclet recoved ok, all %d packets!", next_packet_id); + esp_log_buffer_hex(GATTS_TABLE_TAG, buf, buflen); + pad_deal_recived_data(buf, buflen, &data_notify_enable, &txbuf, &txlen); + if (txbuf != NULL) + { + ble_write_data(IDX_DATA_READ_WRITE_VAL, txbuf, txlen); + free(txbuf); + } + buflen = 0; + next_packet_id = 0; + } + } + else // 不分包的数据 + { + esp_log_buffer_hex(GATTS_TABLE_TAG, data, len); + pad_deal_recived_data(data, len, &data_notify_enable, &txbuf, &txlen); + if (txbuf != NULL) + { + ble_write_data(IDX_DATA_READ_WRITE_VAL, txbuf, txlen); + free(txbuf); + } + } +} + + +void ble_server_notify(uint8_t *data, int len) +{ + if (data_notify_enable && is_connected) + { + ble_write_data(IDX_DATA_NOTIFY_VAL, data, len); + } +} diff --git a/main/communication_pad/communication_pad.c b/main/communication_pad/communication_pad.c new file mode 100644 index 0000000..432bb89 --- /dev/null +++ b/main/communication_pad/communication_pad.c @@ -0,0 +1,168 @@ +// 与pad之间进行数据通信,具有蓝牙、wifi两种方式 +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" + +#include "inc/communication_pad.h" +#include "inc/wifi_softap.h" +#include "inc/tcp_server.h" +#include "inc/ble_gatts_server.h" +#include "../stm32/ModbusS.h" +#include "../stm32/config.h" + +static const char *TAG = "communication_pad"; + + +padDataCtrl_t pad_notify_data; +struct measureData measure_data; + + +int register_pad_data(padDataCtrl_t *data_ctrl, uint8_t tag, uint8_t *data, int len, padUpdataFun updata_fun) +{ + if (data_ctrl->cnt >= MAX_NOTIFY_DATA) + { + ESP_LOGI(TAG, "register_pad_data failed, data_ctrl is full"); + return -1; + } + + data_ctrl->datas[data_ctrl->cnt].tag = tag; + data_ctrl->datas[data_ctrl->cnt].data = data; + data_ctrl->datas[data_ctrl->cnt].len = len; + data_ctrl->datas[data_ctrl->cnt].updata_fun = updata_fun; + data_ctrl->cnt++; + return 0; +} + +extern flow_t *pflow; +extern depth_t *depth_data; +static void measure_data_updata(void) +{ + measure_data.speed = depth_data->speed; + measure_data.time = depth_data->one_pile_work_time; + measure_data.depth = depth_data->depth; + measure_data.pile_id = gWordVar[LAST_PILE_ID_ADDR]; + measure_data.flow1 = pflow[0].flow; + measure_data.flow_10cm1 = depth_data->depth_flow[0]; + measure_data.flow_total1 = pflow[0].total_flow; + measure_data.flow2 = pflow[1].flow; + measure_data.flow_10cm2 = depth_data->depth_flow[1]; + measure_data.flow_total2 = pflow[1].total_flow; + measure_data.current[0] = gWordVar[AC_CURRENT_REG_ADDR + 0]; + measure_data.current[1] = gWordVar[AC_CURRENT_REG_ADDR + 1]; + measure_data.current[2] = gWordVar[AC_CURRENT_REG_ADDR + 2]; +} + + +// 上报data_ctrl中的数据 +static void pad_notify_data_fun(const padDataCtrl_t *data_ctrl) +{ + uint8_t data[1024]; // 这里的大小并没有控制 + int data_len =0; + + // data[0] = NOTIFY_TAG; + // data_len = 1; + + for (int i = 0; i < data_ctrl->cnt; i++) + { + if (data_ctrl->datas[i].updata_fun) data_ctrl->datas[i].updata_fun(); // 更新数据 + data[data_len++] = data_ctrl->datas[i].tag; + data[data_len++] = data_ctrl->datas[i].len; + memcpy(data + data_len, data_ctrl->datas[i].data, data_ctrl->datas[i].len); + data_len += data_ctrl->datas[i].len; + } + + // 调用蓝牙和wifi的notify函数 + tcp_server_notify(data, data_len); + ble_server_notify(data, data_len); +} + + +static void pad_notify_task(void *pvParameters) +{ + ESP_LOGI(TAG, "pad_notify_task"); + while (1) + { + pad_notify_data_fun(&pad_notify_data); + vTaskDelay(pdMS_TO_TICKS(100)); + } + + vTaskDelete(NULL); +} + + + +// 通信初始化 +void pad_communication_init(void) +{ + wifi_init_softap(); + tcp_server_init(); + + ble_gatts_server_init(); + + register_pad_data(&pad_notify_data, 0xA1, &measure_data, sizeof(measure_data), measure_data_updata); + register_pad_data(&pad_notify_data, 0xA2, &gWordVar[REG_GPS_MESSAGE], sizeof(gps_message_t), NULL); // 透传不用更新数据 + xTaskCreate(pad_notify_task, "pad_notify_task", 4096, NULL, 8, NULL); +} + +/* + * 协议说明: + * 功能码1byte + ... + * 0XF0:写寄存器 2byte寄存器地址 + 1byte数据长度(字节为单位) + 数据 小端 + * 0XF1:读寄存器 2byte寄存器地址 + 1byte数据长度(字节为单位) + * 0XF2:开notify + * 0XF3:关notify + * 如果是读寄存器功能,则从参数返回读取结果数组,否则返回NULL,注意,返回的指针需要手动free + */ +void pad_deal_recived_data(uint8_t *data, int len, int *enable_notify, uint8_t **retbuf, int *retlen) +{ + ESP_LOGI(TAG, "pad_deal_recived_data"); + *retbuf = NULL; + *retlen = 0; + + if (len >= 4 && data[0] == 0xF0) /* 写gWordVar寄存器 */ + { + uint16_t addr = data[1] + (data[2] << 8); + uint16_t addr_ = addr; + uint8_t cnt = data[3]; + if (cnt > len - 4) + { + ESP_LOGI(TAG, "write format is fault, cnt > len - 4"); + return; + } + ESP_LOGI(TAG, "write addr:%d cnt:%d", addr, cnt); + uint8_t i; + for (i = 0 + 4; i < cnt + 4; i+=2) /* 发送的数据要求两字节对齐 */ + { + gWordVar[addr++] = data[i] + (data[i + 1] << 8); + ESP_LOGI(TAG, "gwordvar[%d]:0x%x", addr-1, gWordVar[addr-1]); + } + + ModBusWordWriteHook(addr_, cnt); + } + else if (len >= 4 && data[0] == 0xF1) /* 读gWordVar,返回*/ + { + uint16_t addr = data[1] + (data[2] << 8); + uint8_t cnt = data[3]; + ESP_LOGI(TAG, "read addr:%d cnt:%d", addr, cnt); + *retbuf = (uint8_t *)malloc(cnt + 4); + (*retbuf)[0] = data[0]; + (*retbuf)[1] = data[1]; + (*retbuf)[2] = data[2]; + (*retbuf)[3] = data[3]; + memcpy((*retbuf) + 4, (uint8_t *)(gWordVar + addr), cnt); + *retlen = cnt + 4; + } + else if (len == 1 && data[0] == 0xF2) /* 开启notify */ + { + ESP_LOGI(TAG, "enable notify"); + *enable_notify = 1; + } + else if (len == 1 && data[0] == 0xF3) /* 关闭notify */ + { + ESP_LOGI(TAG, "disable notify"); + *enable_notify = 0; + } + else ESP_LOGI(TAG, "format err!"); +} diff --git a/main/communication_pad/inc/ble_gatts_server.h b/main/communication_pad/inc/ble_gatts_server.h new file mode 100644 index 0000000..a928b20 --- /dev/null +++ b/main/communication_pad/inc/ble_gatts_server.h @@ -0,0 +1,32 @@ +#ifndef __BLE_GATTS_SERVER_H +#define __BLE_GATTS_SERVER_H + +#include +#include +#include +#include + +/* Attributes State Machine */ +enum +{ + IDX_SVC, + + /* gWordVar data write */ + IDX_DATA_READ_WRITE_CHAR, + IDX_DATA_READ_WRITE_VAL, + IDX_DATA_READ_WRITE_CFG, + + /* gWordVar data notify */ + IDX_DATA_NOTIFY_CHAR, + IDX_DATA_NOTIFY_VAL, + IDX_DATA_NOTIFY_CFG, + + IDX_NB, +}; + +void ble_gatts_server_init(void); +void ble_write_data(int id, uint8_t *data, int len); +void ble_read_data(uint8_t *data, int len); +void ble_server_notify(uint8_t *data, int len); + +#endif \ No newline at end of file diff --git a/main/communication_pad/inc/communication_pad.h b/main/communication_pad/inc/communication_pad.h new file mode 100644 index 0000000..4c7f9cc --- /dev/null +++ b/main/communication_pad/inc/communication_pad.h @@ -0,0 +1,63 @@ +#ifndef __COMMUNICATION_PAD_H +#define __COMMUNICATION_PAD_H + +#include + +#define MAX_NOTIFY_DATA 20 +#define NOTIFY_TAG 0xF2 + +struct measureData // 测量数据 +{ + int16_t speed; + uint16_t time; + int16_t depth; + uint16_t pile_id; + + int16_t flow1; + uint16_t flow_10cm1; + int32_t flow_total1; + + int16_t flow2; + uint16_t flow_10cm2; + int32_t flow_total2; + + uint16_t current[3]; +}; + +typedef struct gps_message +{ + uint8_t gps_status; // GPS定位状态 + uint8_t gps_view; // GPS可视状态 + uint8_t gps_use; // GPS使用状态 + uint8_t reg[1]; // 保留 + uint32_t utc; // utc时间 + double x; // 大地平面坐标 + double y; + double dir; // 方向 + double pitch; // 俯仰角 +} gps_message_t; + + +typedef void (*padUpdataFun)(void); + +typedef struct padDataStruct +{ + uint8_t tag; + int len; + uint8_t *data; + padUpdataFun updata_fun; +} padData_t; + + +typedef struct padDataCtrlStruct +{ + int cnt; + padData_t datas[MAX_NOTIFY_DATA]; // 输出数据,即上报数据 +} padDataCtrl_t; + + +void pad_communication_init(void); +int register_pad_data(padDataCtrl_t *data_ctrl, uint8_t tag, uint8_t *data, int len, padUpdataFun updata_fun); +void pad_deal_recived_data(uint8_t *data, int len, int *enable_notify, uint8_t **retbuf, int *ret_len); + +#endif \ No newline at end of file diff --git a/main/communication_pad/inc/tcp_server.h b/main/communication_pad/inc/tcp_server.h new file mode 100644 index 0000000..8068d5b --- /dev/null +++ b/main/communication_pad/inc/tcp_server.h @@ -0,0 +1,23 @@ +#ifndef __TCP_SERVER_H +#define __TCP_SERVER_H + +#include + +#define TCP_SERVER_PORT 6000 + + + +// 链表,记录连接的客户端 +struct clientNode +{ + struct tcp_pcb *pcb; + int enable_notify; // 是否使能数据上报 + struct clientNode *next; +}; + +void tcp_server_init(void); +void ble_write_data(int id, uint8_t *data, int len); +void ble_read_data(uint8_t *data, int len); +void tcp_server_notify(uint8_t *data, int len); + +#endif \ No newline at end of file diff --git a/main/communication_pad/inc/wifi_softap.h b/main/communication_pad/inc/wifi_softap.h new file mode 100644 index 0000000..6983dc2 --- /dev/null +++ b/main/communication_pad/inc/wifi_softap.h @@ -0,0 +1,6 @@ +#ifndef __WIFI_SOFTAP_H +#define __WIFI_SOFTAP_H + +void wifi_init_softap(void); + +#endif \ No newline at end of file diff --git a/main/communication_pad/tcp_server.c b/main/communication_pad/tcp_server.c new file mode 100644 index 0000000..9c9c40c --- /dev/null +++ b/main/communication_pad/tcp_server.c @@ -0,0 +1,168 @@ +#include +#include +#include "lwip/ip_addr.h" +#include "lwip/tcp.h" +#include "lwip/err.h" +#include "lwip/opt.h" +#include "lwip/sockets.h" +#include "esp_log.h" + +#include "tcp_server.h" +#include "inc/communication_pad.h" + +#define LOG_TAG "[communication_tcp_sr]: " + + +struct clientNode client_list; // 客户端链表头结点 +struct clientNode *client_r_p = &client_list; // 客户端链表尾指针 + +void client_list_add(struct tcp_pcb *pcb) +{ + struct clientNode *client = (struct clientNode *)malloc(sizeof(struct clientNode)); + client->pcb = pcb; + client->enable_notify = 0; + client->next = NULL; + client_r_p->next = client; + client_r_p = client; +} + +void client_list_delete(struct tcp_pcb *pcb) +{ + struct clientNode *p = &client_list; + while (p->next) + { + if (p->next->pcb == pcb) + { + struct clientNode *q = p->next; + if (q == client_r_p) + { + client_r_p = p; + } + p->next = q->next; + free(q); + return; + } + p = p->next; + } +} + +void cilent_list_delete_all(void) +{ + struct clientNode *p = &client_list; + while (p->next) + { + struct clientNode *q = p->next; + p->next = q->next; + free(q); + } + client_r_p = &client_list; +} + +struct clientNode* find_client_by_pcb(struct tcp_pcb *pcb) +{ + struct clientNode *p = client_list.next; + struct clientNode *ret = NULL; + while (p) + { + if (p->pcb == pcb) + { + ret = p; + break; + } + p = p->next; + } + return ret; +} + + +static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) { + if (p != NULL) { + uint8_t *rxbuf; + uint8_t *txbuf = NULL; + int rxlen, txlen = 0; + tcp_recved(newpcb, p->tot_len); + rxbuf = (uint8_t *)p->payload; + rxlen = p->len; + ESP_LOGI(LOG_TAG, "recive data %d:", rxlen); + esp_log_buffer_hex(LOG_TAG, rxbuf, rxlen); + + // 接受到数据,调用pad_deal_recived_data处理,如果需要回复(读操作),则再将数据发送出去 + struct clientNode* client = find_client_by_pcb(newpcb); + if (!client) + { + ESP_LOGI(LOG_TAG, "err:not find this client"); + return ERR_OK; + } + pad_deal_recived_data(rxbuf, rxlen, &client->enable_notify, &txbuf, &txlen); + if (txbuf) + { + tcp_write(newpcb, txbuf, txlen, 1); + free(txbuf); + } + pbuf_free(p); + } + else if (err == ERR_OK) + { + ESP_LOGI(LOG_TAG, "gps1 remote end is closing the connection\n"); + tcp_err(newpcb, NULL); + tcp_recv(newpcb, NULL); + // tcp_poll(newpcb, NULL, 120); + err_t err_p = tcp_close(newpcb); + client_list_delete(newpcb); + if (ERR_OK != err_p) + { + ESP_LOGI(LOG_TAG, "gps1 close error. err:%d\n", err_p); + } + return err_p; + } + return ERR_OK; +} + + +static void ModBusSlave_conn_err(void *arg, err_t err) { + ESP_LOGI(LOG_TAG, "connect err!"); + // log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err); + // cilent_list_delete_all(); // 不知道为什么这个回调函数没有提供newpcb +} +static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) { + // if (newpcb) { + // // log_printf(LERROR, LOG_TAG "close pcb\n"); + // tcp_close(newpcb); + // newpcb = NULL; + // } + ESP_LOGI(LOG_TAG, "poll!"); + return ERR_OK; +} + + +static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) { + tcp_err(pcb, ModBusSlave_conn_err); + tcp_recv(pcb, ModBusSlave_recv); + // tcp_poll(pcb, ModBusSlave_poll, 120); // 60 second timeout + client_list_add(pcb); + return ERR_OK; +} + +void tcp_server_init(void) { + struct tcp_pcb *pcb; + pcb = tcp_new(); + tcp_bind(pcb, IP_ADDR_ANY, TCP_SERVER_PORT); + pcb = tcp_listen(pcb); + tcp_accept(pcb, ModBusSlave_accept); +} + +// 遍历所有客户端,如果允许上报,则将数据上报 +void tcp_server_notify(uint8_t *data, int len) +{ + struct clientNode *p = client_list.next; + while (p) + { + if (p->enable_notify == 1) // 开启上报 + { + ESP_LOGI(LOG_TAG, "tcp_server_notify"); + esp_log_buffer_hex(LOG_TAG, data, len); + tcp_write(p->pcb, data, len, 1); + } + p = p->next; + } +} diff --git a/main/communication_pad/wifi_softap.c b/main/communication_pad/wifi_softap.c new file mode 100644 index 0000000..ad819ff --- /dev/null +++ b/main/communication_pad/wifi_softap.c @@ -0,0 +1,99 @@ +#include +#include "wifi_softap.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_mac.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +// #include "esp_system.h" +// #include "../../../components/esp_wifi/include/esp_wifi.h" +// #include "../../../components/esp_hw_support/include/esp_mac.h" + +#define ESP_WIFI_SSID "T2N_056455" +#define ESP_WIFI_PASS "01010101" +#define ESP_WIFI_CHANNEL 1 +#define MAX_STA_CONN 8 + +static const char *TAG = "wifi softAP"; + +static void wifi_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + if (event_id == WIFI_EVENT_AP_STACONNECTED) { + wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data; + ESP_LOGI(TAG, "station "MACSTR" join, AID=%d", + MAC2STR(event->mac), event->aid); + } else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) { + wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data; + ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d", + MAC2STR(event->mac), event->aid); + } +} + +void wifi_init_softap(void) +{ + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_ap(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &wifi_event_handler, + NULL, + NULL)); + + wifi_config_t wifi_config = { + .ap = { + .ssid = ESP_WIFI_SSID, + .ssid_len = strlen(ESP_WIFI_SSID), + .channel = ESP_WIFI_CHANNEL, + .password = ESP_WIFI_PASS, + .max_connection = MAX_STA_CONN, + .authmode = WIFI_AUTH_WPA_WPA2_PSK}, + }; + + nvs_handle_t my_handle; + esp_err_t err = nvs_open("wifi", NVS_READWRITE, &my_handle); + if (err == ESP_OK) + { + size_t len; + char temp_str[64]; + uint8_t channel; + if (nvs_get_str(my_handle, "ap_ssid", temp_str, &len) == ESP_OK) + { + strncpy((char*)wifi_config.ap.ssid, temp_str, len); + wifi_config.ap.ssid_len = len; + } + if (nvs_get_str(my_handle, "ap_psk", temp_str, &len) == ESP_OK) + { + strncpy((char*)wifi_config.ap.password, temp_str, len); + } + if (nvs_get_u8(my_handle, "ap_ch", &channel) == ESP_OK) + { + wifi_config.ap.channel = channel; + } + + nvs_close(my_handle); + } + if (strlen(ESP_WIFI_PASS) == 0) + { + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d", + ESP_WIFI_SSID, ESP_WIFI_PASS, ESP_WIFI_CHANNEL); +} + diff --git a/main/main.c b/main/main.c index 1a8fa6d..abf7e86 100644 --- a/main/main.c +++ b/main/main.c @@ -1,22 +1,112 @@ +/* WiFi station Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" #include "esp_system.h" -#include "nvs_flash.h" +#include "esp_wifi.h" +#include "esp_event.h" #include "esp_log.h" +#include "nvs_flash.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include +#include "driver/ledc.h" +#include "esp_err.h" +#include "can_network.h" +#include "freertos/queue.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "driver/mcpwm.h" +#include "driver/uart.h" +/*蓝牙相关的头文件*/ +// #include "esp_bt.h" +// #include "esp_gap_ble_api.h" +// #include "esp_gatts_api.h" +// #include "esp_bt_defs.h" +// #include "esp_bt_main.h" +//#include "ble_server.h" +#include "stm32/config.h" +#include "communication_pad.h" +#include "stm32/pile_id.h" +#include "stm32/led.h" -#include "config.h" -#include "uart0_modbus_slave.h" -#include "flow.h" -#include "bl0939.h" -#include "depth.h" + +/* The examples use WiFi configuration that you can set via project configuration menu + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#if CONFIG_ESP_WIFI_AUTH_OPEN +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN +#elif CONFIG_ESP_WIFI_AUTH_WEP +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP +#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK +#endif + +/* FreeRTOS event group to signal when we are connected*/ +//static EventGroupHandle_t s_wifi_event_group; + +/* The event group allows multiple bits for each event, but we only care about two events: + * - we are connected to the AP with an IP + * - we failed to connect after the maximum amount of retries */ +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 +#define GPIO_4G_PWR GPIO_NUM_4 +#define PWR_4G_ON (0) +#define PWR_4G_OFF (1) static const char *TAG = "main"; +//static int s_retry_num = 0; + +// extern void wifi_init_softap(void); + +void PWR_4G_Init(void); +extern void can_init(void); +extern void FLOW_init(); +extern void DEPTH_init(); +extern void BL0939_init(void); +extern void ads1220_task_start(void); +extern void ModBusTCPSlave_init(void); +extern esp_err_t i2c_master_init(void); +extern void config_load(void); +extern void uart0_modbus_slave_init(void); +extern void bt_client_init(void); +// extern void communication_tcp_init(void); +//extern void ESP32_Uart_Receive_Data(void); uint32_t rtc_clk_apb_freq; -extern void pcnt_rotary_encoder_init_(void); +extern uint16_t *cur_pile_id; +extern cal_4_20ma_t *cal_4_20ma;//电流数据结构体 +extern flow_config_t *flow_config;//流量数据结构体 +extern depth_config_t *depth_config;//深度数据结构体 + void app_main(void) { + // Initialize NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { @@ -24,12 +114,60 @@ void app_main(void) ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); + ESP_ERROR_CHECK(i2c_master_init()); + //restore_default(); + // *cur_pile_id = 0; + // save_pile_id(); + config_load();//读取保存在FRAM里的数据 + // ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); + // rtc_clk_apb_freq = rtc_clk_apb_freq_get(); + // ESP_LOGI(TAG, "rtc_clk_apb_freq=%u", rtc_clk_apb_freq); + + // wifi_init_softap();//ok + // wifi_init_sta(); + // can_init(); + // PWR_4G_Init(); + // ModBusTCPSlave_init(); + // communication_tcp_init(); + + led_init(); + ads1220_task_start(); /* 两路电流AD采样获取瞬时流量,计算累计流量,目前配置的是10HZ,取决于SPS */ + BL0939_init(); /* 实时采集通道电流,根据depth_config_t中配置的启动与结束电流,以及持续时间进行move_t机器开关状态的判断 */ + DEPTH_init(); /* 编码器计算深度,同时进行流量的按深度计数,以及record的记录 */ + // FLOW_init(); /* 两一种计算流量的方法,计算累计流量 */ + pile_id_init(); - config_init(); uart0_modbus_slave_init(); - flow_init(); - BL0939_init(); - // pcnt_rotary_encoder_init_(); - DEPTH_init(); + // ble_gatts_server_init(); + pad_communication_init(); + + // bt_client_init();//ok + //ESP32_Uart_Receive_Data(); + } +void PWR_4G_Init(void) +{ + + ESP_LOGI(TAG, "HELLO~"); + save_cal_4_20ma(); + // zero-initialize the config structure. + gpio_config_t io_conf = { + // disable interrupt + .intr_type = GPIO_INTR_DISABLE, + // set as output mode + .mode = GPIO_MODE_OUTPUT, + // bit mask of the pins that you want to set,e.g.GPIO18/19 + .pin_bit_mask = GPIO_4G_PWR, + // disable pull-down mode + .pull_down_en = 0, + // disable pull-up mode + .pull_up_en = 0, + }; + + // configure GPIO with the given settings + gpio_config(&io_conf); + gpio_set_level(GPIO_4G_PWR, PWR_4G_OFF); + vTaskDelay(pdMS_TO_TICKS(1000)); + gpio_set_level(GPIO_4G_PWR, PWR_4G_ON); +} \ No newline at end of file diff --git a/main/modbus-tcp.c b/main/modbus-tcp.c new file mode 100644 index 0000000..e80debb --- /dev/null +++ b/main/modbus-tcp.c @@ -0,0 +1,140 @@ + +/* Includes ------------------------------------------------------------------*/ +#include +#include + +#include "lwip/ip_addr.h" +#include "lwip/tcp.h" +#include "lwip/err.h" +#include "lwip/opt.h" +#include "lwip/sockets.h" +#include "stm32/ModbusS.h" +#include "esp_log.h" +// #include "log.h" + +#define LOG_TAG "[mb_tcp_sr]: " +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +// static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +// static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err); +// static void ModBusSlave_conn_err(void *arg, err_t err); +// static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *pcb); +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Called when a data is received on the telnet connection + * @param arg the user argument + * @param pcb the tcp_pcb that has received the data + * @param p the packet buffer + * @param err the error value linked with the received data + * @retval error value + */ +int ModBusTcpMonitor; +static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) { + /* We perform here any necessary processing on the pbuf */ + if (p != NULL) { + uint8_t *txbuf; + uint8_t *rxbuf; + int txlen, rxlen; + /* We call this function to tell the LwIp that we have processed the data */ + /* This lets the stack advertise a larger window, so more data can be received*/ + tcp_recved(newpcb, p->tot_len); + rxbuf = (uint8_t *)p->payload; + rxlen = p->len; + if (rxlen < 6) { + pbuf_free(p); + return tcp_close(newpcb); + } + txbuf = (uint8_t *)mem_malloc(1024 + 16); + if (txbuf == NULL) { + return tcp_close(newpcb); + } + ModBusTcpMonitor = 0; + txlen = ModbusSlaveProcess(&txbuf[6], &rxbuf[6], (rxlen - 6), 0); //以前有 2023年4月24日14:39:11 + // log_printf(LINFO, LOG_TAG "[%s] ModbusSlaveProcess (ret=%d)", __FUNCTION__, txlen); + if (txlen > 0) { + int i; + for (i = 0; i < 4; i++) { + txbuf[i] = rxbuf[i]; + } + txbuf[4] = (uint8_t)(txlen >> 8); + txbuf[5] = (uint8_t)(txlen & 0xff); + tcp_write(newpcb, txbuf, txlen + 6, 1); + ModBusTcpMonitor = 0; + } + mem_free(txbuf); + /* End of processing, we free the pbuf */ + pbuf_free(p); + } else if (err == ERR_OK) { + /* When the pbuf is NULL and the err is ERR_OK, the remote end is closing the connection. */ + /* We free the allocated memory and we close the connection */ + // log_printf(LWARN, LOG_TAG "remote end is closing the connection\n"); + tcp_err(newpcb, NULL); + tcp_recv(newpcb, NULL); + tcp_poll(newpcb, NULL, 120); // 60 second timeout + // return tcp_close(newpcb); + err_t err_p = tcp_close(newpcb); + if (ERR_OK != err_p) { + // log_printf(LERROR, LOG_TAG "close error. err:%d\n", err_p); + } + return err_p; + } + return ERR_OK; +} +/** + * @brief This function is called when an error occurs on the connection + * @param arg + * @parm err + * @retval None + */ +static void ModBusSlave_conn_err(void *arg, err_t err) { + // log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err); +} +static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) { + // if (newpcb) { + // // log_printf(LERROR, LOG_TAG "close pcb\n"); + // tcp_close(newpcb); + // newpcb = NULL; + // } + ESP_LOGI(LOG_TAG, "HELLO!"); + return ERR_OK; +} +/** + * @brief This function when the Telnet connection is established + * @param arg user supplied argument + * @param pcb the tcp_pcb which accepted the connection + * @param err error value + * @retval ERR_OK + */ +static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) { + /* Tell LwIP to associate this structure with this connection. */ + // tcp_arg(pcb, mem_calloc(sizeof(struct name), 1)); + /* Configure LwIP to use our call back functions. */ + tcp_err(pcb, ModBusSlave_conn_err); + tcp_recv(pcb, ModBusSlave_recv); + tcp_poll(pcb, ModBusSlave_poll, 1); // 60 second timeout + /* Send out the first message */ + // tcp_write(pcb, GREETING, strlen(GREETING), 1); + return ERR_OK; +} +/** + * @brief Initialize the hello application + * @param None + * @retval None + */ +void ModBusTCPSlave_init(void) { + struct tcp_pcb *pcb; + /* Create a new TCP control block */ + pcb = tcp_new(); + /* Assign to the new pcb a local IP address and a port number */ + /* Using IP_ADDR_ANY allow the pcb to be used by any local interface */ + tcp_bind(pcb, IP_ADDR_ANY, 502); + /* Set the connection to the LISTEN state */ + pcb = tcp_listen(pcb); + /* Specify the function to be called when a connection is established */ + tcp_accept(pcb, ModBusSlave_accept); + // LSAPI_Log_Debug("ModBus Tcp server listen port:%d\n", 502); +} +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/main/modbus-tcp.h b/main/modbus-tcp.h new file mode 100644 index 0000000..d8b4e2e --- /dev/null +++ b/main/modbus-tcp.h @@ -0,0 +1,27 @@ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __HELLOWERLOD_H +#define __HELLOWERLOD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/** @defgroup helloworld_Exported_Functions + * @{ + */ + +void HelloWorld_init(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __HELLOWERLOD_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/main/modbus/inc/ModbusS.h b/main/modbus/inc/ModbusS.h deleted file mode 100644 index d88d4f0..0000000 --- a/main/modbus/inc/ModbusS.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _MODBUS_H -#define _MODBUS_H - -#include -#include "gwordvar.h" - -#define setBit(Add) gBitVar[(Add)>>3] |= (1<<((Add)&0x07)) -#define clrBit(Add) gBitVar[(Add)>>3] &= ~(1<<((Add)&0x07)) - -#define BUFFER_SIZE 2000 -#define gBIT_SIZE 128 -#define MODBUS_SALVE_ADDRESS 0x01 - - -extern uint8_t gBitVar[(gBIT_SIZE+7)/8]; - -extern uint8_t rx_buffer[256]; -extern uint8_t tx_buffer[256]; -extern uint16_t rx_buff_len; - -extern int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc); -void ModBusWordWriteHook(uint16_t addr, uint16_t length); - -#endif - diff --git a/main/modbus/inc/gwordvar.h b/main/modbus/inc/gwordvar.h deleted file mode 100644 index 9ccfec1..0000000 --- a/main/modbus/inc/gwordvar.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __GWORDVAR_H -#define __GWORDVAR_H - -#include -#include "flow.h" - -#define FLOW_REG_ADDR 0 -#define DEPTH_REG_ADDR 12 -#define AC_CURRENT_REG_ADDR 24 -#define MOVE_REG_ADDR 27 -#define TILT_SENSER_ADDR 30 -#define RECORD_REG_ADDR 32 - -#define CAL_4_20MA_ADDR 384 -#define FLOW_CONFIG_ADDR (CAL_4_20MA_ADDR + (sizeof(cal_4_20ma_t) + 15) / 16 * 8) -#define DEPTH_CONFIG_ADDR (FLOW_CONFIG_ADDR + (sizeof(flow_config_t) + 15) / 16 * 8) - -#define AD_RAW_REG_ADDR 444 -#define LAST_PILE_ID_ADDR 509 -#define DEPTH_RESET_ADDR 510 -#define REBOOT_REW_ADDR 511 - -#define REG_GPS_MESSAGE (512 + 48) -#define REG_GPS_WRITE_DATA (REG_GPS_MESSAGE + sizeof(gps_message_t)) - -#define gWORD_SIZE 1024 -extern uint16_t gWordVar[gWORD_SIZE]; - -#endif \ No newline at end of file diff --git a/main/modbus/inc/uart0_modbus_slave.h b/main/modbus/inc/uart0_modbus_slave.h deleted file mode 100644 index d9293d1..0000000 --- a/main/modbus/inc/uart0_modbus_slave.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __UART0_MODBUS_SLAVE_H -#define __UART0_MODBUS_SLAVE_H - -#define UART_PORT_NUM (0) -#define BAUD_RATE (460800) -#define BUF_SIZE (256) -#define UART_READ_TOUT (50 / portTICK_PERIOD_MS) - -void uart0_modbus_slave_init(void); - -#endif \ No newline at end of file diff --git a/main/modbus/uart0_modbus_slave.c b/main/modbus/uart0_modbus_slave.c deleted file mode 100644 index 6d4c0fd..0000000 --- a/main/modbus/uart0_modbus_slave.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/uart.h" -#include "driver/gpio.h" -#include "esp_log.h" - -#include "uart0_modbus_slave.h" -#include "ModbusS.h" -#include "led.h" - -static const char *TAG = "UART0"; - -uint8_t txbuf[BUF_SIZE]; -uint8_t rxbuf[BUF_SIZE]; -extern uint16_t gWordVar[]; - -void uart0_init(void) -{ - const int uart_num = UART_PORT_NUM; - uart_config_t uart_config = { - .baud_rate = BAUD_RATE, - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, - .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, - .rx_flow_ctrl_thresh = 122, - .source_clk = UART_SCLK_APB, - }; - // Set UART log level - // esp_log_level_set(TAG, ESP_LOG_NONE); - - ESP_LOGI(TAG, "Start RS485 application test and configure UART."); - - // Install UART driver (we don't need an event queue here) - // In this example we don't even use a buffer for sending data. - ESP_ERROR_CHECK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE, 0, NULL, 0)); - - // Configure UART parameters - ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config)); - ESP_LOGI(TAG, "UART set pins, mode and install driver."); - // Set UART pins as per KConfig settings - //ESP_ERROR_CHECK(uart_set_pin(uart_num, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN));之前没解开注释 - //ESP_ERROR_CHECK(uart_set_pin(uart_num, 11, 13, 12, -1)); - // Set RS485 half duplex mode - ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX)); - // Set read timeout of UART TOUT feature - ESP_ERROR_CHECK(uart_set_rx_timeout(uart_num, UART_READ_TOUT)); -} - -void uart0_modbus_slave_task(void *arg) -{ - ESP_LOGI(TAG, "uart0_modbus_slave_task"); - - while (1) - { - int txlen = 0; - int len = uart_read_bytes(UART_PORT_NUM, rxbuf, BUF_SIZE, UART_READ_TOUT); - // xTaskGetTickCount(); - // ESP_LOGI("modbus_slave","-----------------------------rxlen:%d", len); - // for (int i = 0; i < len; i++) - // ESP_LOGI("modbus_slave","uart0 get: 0x%x", rxbuf[i]); - - if (len > 0) - { - txlen = ModbusSlaveProcess(txbuf, rxbuf, len, 1); - // if (txlen > 0) - // { - // LED_Toggle(LED1_GPIO_PIN); - // int uart_write_length = uart_write_bytes(UART_PORT_NUM, txbuf, txlen); - // ESP_LOGI("modbus_slave","-----------------------------txlen:%d uart_write_length:%d", txlen, uart_write_length); - // for (int i = 0; i < uart_write_length; i++) - // ESP_LOGI("modbus_slave","uart0 return: 0x%x", txbuf[i]); - // } - } - } -} - -void uart0_modbus_slave_init(void) -{ - uart0_init(); - xTaskCreate(uart0_modbus_slave_task, "uart0_modbus_slave_task", 4096, NULL, 10, NULL); -} diff --git a/main/peripheral/config/inc/config.h b/main/peripheral/config/inc/config.h deleted file mode 100644 index 3176f3f..0000000 --- a/main/peripheral/config/inc/config.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __CONFIG_H -#define __CONFIG_H - - -#define MAGIC 30627 -#define EE_CAL_4_20MA_ADDR 16 -#define EE_FLOW_CFG_ADDR (EE_CAL_4_20MA_ADDR + sizeof(default_cal_4_20ma)) -#define EE_DEPTH_CFG_ADDR (EE_FLOW_CFG_ADDR + sizeof(default_flow_cfg)) - - -void config_init(void); -void config_load(void); -void restore_default(void); -void save_cal_4_20ma(void); -void save_flow_cfg(void); -void save_depth_cfg(void); -void save_pile_id(void); - -#endif diff --git a/main/peripheral/config/inc/fram.h b/main/peripheral/config/inc/fram.h deleted file mode 100644 index 42f7883..0000000 --- a/main/peripheral/config/inc/fram.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __FRAM_H -#define __FRAM_H - -#include -#include "freertos/FreeRTOS.h" - -#define I2C_MASTER_SCL_IO 1 /*!< GPIO number used for I2C master clock */ -#define I2C_MASTER_SDA_IO 2 /*!< GPIO number used for I2C master data */ -#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ -#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ -#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ -#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ -#define I2C_MASTER_TIMEOUT_MS 1000 - -#define WRITE_BIT I2C_MASTER_WRITE -#define ACK_CHECK_EN 0x1 - -esp_err_t i2c_master_init(void); -int fram_write(uint16_t addr, void * buf,uint32_t len); -int fram_read(uint16_t addr,void * buf,uint32_t len); - -#endif - - diff --git a/main/peripheral/depth.c b/main/peripheral/depth.c deleted file mode 100644 index b998d75..0000000 --- a/main/peripheral/depth.c +++ /dev/null @@ -1,481 +0,0 @@ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "esp_system.h" -#include "esp_timer.h" -#include "driver/mcpwm.h" -#include "driver/gpio.h" -#include "esp_err.h" -#include "esp_log.h" -#include "esp_check.h" -#include "soc/rtc.h" - -#include "depth.h" -#include "rotary_encoder.h" -#include "gwordvar.h" -#include "flow.h" -#include "bl0939.h" -#include "utils.h" - -static const char *TAG = "depth"; - -extern uint16_t last_pile_id; -int32_t enc1_value; // 捕获中更新的值 -uint32_t enc1_update_time; -uint32_t _enc1_update_time; - -uint32_t enc2_update_time; -uint32_t _enc2_update_time; -int32_t enc2_value; - -extern rotary_encoder_t *encoder; - -depth_config_t *depth_config = (depth_config_t *)&gWordVar[DEPTH_CONFIG_ADDR]; -depth_t *depth_data = (depth_t *)&gWordVar[DEPTH_REG_ADDR]; -record_t *record = (record_t *)&gWordVar[RECORD_REG_ADDR]; - -rotary_encoder_t *encoder = NULL; // 编码器测量深度参数 - - -void pcnt_rotary_encoder_init(void) -{ - // Rotary encoder underlying device is represented by a PCNT unit in this example - uint32_t pcnt_unit = 0; - int pulse_pin; - int ctrl_pin; - if (depth_config->port) - { - pulse_pin = DEPTH_PIN_ENC_A; - ctrl_pin = DEPTH_PIN_ENC_B; - } - else - { - pulse_pin = DEPTH_PIN_PULSE; - ctrl_pin = DEPTH_PIN_CTRL; - } - // Create rotary encoder instance - rotary_encoder_config_t config = ROTARY_ENCODER_DEFAULT_CONFIG((rotary_encoder_dev_t)pcnt_unit, pulse_pin, ctrl_pin); - config.flags = depth_config->input_type; - ESP_ERROR_CHECK(rotary_encoder_new_ec11(&config, &encoder)); - // Filter out glitch (1us) - ESP_ERROR_CHECK(encoder->set_glitch_filter(encoder, 10)); - // Start encoder - ESP_ERROR_CHECK(encoder->start(encoder)); -} - - -/** - * @brief this is an ISR callback, we take action according to the captured edge - */ -static bool depth_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, - void *arg) -{ - - // 双边沿触发中断,只有一个边缘会更新值,所以只有在值发生变化时才更新时间 - int value = encoder->get_counter_value(encoder); - if (value != enc1_value) - { - enc1_value = value; - enc1_update_time = edata->cap_value; - } - return false; -} - -void capture_depth_init() -{ - int pulse_pin; - if (depth_config->port) - { - pulse_pin = DEPTH_PIN_ENC_A; - } - else - { - pulse_pin = DEPTH_PIN_PULSE; - } - ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, pulse_pin)); - // enable pull down CAP0, to reduce noise - ESP_ERROR_CHECK(gpio_pullup_en(pulse_pin)); - // enable both edge capture on CAP0 - mcpwm_capture_config_t conf = { - .cap_edge = MCPWM_NEG_EDGE, - .cap_prescale = 1, - .capture_cb = depth_isr_handler, // 绑定深度中断处理函数 - .user_data = NULL - }; - if (depth_config->input_type > 1) - { - conf.cap_edge = MCPWM_BOTH_EDGE; - } - ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, &conf)); - ESP_LOGI(TAG, "capture_depth_init"); -} - -void depth_init(void) -{ - // if (depth_config->input_type == 1) - // { // 电压型 方向+脉冲信号 使用比较器通道,IO口中断方式采集 - - // // GPIO_InitTypeDef GPIO_InitStruct = {0}; - // // /*Configure GPIO pin : PtPin */ - // // GPIO_InitStruct.Pin = ROLLER_DIR_Pin; - // // GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - // // GPIO_InitStruct.Pull = GPIO_PULLUP; - // // HAL_GPIO_Init(ROLLER_GPIO_Port, &GPIO_InitStruct); - - // // /*Configure GPIO pin : PtPin */ - // // GPIO_InitStruct.Pin = ROLLER_CLK_Pin; - // // GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; - // // GPIO_InitStruct.Pull = GPIO_PULLUP; - // // HAL_GPIO_Init(ROLLER_GPIO_Port, &GPIO_InitStruct); - // } - // else if (depth_config->input_type == 2) - // { // 电压型 正交编码器 使用比较器通道,TIM1编码器通道采集 - // MX_TIM1_Init(); - // pcnt_rotary_encoder_init(); // 编码器初始化 - // capture_depth_init(); - // HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL); - // } - // else if (depth_config->input_type == 3) - // { // 开漏输出 正交编码器 使用光耦输入通道,TIM3编码器通道采集 - // // MX_TIM3_Init(); - // // HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); - // } - depth_data->depth_offset = -depth_config->depth_offset; - depth_data->pile_work_state_and_direction = (PILE_STATE_STOP | PILE_DIR_NONE); // 默认不工作 -} - -enum -{ - REST = -1, - STOP = 0, - DOWN = 1, - UP = 2, -}; - -int last_enc_value = 0; -uint32_t _enc_update_time; -uint32_t enc_update_time; -int last_sample_depth = 0; -int last_flow[2] = {0}; -int16_t prev_depth = 0; -uint32_t prev_update_time = 0; -int16_t target_sample_depth = 0; - -extern bool is_connected; -// extern uint16_t spp_handle_table[IDX_NB]; -extern uint16_t spp_conn_id; -extern flow_t *pflow; - - -void calculate_depth_speed(int speed_enc_value) -{ - static int speed_last_enc_value = -1; - static int64_t speed_last_time = -1; - int64_t speed_time = esp_timer_get_time(); - - if (speed_last_enc_value == -1) // 第一次,记录值,并不计算 - { - goto exit; - } - - depth_data->speed = (speed_enc_value - speed_last_enc_value) * depth_config->N / depth_config->M * 600000ll / (speed_time - speed_last_time); - // ESP_LOGI(TAG, "speed:%d", depth_data->speed); -exit: - speed_last_enc_value = speed_enc_value; - speed_last_time = speed_time; -} - - - - -/** - * _enc1_update_time 编码器1上一次更新时间 - * enc1_update_time 编码器1当前更新时间 - * time_diff 两次编码器更新时间的绝对差值 - * depth_config 预设好的深度数据 - * enc1_value 编码器1值,在深度中断中获得 - * prev_depth 上一次的深度 -*/ -void depth_task(void *arg) -{ - ESP_LOGI(TAG, "depth_task start\n"); - - int time_diff = 0; - int speed_calc_count = 0; - int enc_value = 0; - int64_t work_start_time = 0; - uint16_t last_work_state = 0; - - depth_data->depth_offset = -depth_config->depth_offset; - depth_data->pile_work_state_and_direction = 0x0300; - last_work_state = depth_data->pile_work_state_and_direction; - record->pile_id = ++last_pile_id; - gWordVar[LAST_PILE_ID_ADDR] = last_pile_id; - - while (1) - { - if (_enc1_update_time != enc1_update_time) /* 深度数据更新 */ - { - enc_update_time = enc1_update_time; - enc_value = enc1_value; - time_diff = abs_sub_uint32(enc_update_time, _enc1_update_time); - _enc1_update_time = enc_update_time; - } - //ESP_LOGI(TAG, "time_diff:%d", time_diff); - - if (time_diff != 0) - { - // ESP_LOGI(TAG, "time_diff = %d\n",time_diff); - int16_t depth = enc_value * depth_config->N / depth_config->M; // 1mm - depth_data->depth = depth - depth_data->depth_offset; - - /*深度补偿修正*/ - if (depth_data->depth > depth_config->max_depth) - { - // ESP_LOGI(TAG, "depth_data->depth > depth_config->max_depth\n"); - depth_data->depth_offset = depth - depth_config->max_depth; - depth_data->depth = depth_config->max_depth; - } - else if (depth_data->depth < depth_config->min_depth) - { - // ESP_LOGI(TAG, "depth_data->depth < depth_config->min_depth\n"); - depth_data->depth_offset = depth - depth_config->min_depth; - depth_data->depth = depth_config->min_depth; - } - - /*更新记录值*/ - if (depth_data->depth > record->max_depth) - { - // ESP_LOGI(TAG, "depth_data->depth > record->max_depth\n"); - record->max_depth = depth_data->depth; - // send_to_bt1.max_depth = depth_data->depth; - } - - // ESP_LOGI(TAG, "depth_data->depth:0x%x", (unsigned int)depth_data->depth); - - uint16_t pile_work_state = (depth_data->pile_work_state_and_direction & 0xff00); - if (pile_work_state == PILE_STATE_WORK) - { - // ESP_LOGI(TAG, "pile_work_state == PILE_STATE_WORK\n"); - /*如果机器从停止状态->工作状态,则重新记录工作开始时间*/ - if(last_work_state == PILE_STATE_STOP){ - work_start_time = esp_timer_get_time(); - depth_data->one_pile_work_time = 0; - } - int64_t current_work_time = esp_timer_get_time(); - if(work_start_time != 0){ - depth_data->one_pile_work_time = (uint16_t)((current_work_time - work_start_time)/1000000); // s - // ESP_LOGI(TAG, "time : %ud", (int)depth_data->one_pile_work_time); - } - - /*下钻,深度增加 计算采样深度流量*/ - if (enc_value > last_enc_value) - { - // ESP_LOGI(TAG, "enc_value > last_enc_value\n"); - uint8_t pile_work_dir = (depth_data->pile_work_state_and_direction & 0xff); - if(pile_work_dir != PILE_DIR_DOWN) - { - // 方向改变,更新目标采样深度 - depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_DOWN); - target_sample_depth = (depth_data->depth / depth_config->sample_depth) * depth_config->sample_depth; - - // 小于半个采样长度的合并到下一个采样点 - if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2) - { - target_sample_depth += depth_config->sample_depth; - } - } - - // 到达或超过目标采样点 - if (depth_data->depth >= target_sample_depth) - { - // 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点 - // 当使用10线编码器时每个脉冲深度达6.25cm,当采样间隔为10cm时抖动值太大 - if ((prev_depth - depth_data->depth) != 0) - { - int i; - //uint32_t time = (target_sample_depth - prev_depth) * (enc_update_time - prev_update_time) / (depth_data->depth - prev_depth) + prev_update_time; - for (i = 0; i < 2; i++) - { - // int total_flow = get_total_flow_by_time(i, time); - int total_flow = get_total_flow_by_time(i, pflow[i].update_time); - int flow = total_flow - depth_data->last_total_flow[i]; - if (flow < 0) - { - flow = 0; - } - depth_data->depth_flow[i] = flow; /* 采样深度对应的流量 */ - depth_data->last_total_flow[i] = total_flow; - } - depth_data->sample_count++; - target_sample_depth += depth_config->sample_depth; - add_recod_item(); - } - } - } - /*上钻,深度减少*/ - else if (enc_value < last_enc_value) - { - // ESP_LOGI(TAG, "enc_value < last_enc_value\n"); - uint8_t pile_work_dir = (depth_data->pile_work_state_and_direction & 0xff); - if (pile_work_dir != PILE_DIR_UP) - { - // 方向改变 - depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_UP); - target_sample_depth = (depth_data->depth / depth_config->sample_depth - 1) * depth_config->sample_depth; - - if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2) - { - // 小于半个采样长度的合并到下一个采样点 - target_sample_depth -= depth_config->sample_depth; - } - } - if (depth_data->depth <= target_sample_depth) - { - // 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点 - // 当使用10线编码器时每个脉冲深度达7.6cm,当采样间隔为10cm时抖动值太大 - if ((prev_depth - depth_data->depth) != 0) - { - int i; - //uint32_t time = (prev_depth - target_sample_depth) * (enc_update_time - prev_update_time) / (prev_depth - depth_data->depth) + prev_update_time; - for (i = 0; i < 2; i++) - { - // int total_flow = get_total_flow_by_time(i, time); - int total_flow = get_total_flow_by_time(i, pflow[i].update_time); - int flow = total_flow - depth_data->last_total_flow[i]; - if (flow < 0) - { - flow = 0; - } - depth_data->depth_flow[i] = flow; - depth_data->last_total_flow[i] = total_flow; - } - depth_data->sample_count++; - add_recod_item(); - target_sample_depth -= depth_config->sample_depth; - } - } - } - else - { - depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_NONE); - } - - if (depth_data->depth < depth_config->inc_pile_depth) // 小于指定深度时才允许行走清零 - { - if (pMoveCtx->pile_inc_req == 1) - { - pMoveCtx->pile_inc_req = 0; - reset_depth(); - } - } - else - { - if (pMoveCtx->pile_inc_req == 1) - { - pMoveCtx->pile_inc_req = 0; - } - } - } - else if((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_PAUSE) - { - - } - else if((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_STOP) - { - work_start_time = 0; - } - last_work_state = pile_work_state; - prev_depth = depth_data->depth; - prev_update_time = enc_update_time; - last_enc_value = enc_value; - } - - vTaskDelay(pdMS_TO_TICKS(100)); - - // 500ms计算一次速度 - if (++speed_calc_count >= 5) - { - calculate_depth_speed(enc1_value); - speed_calc_count = 0; - } - } -} - - -void add_recod_item(void) -{ - // 每10cm计算一次 - record->count = depth_data->sample_count; - ESP_LOGI(TAG, "add_recod_item:id:%d count:%d", record->pile_id, record->count); - memmove(&record->item[1], &record->item[0], sizeof(record->item[0]) * 9); - record->item[0].flow[0] = depth_data->depth_flow[0]; - record->item[0].flow[1] = depth_data->depth_flow[1]; - record->item[0].total_flow[0] = depth_data->last_total_flow[0]; - record->item[0].total_flow[1] = depth_data->last_total_flow[1]; - - if (depth_config->move_current_channel == 2) // 1 - { - record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR]; - record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 1]; - } - else if (depth_config->move_current_channel == 1) - { - record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR]; - record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 2]; - } - else - { - record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR + 1]; - record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 2]; - } - - record->item[0].tilt_x = (short)gWordVar[TILT_SENSER_ADDR]; - record->item[0].tilt_y = (short)gWordVar[TILT_SENSER_ADDR + 1]; - - record->item[0].speed = depth_data->speed; // 每500ms计算一次 - record->item[0].depth = depth_data->depth; // 每10ms计算一次 -} - -extern void save_pile_id(void); -void reset_depth(void) -{ - // uint16_t pile_id; - last_sample_depth = 0; - last_flow[0] = 0; - last_flow[1] = 0; - prev_depth = 0; - prev_update_time = 0; - target_sample_depth = 0; - flow_zero(); - if (record->count > 0) - { - record->count = 0; - memset(record->item, 0, sizeof(record->item)); - } - memset(depth_data, 0, sizeof(*depth_data)); - if (record->max_depth >= depth_config->min_valid_depth) // 上一个桩有一定深度数据 - { - save_pile_id(); - last_pile_id++; - gWordVar[LAST_PILE_ID_ADDR] = last_pile_id; - } - memset(record, 0, sizeof(*record)); - record->pile_id = last_pile_id; - // ec11_pcnt_clear(0); - depth_data->depth_offset = -depth_config->depth_offset; - depth_data->depth = depth_config->depth_offset; - enc1_value = 0; - enc1_update_time = 0; - depth_data->pile_work_state_and_direction = PILE_STATE_STOP | PILE_DIR_NONE; // 默认不工作 -} - -void DEPTH_init(void) -{ - pcnt_rotary_encoder_init(); - capture_depth_init(); - - xTaskCreate(depth_task, "depth_task", 4096, NULL, 10, NULL); -} diff --git a/main/peripheral/depth_.c b/main/peripheral/depth_.c deleted file mode 100644 index 88e5856..0000000 --- a/main/peripheral/depth_.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "esp_err.h" -#include "esp_timer.h" -#include "stdlib.h" -#include "config.h" -#include "utils.h" -#include "ads1220.h" -#include "fram.h" - -#include "rotary_encoder.h" -#include "esp_log.h" -#include "esp_check.h" -#include "soc/rtc.h" -#include "driver/mcpwm.h" -// #include "driver/mcpwm_prelude.h" -// #include "bt_server.h" -// #include "../ble_gatts_server.h" - -#include "esp_system.h" -#include "driver/uart.h" -#include "string.h" -#include "driver/gpio.h" - -#include -#include - -static const char *TAG = "depth"; - -typedef struct -{ - uint32_t capture_signal; - mcpwm_capture_signal_t sel_cap_signal; -} capture; - -typedef struct capture_event -{ - int ch; - uint32_t val; -} capture_event_t; - -// #define DEPTH_PIN_CLK GPIO_NUM_36 // 捕获GPIO端口 -// #define GPIO_PCNT_PIN_1 36 // Set GPIO 18 as phaseA/C1 -// #define GPIO_PCNT_PIN_2 35 // Set GPIO 19 as phaseB/C2 -// #define DEPTH_PIN_PULSE 36 //深度脉冲GPIO端口 -// #define DEPTH_PIN_CTRL 35 //深度控制GPIO端口 - -#define FLOW_SYNC_PIN 7 // 捕获GPIO端口 SPI2_nIRQ - -#define DEPTH_PIN_PULSE 39 // 深度脉冲GPIO端口 TIM15_CH1 -#define DEPTH_PIN_CTRL 38 // 深度控制GPIO端口 TIM15_CH2 -#define DEPTH_PIN_ENC_A 42 // 深度脉冲GPIO端口 TIM3_CH1 -#define DEPTH_PIN_ENC_B 41 // 深度控制GPIO端口 TIM3_CH2 -#define SEND_DATA_TEST 0 - -#define PILE_STATE_STOP 0x0100 -#define PILE_STATE_PAUSE 0x0200 -#define PILE_STATE_WORK 0x0300 - -#define PILE_DIR_NONE 0x01 -#define PILE_DIR_UP 0x02 -#define PILE_DIR_DOWN 0x03 - - -rotary_encoder_t *encoder_ = NULL; // 编码器测量深度参数 - - - -void pcnt_rotary_encoder_init_(void) -{ - // Rotary encoder underlying device is represented by a PCNT unit in this example - uint32_t pcnt_unit = 0; - int pulse_pin; - int ctrl_pin; - - pulse_pin = DEPTH_PIN_ENC_A; - ctrl_pin = DEPTH_PIN_ENC_B; - - // Create rotary encoder instance - rotary_encoder_config_t config = ROTARY_ENCODER_DEFAULT_CONFIG((rotary_encoder_dev_t)pcnt_unit, pulse_pin, ctrl_pin); - config.flags = 0; - ESP_ERROR_CHECK(rotary_encoder_new_ec11(&config, &encoder_)); - // Filter out glitch (1us) - ESP_ERROR_CHECK(encoder_->set_glitch_filter(encoder_, 10)); - // Start encoder - ESP_ERROR_CHECK(encoder_->start(encoder_)); -} diff --git a/main/peripheral/flow/ads1220.c b/main/peripheral/flow/ads1220.c deleted file mode 100644 index 3eb1d45..0000000 --- a/main/peripheral/flow/ads1220.c +++ /dev/null @@ -1,233 +0,0 @@ -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "driver/spi_master.h" -#include "driver/mcpwm.h" -#include "esp_log.h" - -#include "ads1220.h" -#include "led.h" - -#define TAG "ADS1220" - -static spi_device_handle_t spi2; -QueueHandle_t drdy_queue = NULL; -int ads1220_ch_now = 0; -uint32_t ads1220_update_time[4]; -const uint8_t ch_cmd[4] = {0x0C, 0xA1, 0x0C, 0xB1}; - -static void SPI2_Init(void) -{ - esp_err_t ret; - - spi_bus_config_t buscfg2 = { - .miso_io_num = SPI2_PIN_NUM_MISO, - .mosi_io_num = SPI2_PIN_NUM_MOSI, - .sclk_io_num = SPI2_PIN_NUM_CLK, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 8}; - - spi_device_interface_config_t devcfg2 = { - .clock_speed_hz = 1 * 1000 * 1000, // Clock out at 1 MHz - .mode = 0, // SPI mode 0 - .cs_ena_posttrans = 2, // Keep the CS low 2 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than SPI CLK - .spics_io_num = SPI2_PIN_NUM_CS, // CS pin - .queue_size = 1, // We want to be able to queue 7 transactions at a time - // .address_bits = 8, - // .pre_cb = lcd_spi_pre_transfer_callback, // Specify pre-transfer callback to handle D/C line - // .command_bits = 8, - }; - // Initialize the SPI bus - ret = spi_bus_initialize(ADS1220_HOST, &buscfg2, SPI_DMA_CH_AUTO); - ESP_ERROR_CHECK(ret); - // Attach the ADS1220 to the SPI bus - ret = spi_bus_add_device(ADS1220_HOST, &devcfg2, &spi2); - ESP_ERROR_CHECK(ret); -} - - -static void IRAM_ATTR ads1220_done_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, - const cap_event_data_t *edata, void *arg) -{ - ads1220_update_time[ads1220_ch_now] = edata->cap_value; - xQueueSendFromISR(drdy_queue, &ads1220_update_time[ads1220_ch_now], NULL); -} - -static void drdy_capture_init(void) -{ - drdy_queue = xQueueCreate(1, sizeof(uint32_t)); - - ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_1, ADS1220_DRDY_IO)); - // enable pull down CAP0, to reduce noise - ESP_ERROR_CHECK(gpio_pullup_en(ADS1220_DRDY_IO)); - // enable both edge capture on CAP0 - mcpwm_capture_config_t conf = { - .cap_edge = MCPWM_NEG_EDGE, - .cap_prescale = 1, - .capture_cb = ads1220_done_handler, // 绑定深度中断处理函数 - .user_data = NULL}; - ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, &conf)); -} - - -uint8_t ADS1220_ReadReg(uint8_t reg) -{ - uint8_t Val; - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); // Zero out the transaction - t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; - t.tx_data[0] = ADS1220_CMD_RREG | ((reg & 0x03) << 2); - t.length = 2 * 8; - ret = spi_device_polling_transmit(spi2, &t); // Transmit! - assert(ret == ESP_OK); - Val = t.rx_data[1]; - return Val; -} - - -int32_t ADS1220_ReadData(void) -{ - int32_t Val = 0; - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); // Zero out the transaction - t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; - t.tx_data[0] = ADS1220_CMD_RDATA; - t.length = 4 * 8; // Command is 24 bits - ret = spi_device_polling_transmit(spi2, &t); // Transmit! - assert(ret == ESP_OK); - Val = (t.rx_data[1] << 16) | (t.rx_data[2] << 8) | t.rx_data[3]; - if (Val & 0x800000) - { - Val |= 0xFF000000; - } - return Val; -} - -void ADS1220_WriteReg(uint8_t reg, uint8_t dat) -{ - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); // Zero out the transaction - t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; - // t.flags = SPI_TRANS_USE_TXDATA; - t.tx_data[0] = ADS1220_CMD_WREG | ((reg & 0x03) << 2); - t.tx_data[1] = dat; - t.length = 2 * 8; // Command is 16 bits - ret = spi_device_polling_transmit(spi2, &t); // Transmit! - assert(ret == ESP_OK); -} - -void ADS1220_WriteCommand(uint8_t cmd) -{ - - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); // Zero out the transaction - t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; - t.length = 8 * 2; // Command is 8 bits - t.tx_data[0] = cmd; // The data is the cmd itself - ret = spi_device_polling_transmit(spi2, &t); // Transmit! - assert(ret == ESP_OK); - // // ADS1220_CS=0; - // ADS1220_nCS_LOW(); - // ADS1220_ReadWriteByte(cmd); - // // ADS1220_CS=1; - // ADS1220_nCS_HIGH(); -} - -void ADS1220_PowerDown(void) -{ - ADS1220_WriteCommand(ADS1220_CMD_POWERDOWN); -} - -void ADS1220_StartConv(uint8_t channal) -{ - /* - u8 val ; - val = ADS1220_ReadReg(ADS1220_REG0); - - ADS1220.CurrentCH = ADS1220_Channal1; - val = val & 0x0f | Channal1; - ADS1220_WriteReg(ADS1220_REG0, val ); - */ - ADS1220_WriteCommand(ADS1220_CMD_START); -} - -void ADS1220_Reset(void) -{ - ADS1220_WriteCommand(ADS1220_CMD_RESET); -} - -void ADS1220_PGASet(uint8_t gain) -{ - uint8_t val; - val = ADS1220_ReadReg(ADS1220_REG0); - val = (val & 0xF1) | gain; - - ADS1220_WriteReg(ADS1220_REG0, val); - // val = ADS1220_ReadReg(ADS1220_REG0); - ADS1220_StartConv(ADS1220_Channal1); -} - -void ADS1220_Config(void) -{ - static uint8_t read[4]; - - ADS1220_WriteCommand(ADS1220_CMD_RESET); - vTaskDelay(10); - - ADS1220_WriteReg(ADS1220_REG0, 0xa0); - ADS1220_WriteReg(ADS1220_REG1, 0x20); - ADS1220_WriteReg(ADS1220_REG2, 0x20); - ADS1220_WriteReg(ADS1220_REG3, 0x00); - - read[0] = ADS1220_ReadReg(ADS1220_REG0); - read[1] = ADS1220_ReadReg(ADS1220_REG1); - read[2] = ADS1220_ReadReg(ADS1220_REG2); - read[3] = ADS1220_ReadReg(ADS1220_REG3); - ESP_LOGI(TAG, "ads1220 reg %02x %02x %02x %02x \n", read[0], read[1], read[2], read[3]); -} - -void ads1220_init(void) -{ - SPI2_Init(); - drdy_capture_init(); - ADS1220_Config(); - - ads1220_ch_now = 0; - ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ads1220_ch_now]); - ADS1220_WriteCommand(ADS1220_CMD_START); -} - - -int ads1220_read_flow(int32_t *ad_raw_p, int *ad_ch_p, uint32_t *ad_update_time_p) -{ - uint32_t io_num; - if (pdFALSE == xQueueReceive(drdy_queue, &io_num, pdMS_TO_TICKS(100))) - { - ESP_LOGI(TAG, "ads1220 wait drdy_queue timeout!"); - ads1220_init(); // 但是请注意,init会让两通道都初始化了 - *ad_ch_p = ads1220_ch_now; - return -1; - } - - int ad_ch = ads1220_ch_now; - int32_t ad_raw = ADS1220_ReadData(); - - ads1220_ch_now++; - if (ads1220_ch_now >= sizeof(ch_cmd)) - { - ads1220_ch_now = 0; - } - ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ads1220_ch_now]); - ADS1220_WriteCommand(ADS1220_CMD_START); - - *ad_raw_p = ad_raw; - *ad_ch_p = ad_ch; - *ad_update_time_p = ads1220_update_time[ad_ch]; - return 0; -} diff --git a/main/peripheral/flow/flow.c b/main/peripheral/flow/flow.c deleted file mode 100644 index 4087a65..0000000 --- a/main/peripheral/flow/flow.c +++ /dev/null @@ -1,216 +0,0 @@ -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "esp_err.h" -#include "esp_log.h" -// #include "soc/rtc.h" - -#include "flow.h" -#include "ads1220.h" -#include "input_type2.h" -#include "led.h" -#include "gwordvar.h" -#include "utils.h" - -const static char *TAG = "flow"; - -cal_4_20ma_t *cal_4_20ma = (cal_4_20ma_t *)&gWordVar[CAL_4_20MA_ADDR]; -flow_config_t *flow_config = (flow_config_t *)&gWordVar[FLOW_CONFIG_ADDR]; -flow_t *pflow = (flow_t *)&gWordVar[FLOW_REG_ADDR]; - -extern uint32_t rtc_clk_apb_freq; -static uint32_t volatile last_ccr[2]; -static int flow_rem[2]; -static uint8_t timeout[2]; - - - -// 获取给定时刻累计流量 -int get_total_flow_by_time(int ch, uint32_t time) -{ - int delta_t; - int delta_flow; - if (ch > 1) - { - return 0; - } - delta_t = abs_sub_uint32(time, pflow[ch].update_time) / (APB_CLK_FREQ / 1000000); // 换算成us - delta_flow = pflow[ch].flow * delta_t / 60 / 100; - return pflow[ch].total_flow + delta_flow; -} - -void zero_totalflow(int ch) -{ - if (ch > 1) - { - return; - } - pflow[ch].total_flow = 0; - flow_rem[ch] = 0; -} - -void flow_zero(void) -{ - memset(pflow, 0, sizeof(flow_t) * 2); - for (int i = 0; i < 2; i++) - { - last_ccr[i] = 0; - flow_rem[i] = 0; - timeout[i] = 0; - - t15_ccr[i] = 0; - t15_ccr_times[i] = 0; - } -} - -void flow_input_type1_calculate(void) -{ - int ret = 0; - int32_t ad_raw_data = 0; - int ad_ch = 0, flow_ch = 0; - int time_diff = 0; - uint32_t ad_update_time = 0; - - if (ads1220_read_flow(&ad_raw_data, &ad_ch, &ad_update_time) == 0) - { - ad_raw_data = ad_raw_data / 128; - gWordVar[AD_RAW_REG_ADDR + ad_ch] = ad_raw_data / 2; - - if (ad_ch != 1 && ad_ch != 3) // 1, 3命令所测的电流是我们想要的 - { - return; - } - - LED_Toggle(LED2_GPIO_PIN); - - flow_ch = ad_ch / 2; - if (pflow[flow_ch].update_time == 0) // 第一次测得数据,不计算 - { - goto exit; - } - - // 瞬时流量换算 - ad_flow_cal_t *cal = flow_config->ad_cal; - pflow[flow_ch].flow_ = scale(ad_raw_data, cal_4_20ma->ch[flow_ch].ad_4ma, cal_4_20ma->ch[flow_ch].ad_20ma, cal[flow_ch].flow_min, cal[flow_ch].flow_max); - if (pflow[flow_ch].flow_ < flow_config->min_flow[flow_ch]) // 小流量切除 - { - pflow[flow_ch].flow = 0; - } - else - { - pflow[flow_ch].flow = pflow[flow_ch].flow_; - } - - // 累计流量计算 - int t_flow; // time_diff时间段总流量 - time_diff = abs_sub_uint32(ad_update_time, pflow[flow_ch].update_time); - // 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为1us - // flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s - // t_diff = time_diff / 1000 将时间差换算成秒 - // t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL - // 取出0.01L的整数部分累加,余数部分和下次值累加 - // t_flow = pflow[i].flow * 1000 * time_diff / 1000000 / 60; - int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000); - // if (ad_ch == 3) ESP_LOGI(TAG, "time_diff_us:%d", time_diff_us); - t_flow = pflow[flow_ch].flow * (long long)time_diff_us / 60 / 100; //(5 * 60); - flow_rem[flow_ch] += t_flow; - int sub_flow = flow_rem[flow_ch] / 10000; - pflow[flow_ch].total_flow += sub_flow; - flow_rem[flow_ch] = flow_rem[flow_ch] - sub_flow * 10000; -exit: - pflow[flow_ch].update_time = ad_update_time; - // ESP_LOGI(TAG, "flow_ch %d: %5d %5ld, %5d %5ld", flow_ch, pflow[0].flow, pflow[0].total_flow, pflow[1].flow, pflow[1].total_flow); - return; - } -} - -void flow_input_type2_calculate(void) -{ - vTaskDelay(pdMS_TO_TICKS(100)); - int ch; - - for (ch = 0; ch < 2; ch++) - { - if (t15_ccr_times[ch] > 0) - { - int ccr_times; - int time_diff; - uint32_t ccr; - // __disable_irq(); - ccr_times = t15_ccr_times[ch]; - t15_ccr_times[ch] = 0; - ccr = t15_ccr[ch]; - ccr = ccr / (rtc_clk_apb_freq / 1000000); - // __enable_irq(); - time_diff = ccr - last_ccr[ch]; - // ESP_LOGI(TAG, "(type2) t15_ccr_times[%d]: %lu %d time_diff: %d", ch, ccr, ccr_times, time_diff); - // ESP_LOGI(TAG,"rtc_clk_apb_freq : %lu\n", rtc_clk_apb_freq); - if (time_diff != 0) - { - int t_flow; - - pflow[ch].flow_ = flow_config->pulse_coef[ch] * 600 * (int64_t)ccr_times / time_diff; - if (pflow[ch].flow_ < flow_config->min_flow[ch]) - { - pflow[ch].flow = 0; - } - else - { - pflow[ch].flow = pflow[ch].flow_; - } - t_flow = pflow[ch].flow * time_diff / (5 * 60); - flow_rem[ch] += t_flow; - pflow[ch].total_flow += flow_rem[ch] / 10000; - flow_rem[ch] = flow_rem[ch] % 10000; - pflow[ch].update_time = ccr; - last_ccr[ch] = ccr; - timeout[ch] = 0; - // ESP_LOGI(TAG, "(type2) pflow[%d].flow: %u", ch ,pflow[ch].flow); - } - } - else if (++timeout[ch] > 5) - { - timeout[ch] = 0; - pflow[ch].flow = 0; - pflow[ch].flow_ = 0; - } - } -} - - -void flow_task(void *arg) -{ - flow_config->input_type = 1; - while (1) - { - switch (flow_config->input_type) - { - case 1: - { - flow_input_type1_calculate(); - break; - } - case 2: - { - flow_input_type2_calculate(); - break; - } - default: - ESP_LOGI(TAG, "Flow input type not illegality! Can not measure flow."); - vTaskDelay(pdMS_TO_TICKS(100)); - break; - } - } -} - - -void flow_init(void) -{ - ads1220_init(); - flow_input_type2_init(); - led_init(); - - xTaskCreate(flow_task, "flow_task", 4096, NULL, 10, NULL); -} diff --git a/main/peripheral/flow/inc/ads1220.h b/main/peripheral/flow/inc/ads1220.h deleted file mode 100644 index 0796b98..0000000 --- a/main/peripheral/flow/inc/ads1220.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __ADS1220_H -#define __ADS1220_H - -#include -#include "freertos/queue.h" - -#define ADS1220_DRDY_IO 7 -#define SPI2_PIN_NUM_MISO 6 -#define SPI2_PIN_NUM_MOSI 5 -#define SPI2_PIN_NUM_CLK 16 -#define SPI2_PIN_NUM_CS 15 -#define ADS1220_HOST SPI2_HOST -#define PARALLEL_LINES 16 - - -#define ADS1220_nCS_HIGH() gpio_set_level(GPIO_NUM_38, 1) -#define ADS1220_nCS_LOW() gpio_set_level(GPIO_NUM_38, 0) - -#define ADS1220_CMD_WREG 0x40 -#define ADS1220_CMD_RREG 0x20 -#define ADS1220_CMD_RESET 0x06 -#define ADS1220_CMD_START 0x08 -#define ADS1220_CMD_POWERDOWN 0x02 -#define ADS1220_CMD_RDATA 0x10 - -#define Channal1 0x00 -#define Channal2 0x10 -#define Channal3 0x20 -#define Channal4 0x30 - -#define ADS1220_REG0 0x00 -#define ADS1220_REG1 0x01 -#define ADS1220_REG2 0x02 -#define ADS1220_REG3 0x03 - -#define PGAGain1 0x00 -#define PGAGain2 0x02 -#define PGAGain4 0x04 -#define PGAGain8 0x06 -#define PGAGain16 0x08 -#define PGAGain32 0x0A -#define PGAGain64 0x0C -#define PGAGain128 0x0E - -#define ADS1220_Standby 0 -#define ADS1220_ConvStart 1 -#define ADS1220_ConvFinish 2 - -#define ADS1220_Channal1 0 -#define ADS1220_Channal2 1 -#define ADS1220_Channal3 2 -#define ADS1220_Channal4 3 - -int ADS1220_get_rate(void); -void ADS1220_set_rate(int i); -void ADS1220_Config(void); -void ADS1220_StartConv(uint8_t channal); -void ADS1220_Reset(void); -void ADS1220_PowerDown(void); -void ADS1220_PGASet(uint8_t gain); -void ADS1220_WriteCommand(uint8_t cmd); -int32_t ADS1220_ReadData(void); -void ADS1220_WriteReg(uint8_t reg,uint8_t dat); -uint8_t ADS1220_ReadReg(uint8_t reg); -uint8_t ADS1220_ReadWriteByte(uint8_t dat); - -void ads1220_init(void); -int ads1220_read_flow(int32_t *ad_raw_p, int *ad_ch_p, uint32_t *ad_update_time_p); - -#endif diff --git a/main/peripheral/flow/inc/flow.h b/main/peripheral/flow/inc/flow.h deleted file mode 100644 index 38c36ff..0000000 --- a/main/peripheral/flow/inc/flow.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __FLOW_H -#define __FLOW_H - -#include - -typedef struct -{ - uint16_t magic; - struct _ch - { - uint16_t ad_4ma; - uint16_t ad_20ma; - } ch[2]; -} cal_4_20ma_t; - -typedef struct -{ - int16_t flow_min; - int16_t flow_max; -} ad_flow_cal_t; //存储ad转换的最大流量和最小流量 - -typedef struct -{ - uint16_t magic; - uint16_t input_type; // 1: 4~20ma 2: 0~3.6K - int16_t min_flow[2]; // 小流量切除 - ad_flow_cal_t ad_cal[2]; - uint16_t pulse_coef[2]; - uint16_t rsv[6]; -} flow_config_t; - -typedef struct -{ - int16_t flow_; - int16_t flow; - int32_t total_flow; - uint32_t update_time; -} flow_t; - - -extern cal_4_20ma_t *cal_4_20ma; -extern flow_config_t *flow_config; -extern flow_t *pflow; - -void flow_init(void); -void zero_totalflow(int ch); -void flow_zero(void); -int get_total_flow_by_time(int ch, uint32_t time); - - -#endif \ No newline at end of file diff --git a/main/peripheral/flow/inc/input_type2.h b/main/peripheral/flow/inc/input_type2.h deleted file mode 100644 index 90a8186..0000000 --- a/main/peripheral/flow/inc/input_type2.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __INPUT_TYPE2_H -#define __INPUT_TYPE2_H - -#include - -#define FLOW1_PIN_ECHO GPIO_NUM_39 -#define FLOW2_PIN_ECHO GPIO_NUM_38 - -extern uint32_t volatile t15_ccr[2]; -extern uint16_t volatile t15_ccr_times[2]; - -void flow_input_type2_init(void); - -#endif \ No newline at end of file diff --git a/main/peripheral/flow/input_type2.c b/main/peripheral/flow/input_type2.c deleted file mode 100644 index 47ecc82..0000000 --- a/main/peripheral/flow/input_type2.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "freertos/FreeRTOS.h" -#include "driver/mcpwm.h" -#include "driver/gpio.h" -#include "esp_err.h" -#include "esp_log.h" - -#include "input_type2.h" - -const static char *TAG = "flow_input_type2"; - - -uint32_t volatile t15_ccr[2]; -uint16_t volatile t15_ccr_times[2]; - - -static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, - void *arg) -{ - // calculate the interval in the ISR, - // so that the interval will be always correct even when cap_queue is not handled in time and overflow. - BaseType_t high_task_wakeup = pdFALSE; - - t15_ccr[0] = edata->cap_value; - t15_ccr_times[0]++; - return high_task_wakeup == pdFALSE; -} - -void capture_flow1_init() -{ - ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO)); - // enable pull down CAP0, to reduce noise - ESP_ERROR_CHECK(gpio_pulldown_en(FLOW1_PIN_ECHO)); - // enable both edge capture on CAP0 - mcpwm_capture_config_t conf = { - .cap_edge = MCPWM_NEG_EDGE, - .cap_prescale = 1, - .capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数 - .user_data = NULL}; - ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf)); - ESP_LOGI(TAG, "capture_flow_init"); -} - -static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, - void *arg) -{ - // calculate the interval in the ISR, - // so that the interval will be always correct even when cap_queue is not handled in time and overflow. - BaseType_t high_task_wakeup = pdFALSE; - - t15_ccr[1] = edata->cap_value; - // t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq); - t15_ccr_times[1]++; - // send measurement back though queue - // xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup); - - return high_task_wakeup == pdFALSE; -} - -void capture_flow2_init() -{ - ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO)); - // enable pull down CAP0, to reduce noise - ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO)); - // enable both edge capture on CAP0 - mcpwm_capture_config_t conf = { - .cap_edge = MCPWM_NEG_EDGE, - .cap_prescale = 1, - .capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数 - .user_data = NULL}; - ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf)); - ESP_LOGI(TAG, "capture_flow_init"); -} - -void flow_input_type2_init(void) -{ - capture_flow1_init(); - capture_flow2_init(); -} diff --git a/main/peripheral/inc/bl0939.h b/main/peripheral/inc/bl0939.h deleted file mode 100644 index 49b3dc1..0000000 --- a/main/peripheral/inc/bl0939.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __BL0939_H -#define __BL0939_H - -#include - - -#define BL0939_HOST SPI3_HOST -#define SPI1_PIN_NUM_MISO 37 -#define SPI1_PIN_NUM_MOSI 36 -#define SPI1_PIN_NUM_CLK 35 -#define SPI1_PIN_NUM_CS 40 - -typedef struct -{ - uint16_t status; // 0:未开始 1:开始 2:结束 - uint16_t time_count; //持续时间 - uint16_t pile_inc_req; -} move_t; - -extern move_t *pMoveCtx; - -void bl0939_reset(void); -int bl0939_get_current_A(void); -int bl0939_get_current_B(void); -int bl0939_get_voltage(void); - -//DMA -void bl0939_get_abv(uint8_t * buf); -int bl0939_parse_abv(uint8_t * buf,unsigned int * data); - -void BL0939_init(void); - -#endif \ No newline at end of file diff --git a/main/peripheral/inc/depth.h b/main/peripheral/inc/depth.h deleted file mode 100644 index ebef68f..0000000 --- a/main/peripheral/inc/depth.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef __DEPTH_H -#define __DEPTH_H - -#include - - -#define FLOW_SYNC_PIN 7 // 捕获GPIO端口 SPI2_nIRQ - -#define DEPTH_PIN_PULSE 39 // 深度脉冲GPIO端口 TIM15_CH1 -#define DEPTH_PIN_CTRL 38 // 深度控制GPIO端口 TIM15_CH2 -#define DEPTH_PIN_ENC_A 42 // 深度脉冲GPIO端口 TIM3_CH1 -#define DEPTH_PIN_ENC_B 41 // 深度控制GPIO端口 TIM3_CH2 -#define SEND_DATA_TEST 0 - -#define PILE_STATE_STOP 0x0100 -#define PILE_STATE_PAUSE 0x0200 -#define PILE_STATE_WORK 0x0300 - -#define PILE_DIR_NONE 0x01 -#define PILE_DIR_UP 0x02 -#define PILE_DIR_DOWN 0x03 - - - -typedef struct -{ - uint16_t magic; - uint8_t input_type; // 0:正交 1:正交反向 2:方向脉冲 3:方向脉冲反向 - uint8_t port; // 编码器端口 - uint16_t N; //编码器系数分子 - uint16_t M; //编码器系数分母 - // int pluse_coef; // 脉冲系数0.001mm - int16_t min_depth; // 最小深度 mm - int16_t max_depth; // 最大深度 mm - int16_t sample_depth; // 采样深度 mm - int16_t depth_offset; // 默认深度偏移 - int16_t min_valid_depth; // 最小有效深度 - int16_t inc_pile_depth; // 允许换桩深度 - uint16_t current_on_threshold; // 行走电机开启电流 - uint16_t current_off_threshold; // 行走电机关闭电流 - uint16_t move_on_duratino; // 持续时间 - uint16_t move_off_duration; // 持续时间 - uint16_t move_current_channel; //行走电流通道 -} depth_config_t; - - -typedef struct -{ - uint16_t pile_work_state_and_direction; // 12 - int16_t speed; // 13 - int16_t depth; // 14 - uint16_t sample_count; // 15 - uint16_t depth_flow[2]; // 16~17 - uint32_t last_total_flow[2]; // - int16_t depth_offset; // 22 - uint16_t one_pile_work_time; //23 系统工作时间 - // uint32_t update_time; - // int16_t tilt_x; - // int16_t tilt_y; - // uint16_t current1; - // uint16_t current2; - // uint16_t current3; -} depth_t; - - -typedef struct -{ - int16_t max_depth; - uint16_t pile_id; - uint16_t count; - // uint16_t work_time; - struct _item - { - int16_t speed; - int16_t depth; - int16_t flow[2]; - uint32_t total_flow[2]; - int16_t tilt_x; - int16_t tilt_y; - uint16_t current1; - uint16_t current2; - } item[10]; -} record_t; - -extern depth_config_t *depth_config; -extern depth_t *depth_data; -extern record_t *record; - - -void DEPTH_init(void); -void reset_depth(void); -void add_recod_item(void); - - -#endif \ No newline at end of file diff --git a/main/stm32/ModbusM.c b/main/stm32/ModbusM.c new file mode 100644 index 0000000..4727397 --- /dev/null +++ b/main/stm32/ModbusM.c @@ -0,0 +1,680 @@ +#include +#include +#include "ModbusM.h" +#include "ModbusS.h" +#include "config.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "uart.h" +#include "driver/uart.h" + +#define ZB_CHANNEL 1 + +extern uint16_t gWordVar[]; +//uint16_t g_tmp[100]; +device_t zb_device[ZB_CHANNEL]; + +send_t zb_send[16]; + +#define GetTicks xTaskGetTickCount +#define UART1_TXBUF_SIZE 256 + +int zbapi_send_write(device_t *device, send_t *sender); +int zbapi_send_req(device_t *device); +int max(int x, int y) +{ + if (x > y) + return x; + else + return y; +} + +//static float pow_user(float x, float y) +//{ +// int i; +// float tmp = 1; +// for (i = 0; i < y; i++) +// { +// tmp = tmp * x; +// } +// return tmp; +//} +uint16_t bin2bcd(uint16_t bin) +{ + uint16_t bcd; + uint8_t buf[4]; + if (bin > 9999) + { + bin = 9999; + } + buf[0] = bin % 10; + bin /= 10; + buf[1] = bin % 10; + bin /= 10; + buf[2] = bin % 10; + buf[3] = bin / 10; + bcd = buf[0] | (buf[1] << 4) | (buf[2] << 8) | (buf[3] << 12); + return bcd; +} +int min(int x, int y) +{ + if (x < y) + return x; + else + return y; +} +// ��������sn ֵ +uint8_t get_new_sn(int device_id) +{ + int i; + int sn = 0; + for (i = 0; i < 16; i++) + { + if (zb_send[i].device_id == device_id) + { + sn = max(zb_send[i].sn, sn); + } + } + return sn + 1; +} + +// �����豸��Сsn��Ӧ���±� +int device_get_send(int device_id) +{ + int i; + int sn = 255; + int min_index = -1; + for (i = 0; i < 16; i++) + { + if (zb_send[i].device_id == device_id) + { + if (zb_send[i].sn < sn) + { + sn = zb_send[i].sn; + min_index = i; + } + } + } + return min_index; +} +void on_in_pack_error(device_t *device) +{ + if (device->in_err_cnt[device->in_index] < device->in->max_err_cnt) + { + if (++device->in_err_cnt[device->in_index] >= device->in->max_err_cnt) + { + const packet_t *in_pack = device->in->packets + device->in_index; + int i; + for (i = 0; i < in_pack->length; i++) + { + uint32_t reg_addr = in_pack->local_addr + i; + if (reg_addr < gWORD_SIZE) + { + gWordVar[reg_addr] = 0; + } + } + if (device->protocol == 255) + { + if (in_pack->slave > 0 && in_pack->slave <= 10) + { + int i; + for (i = 0; i < 10; i++) + { + gWordVar[in_pack->local_addr] = 0; + } + } + if (in_pack->slave == 0) + { + gWordVar[64 + 10] = 0; + } + } + // on_data_error(device); + } + } +} +extern int page; +void modbus_master_poll(int n) +{ + uint32_t now = GetTicks(); + // printf("status == %d\n",zb_device[n].status); + if (zb_device[n].status == 0) // 空闲状态 + { + if (zb_device[n].out_pending > 0) ////如果有发送请求先处理发送 + { + // printf("out_pending > 0\n"); + int send_index = device_get_send(n); + if (send_index >= 0) + { + if (now >= zb_send[send_index].next_try_time) + { + zb_device[n].out_index = send_index; + zb_device[n].send_req_time = now; + zbapi_send_write(&zb_device[n], &zb_send[send_index]); + zb_device[n].status = 0x10; + return; + } + } + else + { + zb_device[n].out_pending = 0; + } + } + if (now >= zb_device[n].next_scan_time) + { + // printf("now >= zb_device[%d]\n",n); + zb_device[n].send_req_time = now; + zbapi_send_req(&zb_device[n]); + zb_device[n].status = 2; + } + } + else if (zb_device[n].status == 1 || zb_device[n].status == 2) // + { + + if ((now - zb_device[n].send_req_time) > zb_device[n].in->time_out * 100) + { + zb_device[n].status = 0; //��ʱ + zb_device[n].ErrCode = 0x01; + zb_device[n].ErrCount++; + on_in_pack_error(&zb_device[n]); + if ((++zb_device[n].try_times >= zb_device[n].in->max_try_times) || + (zb_device[n].in_err_cnt[zb_device[n].in_index] >= zb_device[n].in->max_err_cnt)) + { + if (++zb_device[n].in_index >= zb_device[n].in->packet_cnt) + { + zb_device[n].in_index = 0; + zb_device[n].group_start_time = now; + } + //zb_device[n].next_scan_time = zb_device[n].group_start_time + zb_device[n].in->scan_rate*10; + zb_device[n].try_times = 0; + } + zb_device[n].next_scan_time = zb_device[n].group_start_time + zb_device[n].in->scan_rate * 10; + zb_device[n].status = 0; + } + } + else if (zb_device[n].status == 3) // ���յ��ظ� + { + if (++zb_device[n].in_index >= zb_device[n].in->packet_cnt) + { + zb_device[n].in_index = 0; + zb_device[n].group_start_time = now; //+ zb_device[n].in->scan_rate*10; + } + zb_device[n].next_scan_time = zb_device[n].group_start_time + zb_device[n].in->scan_rate * 10; + zb_device[n].status = 255; + zb_device[n].try_times = 0; + } + else if (zb_device[n].status == 0x10) // �������������ѷ����ȴ���Ӧ���߳�ʱ + { + int index = zb_device[n].out_index; + if ((now - zb_device[n].send_req_time) > zb_device[n].in->time_out * 100) + { + zb_device[n].status = 0; //��ʱ + zb_device[n].ErrCode = 0x01; + zb_device[n].ErrCount++; + if (++zb_send[index].try_times >= zb_device[n].out->max_try_times) //����������Դ���������ʧ�� + { + zb_send[index].device_id = 0xff; + } + else + { + zb_send[index].next_try_time = now + zb_device[n].out->try_space * 100; + } + zb_device[n].status = 0; + zb_device[n].try_times = 0; + } + } + else if (zb_device[n].status == 0x11) // ���յ���������ȷ�� + { + zb_send[zb_device[n].out_index].device_id = 0xff; + zb_device[n].status = 255; + zb_device[n].try_times = 0; + } + else + { + if ((now - zb_device[n].revice_resp_time) >= (zb_device[n].in->scan_space)) + { + zb_device[n].status = 0; + zb_device[n].try_times = 0; + } + } +} +// �����ཻ +int intersection(int x0, int x1, int y0, int y1, int *s, int *e) +{ + int ret = 0; + if ((y0 >= x0) && (y0 < x1)) + { + *s = y0; + *e = min(x1, y1); + ret = 1; + } + else if ((y1 > x0) && (y1 <= x1)) + { + *s = y1 - 1; + *e = min(x1, y1); + ret = 1; + } + else if ((x0 >= y0) && (x0 < y1)) + { + *s = x0; + *e = min(y1, x1); + ret = 1; + } + else if ((x1 > y0) && (x1 <= y1)) + { + *s = x1 - 1; + *e = min(y1, x1); + ret = 1; + } + return ret; +} +int zb_ModBusWordWriteHook(uint16_t addr, uint16_t length) +{ + int i, j; + int ret = 0; + for (i = 0; i < ZB_CHANNEL; i++) + { + if (zb_device[i].out == NULL) + { + continue; + } + for (j = 0; j < zb_device[i].out->packet_cnt; j++) + { + int s1, e1; + int s2, e2; + int s, e; + int n; + s1 = zb_device[i].out->packets[j].local_addr; + e1 = zb_device[i].out->packets[j].local_addr + zb_device[i].out->packets[j].length; + s2 = addr; + e2 = addr + length; + if (intersection(s1, e1, s2, e2, &s, &e)) + //if((s2 >= s1 && s2 < e1) || (e2 >= s1 && s2 < e1)) + { + for (n = 0; n < 16; n++) + { + if (zb_send[n].device_id == 0xff) + { + zb_send[n].sn = get_new_sn(i); + zb_send[n].device_id = i; + zb_send[n].packet_index = j; + zb_send[n].address = s; + zb_send[n].length = e - s; + zb_send[n].next_try_time = 0; + zb_send[n].try_times = 0; + zb_device[i].out_pending++; + ret = 1; + break; + } + } + } + } + } + return ret; +} + +//extern uint8_t Uart3TxBuf[]; +//#define txbuf Uart3TxBuf + +int zbapi_send_req(device_t *device) +{ + if (device->protocol == 255) + { + device->txbuf[0] = device->in->packets[device->in_index].slave; + device->txbuf[1] = 0x5a; + device->txbuf[2] = 0xaa; + device->write(device->txbuf, 3); + } + else + { + uint16_t crc; + device->txbuf[0] = device->in->packets[device->in_index].slave; + device->txbuf[1] = device->in->packets[device->in_index].funcode; + device->txbuf[2] = device->in->packets[device->in_index].address >> 8; + device->txbuf[3] = device->in->packets[device->in_index].address & 0xff; + device->txbuf[4] = device->in->packets[device->in_index].length >> 8; + device->txbuf[5] = device->in->packets[device->in_index].length & 0xff; + crc = crc16(device->txbuf, 6); + device->txbuf[6] = crc >> 8; + device->txbuf[7] = crc & 0xff; + device->write(device->txbuf, 8); + } + return 0; +} +int zbapi_send_write(device_t *device, send_t *sender) +{ + { + int n = 0; + uint16_t crc; + const packet_t *out_pack = &device->out->packets[sender->packet_index]; + if (sender->length == 0) + { + return 0; + } + device->txbuf[0] = device->out->packets[sender->packet_index].slave; + if (sender->length > 1) + { + int addr = out_pack->address + (sender->address - out_pack->local_addr); + int i; + int len; + device->txbuf[1] = 0x10; + device->txbuf[2] = addr >> 8; + device->txbuf[3] = addr & 0xff; + device->txbuf[4] = sender->length >> 8; + device->txbuf[5] = sender->length & 0xff; + device->txbuf[6] = (sender->length * 2) & 0xff; + len = 7; + for (i = 0; i < sender->length; i++) + { + uint16_t reg16 = gWordVar[sender->address + i]; + if (out_pack->device_type == 5) + { + reg16 = bin2bcd(reg16); + } + device->txbuf[len++] = reg16 >> 8; + device->txbuf[len++] = reg16 & 0xff; + } + crc = crc16(device->txbuf, len); + device->txbuf[len++] = crc >> 8; + device->txbuf[len++] = crc & 0xff; + n += len; + } + else + { + int addr = out_pack->address + (sender->address - out_pack->local_addr); + uint16_t reg16 = gWordVar[sender->address]; + device->txbuf[1] = 0x06; + device->txbuf[2] = addr >> 8; + device->txbuf[3] = addr & 0xff; + if (out_pack->device_type == 5) + { + reg16 = bin2bcd(reg16); + } + if ((device->protocol == 5) || (device->protocol == 6)) + { + reg16 *= 10; + } + device->txbuf[4] = reg16 >> 8; + device->txbuf[5] = reg16 & 0xff; + crc = crc16(device->txbuf, 6); + device->txbuf[6] = crc >> 8; + device->txbuf[7] = crc & 0xff; + n += 8; + } + if (device->write != NULL) + { + device->write(device->txbuf, n); + } + } + return 1; +} + +extern uint16_t Is_SetFromScreen; + +int modbus_master_on_revice(int ch, uint8_t *rxbuf, int length) +{ + int i; +// uint8_t src_addr[8]; + if (length < 4) + { + return -1; + } + i = ch; + //for(i=0; ipackets[index].slave == rxbuf[0]) && + zb_device[i].in->packets[index].funcode == rxbuf[1]) + { + uint16_t crcChk = crc16(rxbuf, length - 2); + uint16_t crcData = (rxbuf[length - 2] << 8) | rxbuf[length - 1]; + if (crcData != crcChk) + { + zb_device[i].ErrCode = 2; //CRC error + zb_device[i].ErrCount++; + } + else if (rxbuf[0] != zb_device[i].in->packets[index].slave) + { + zb_device[i].ErrCode = 3; //ADD error + zb_device[i].ErrCount++; + } + else if (rxbuf[1] != zb_device[i].in->packets[index].funcode) + { + zb_device[i].ErrCode = 4; //Fun err; + zb_device[i].ErrCount++; + } + else if (rxbuf[2] != (zb_device[i].in->packets[index].length * 2)) + { + zb_device[i].ErrCode = 1; //byte miss + zb_device[i].ErrCount++; + } + else + { + int n = 0; + // uint32_t reg32; + uint16_t addr = zb_device[i].in->packets[index].local_addr; + uint8_t len = rxbuf[2] / 2; + if (addr >= gWORD_SIZE) + { + zb_device[i].ErrCode = 5; //regaddr err; + goto done; + } + zb_device[i].ErrCode = 0; + switch (zb_device[i].in->packets[index].device_type) + { + default: + + for (n = 0; n < len; n++) + { + if (addr + n < gWORD_SIZE) + { + gWordVar[addr + n] = (rxbuf[3 + n * 2] << 8) | (rxbuf[3 + n * 2 + 1]); + } + else + { + break; + } + } + break; + } + zb_device[i].in_err_cnt[zb_device[i].in_index] = 0; + } + done: + zb_device[i].status = 3; + } + } + } + else if (zb_device[i].status == 0x10) + { + zb_device[i].revice_resp_time = GetTicks(); + //if(memcmp(src_addr,((zb_dev_t*)zb_device[i].ext)->zb_addr,8) == 0) + { + zb_device[i].status = 0x11; + } + } + } + return 0; +} + +//int meter_count = 4; + +//#define meter_count meter_cfg.count +//const int reg_offset[] = {0, 2, 3, 4, 1}; + +//static char input_buf[1][414]; +//static char output_buf[1][212]; +static char in_err_cnt_buf[1][25]; +struct input{ + input_t input; + packet_t packet[5]; +}; +struct output{ + output_t output; + packet_t packet[5]; +}; +struct input input1; +struct output output1; + +extern int uart1_tx_start(uint8_t *data, int length); +extern uint8_t uart1_txbuf[]; +//static uint8_t uart_txbuf[ 256 ]; +//static uint8_t uart_rxbuf[ 256 ]; + +static int uart_send(uint8_t *buf, int len) +{ + // uart1_tx_start(buf, len); + uart_write_bytes(RS485_UART_PORT_NUM, buf, len); + //HAL_UART_Transmit_DMA(&huart1,buf,len); + return len; +} +int ModbusM_init(void) +{ + int i = 0; +// int meter_count[4] = {0, 0, 0, 0}; +// int size; +// char *p; + // int n; +// uint8_t *in_err_cnt; + + zb_device[0].txbuf = uart1_txbuf; + zb_device[0].txbuf_size = UART1_TXBUF_SIZE; + zb_device[0].write = uart_send; + + { + input_t *input; + output_t *output; + uint8_t *in_err_cnt; + + + // memset(input_buf[i], 0, sizeof(input_buf[i])); + // memset(output_buf[i], 0, sizeof(output_buf[i])); + // memset(in_err_cnt_buf[i], 0, sizeof(in_err_cnt_buf[i])); + + output = &output1.output; + input = &input1.input; + in_err_cnt = (uint8_t *)in_err_cnt_buf[i]; + + zb_device[i].in_err_cnt = in_err_cnt; + + input->scan_rate = 10; //*10ms + input->time_out = 10; //*100ms + input->max_try_times = 2; + input->scan_space = 50; //*10ms + input->max_err_cnt = 30; + + output->max_try_times = 3; + output->try_space = 40; + + zb_device[i].channl = i; + zb_device[i].next_scan_time = 0; + zb_device[i].status = 0; + zb_device[i].try_times = 0; + zb_device[i].in_index = 0; + zb_device[i].out_pending = 0; + zb_device[i].in_err_cnt = in_err_cnt; + zb_device[i].in = input; + zb_device[i].out = output; + // zb_device[i].ext = &serial_port_cfg[i]; + } + { + device_t *dev = (device_t *)&zb_device; + dev->in->packets[dev->in->packet_cnt].slave = 1; + dev->in->packets[dev->in->packet_cnt].funcode = 3; + dev->in->packets[dev->in->packet_cnt].address = 0; + dev->in->packets[dev->in->packet_cnt].length = 3; + dev->in->packets[dev->in->packet_cnt].device_type = 0; + dev->in->packets[dev->in->packet_cnt].local_addr = TILT_SENSER_ADDR; + dev->in->packets[dev->in->packet_cnt].ch = 0; + dev->in->packet_cnt++; + + dev->out->packets[dev->out->packet_cnt].slave = 1; + dev->out->packets[dev->out->packet_cnt].funcode = 6; + dev->out->packets[dev->out->packet_cnt].local_addr = 10; + dev->out->packets[dev->out->packet_cnt].length = 1; + dev->out->packets[dev->out->packet_cnt].address = 5; + dev->out->packets[dev->out->packet_cnt].device_type = 0; + dev->in->packets[dev->in->packet_cnt].ch = 0; + dev->out->packet_cnt++; + } + return 0; +} +extern int meter_type; + +void ModbusM_reinit(void) +{ + int i; + for (i = 64; i < 64 + 128; i++) + { + gWordVar[i] = 0; + } + ModbusM_init(); +} + +int fill_data(uint8_t *pData, uint16_t local_addr, uint8_t remote_offset, uint8_t length) +{ + uint16_t *pWordVar; + int i; + *pData++ = remote_offset; + *pData++ = length; + pWordVar = &gWordVar[local_addr]; + for (i = 0; i < length; i++) + { + *pData++ = *pWordVar >> 8; + *pData++ = *pWordVar & 0xff; + pWordVar++; + } + return i * 2 + 2; +} +int build_data(int dest_addr, const int *src_addr_map, int length) +{ + int i; + int change_cnt = 0; + for (i = 0; i < length; i++) + { + int src_addr = src_addr_map[i]; + if (dest_addr < gWORD_SIZE && src_addr >= 0 && src_addr < gWORD_SIZE) + { + if (gWordVar[dest_addr] != gWordVar[src_addr]) + { + gWordVar[dest_addr] = gWordVar[src_addr]; + change_cnt++; + } + } + else + { + return -1; + } + dest_addr++; + } + return change_cnt; +} +int copy_data(int dest_addr, int src_addr, int length) +{ + int i; + int change_cnt = 0; + for (i = 0; i < length; i++) + { + //int src_addr = src_addr_map[i]; + if (dest_addr < gWORD_SIZE && src_addr >= 0 && src_addr < gWORD_SIZE) + { + if (gWordVar[dest_addr] != gWordVar[src_addr]) + { + gWordVar[dest_addr] = gWordVar[src_addr]; + change_cnt++; + } + } + else + { + return -1; + } + dest_addr++; + src_addr++; + } + return change_cnt; +} diff --git a/main/stm32/ModbusM.h b/main/stm32/ModbusM.h new file mode 100644 index 0000000..a216e42 --- /dev/null +++ b/main/stm32/ModbusM.h @@ -0,0 +1,120 @@ +#ifndef _MODBUSM_H_ +#define _MODBUSM_H_ +#define uint8 unsigned char +#define uint16 unsigned short +#define uint32 unsigned int + +typedef struct _MODBUS_MASTRT_ +{ + uint8 Status; + uint8 ErrCode; + + uint8 Slave; + uint8 Function; + + uint8 PackId; + uint8 Length; + uint16 Address; + + uint16 *Data; + + uint32 txtime; + uint32 rxtime; + uint16 TxCont; + uint16 TimeOut; + uint16 CrcErr; + uint16 ByteMiss; + uint16 OtherErr; +}MODBUS_MASTERT_T; +typedef struct _MODBUS_READ_T_ +{ + uint8 SaveAdd; + uint8 Length; + uint16 RegAdd; + uint16 *pDat; +}MODBUS_READ_T; + + + +typedef struct _packet_ +{ + uint8_t device_type; + uint8_t slave; + uint8_t funcode; + uint8_t ch; + uint16_t length; + uint16_t address; + uint16_t local_addr; + uint16_t ext_flg; + const void* ext; +}packet_t; + +typedef struct _input_ +{ + uint8_t packet_cnt; + uint8_t max_try_times; + uint8_t time_out; + + uint16_t scan_rate; + uint16_t scan_space; + + uint8_t max_err_cnt; + uint8_t ch; + uint8_t rsv[2]; + packet_t packets[1]; +}input_t; + +typedef struct _output_ +{ + uint8_t packet_cnt; + uint8_t max_try_times; + uint8_t try_space; + uint8_t rsv; + packet_t packets[1]; +}output_t; + +typedef struct _device_ +{ + uint8_t channl; + uint8_t protocol; + uint8_t status; + uint8_t in_index; + + uint8_t try_times; + uint8_t out_pending; + uint8_t out_index; + uint8_t ErrCode; + + uint8_t continue_err; + uint8_t max_coutinue; + uint16_t ErrCount; + uint16_t PackId; + + uint32_t group_start_time; + uint32_t next_scan_time; + uint32_t send_req_time; + uint32_t revice_resp_time; + uint8_t *txbuf; + int txbuf_size; + int (*write)(uint8*, int); + uint8_t *in_err_cnt; + input_t *in; + output_t *out; + void *ext; +}device_t; + +typedef struct _send_ +{ + uint8_t device_id; + uint8_t sn; + uint8_t packet_index; + uint8_t try_times; + uint16_t address; + uint16_t length; + uint32_t next_try_time; +}send_t; +extern int ModbusM_init(void); +extern int ModbusMastertRx(MODBUS_MASTERT_T *m,uint8 *rxbuf, uint8 len); +extern void ModbusMastertPoll(MODBUS_MASTERT_T *m); +extern int zb_ModBusWordWriteHook(unsigned short addr, unsigned short length); +#endif diff --git a/main/modbus/ModbusS.c b/main/stm32/ModbusS.c similarity index 82% rename from main/modbus/ModbusS.c rename to main/stm32/ModbusS.c index 55e0ed1..f790e86 100644 --- a/main/modbus/ModbusS.c +++ b/main/stm32/ModbusS.c @@ -1,9 +1,13 @@ #include -// #include "driver/ledc.h" -// #include "esp_err.h" -#include "esp_log.h" #include "ModbusS.h" -#include "gwordvar.h" +#include "config.h" +#include +#include "driver/ledc.h" +#include "esp_err.h" +#include +#include "esp_log.h" + +#include "config.h" static const char *TAG = "main"; @@ -104,58 +108,70 @@ int isBitHI(uint16_t Add) void ModBusBitWriteHook(uint16_t addr, uint16_t length) { } - -// extern void reset_depth(void); -// uint16_t reboot_req ; +extern void reset_depth(void); +uint16_t reboot_req ; // extern uint16_t last_pile_id; -// extern int zb_ModBusWordWriteHook(uint16_t addr, uint16_t length); +extern uint16_t *cur_pile_id; +extern int zb_ModBusWordWriteHook(uint16_t addr, uint16_t length); void ModBusWordWriteHook(uint16_t addr, uint16_t length) { -// // ESP_LOGI(TAG, "ModBusWordWriteHook"); -// if(addr == RECORD_REG_ADDR && gWordVar[RECORD_REG_ADDR] == 0xffff){ -// reset_depth(); -// gWordVar[RECORD_REG_ADDR] = 0; -// } -// if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x5555){ -// config_load(); -// gWordVar[DEPTH_RESET_ADDR] = 0; -// } -// if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x55aa){ -// gWordVar[RECORD_REG_ADDR] = 9999; //强制增加桩号 -// reset_depth(); -// gWordVar[DEPTH_RESET_ADDR] = 0; -// } -// if(addr == LAST_PILE_ID_ADDR){ -// last_pile_id = gWordVar[LAST_PILE_ID_ADDR]; -// } -// else if(addr == FLOW_CONFIG_ADDR && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa){ -// save_flow_cfg(); -// } -// else if(addr == DEPTH_CONFIG_ADDR && gWordVar[DEPTH_CONFIG_ADDR] == 0x55aa){ -// save_depth_cfg(); -// } -// else if(addr == CAL_4_20MA_ADDR && gWordVar[CAL_4_20MA_ADDR] == 0x55aa){ -// save_cal_4_20ma(); -// } -// else if(addr == REBOOT_REW_ADDR ){ -// if(gWordVar[REBOOT_REW_ADDR] == 0x55aa){ -// reboot_req = 0x55aa; -// } -// else if(gWordVar[REBOOT_REW_ADDR] == 0x55ab){ -// esp_restart(); -// } -// else if(gWordVar[REBOOT_REW_ADDR] == 0xaa55){ -// restore_default(); -// esp_restart(); -// } -// } -// else{ -// zb_ModBusWordWriteHook(addr,length); -// } + // ESP_LOGI(TAG, "ModBusWordWriteHook"); + if(addr == RECORD_REG_ADDR && gWordVar[RECORD_REG_ADDR] == 0xffff){ + // reset_depth(); + gWordVar[RECORD_REG_ADDR] = 0; + } + if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x5555){ + config_load(); + gWordVar[DEPTH_RESET_ADDR] = 0; + } + if(addr == DEPTH_RESET_ADDR && gWordVar[DEPTH_RESET_ADDR] == 0x55aa){ + gWordVar[RECORD_REG_ADDR] = 9999; //强制增加桩号 + // reset_depth(); + gWordVar[DEPTH_RESET_ADDR] = 0; + } + if(addr == LAST_PILE_ID_ADDR){ + *cur_pile_id = gWordVar[LAST_PILE_ID_ADDR]; + } + else if(addr == FLOW_CONFIG_ADDR && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa){ + save_flow_cfg(); + } + else if(addr == DEPTH_CONFIG_ADDR && gWordVar[DEPTH_CONFIG_ADDR] == 0x55aa){ + save_depth_cfg(); + } + else if(addr == CAL_4_20MA_ADDR && gWordVar[CAL_4_20MA_ADDR] == 0x55aa){ + save_cal_4_20ma(); + } + // else if(addr >= FLOW_CONFIG_ADDR && addr < (FLOW_CONFIG_ADDR + sizeof(flow_config_t))/* && gWordVar[FLOW_CONFIG_ADDR] == 0x55aa */){ + // save_flow_cfg(); + // } + // else if(addr >= DEPTH_CONFIG_ADDR && addr < (DEPTH_CONFIG_ADDR + sizeof(depth_config_t))){ + // save_depth_cfg(); + // } + // else if(addr >= CAL_4_20MA_ADDR && addr < (CAL_4_20MA_ADDR + sizeof(cal_4_20ma_t))){ + // save_cal_4_20ma(); + // } + else if(addr == REBOOT_REW_ADDR ){ + if(gWordVar[REBOOT_REW_ADDR] == 0x55aa){ + reboot_req = 0x55aa; + } + else if(gWordVar[REBOOT_REW_ADDR] == 0x55ab){ + esp_restart(); + } + else if(gWordVar[REBOOT_REW_ADDR] == 0xaa55){ + restore_default(); + esp_restart(); + } + } + else{ + zb_ModBusWordWriteHook(addr,length); + } } +extern volatile int modbus_save_flg; +uint16_t modbus_addr = 1; int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc) { + // ESP_LOGI(TAG, "ModbusSlaveProcess"); uint16_t crcData,crcChk; uint8_t Offset,ByteAdd; uint16_t ByteNumber; @@ -171,7 +187,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr } /*地址校验*/ - if((rxbuf[0]==MODBUS_SALVE_ADDRESS) || (rxbuf[0]==255)){ + if((rxbuf[0]==modbus_addr) || (rxbuf[0]==255)){ /*crc校验*/ if(is_crc != 0){ @@ -212,6 +228,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr break; case 0x03: case 0x04: //Read Holding Registers + // ESP_LOGI(TAG, "read"); if((add+length) > gWORD_SIZE) { txbuf[1] = 0x80 + rxbuf[1]; @@ -270,6 +287,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr out_len = 6; break; case 0x06: //Write Single Register + // ESP_LOGI(TAG, "write"); // ESP_LOGI(TAG, "modbus 0x06"); if(add >= gWORD_SIZE) { @@ -310,6 +328,7 @@ int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_cr out_len = 6; break; case 0x10: //Write Multiple registers + ESP_LOGI(TAG, "write"); if((add+length) > gWORD_SIZE) { txbuf[1] = 0x90; diff --git a/main/stm32/ModbusS.h b/main/stm32/ModbusS.h new file mode 100644 index 0000000..3da6c7b --- /dev/null +++ b/main/stm32/ModbusS.h @@ -0,0 +1,46 @@ +#ifndef _MODBUS_H +#define _MODBUS_H +#include +//#define uint8_t unsigned char +//#define uint16_t unsigned short +//#define uint32 unsigned int + +#define setBit(Add) gBitVar[(Add)>>3] |= (1<<((Add)&0x07)) +#define clrBit(Add) gBitVar[(Add)>>3] &= ~(1<<((Add)&0x07)) +//#define ModBusTxData uart1_tx + +extern uint16_t crc16(uint8_t *puchMsg, uint16_t usDataLen); +extern int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc); + + + + +int isBitHI(uint16_t Add); +void xorBit(uint16_t Add); + +void WriteBit(uint16_t Add,uint8_t bit_value); +#define gBIT_SIZE 128 +#define gWORD_SIZE 1024 +extern uint8_t gBitVar[(gBIT_SIZE+7)/8]; +extern uint16_t gWordVar[gWORD_SIZE]; +extern uint16_t modbus_addr; + +// #include "usart.h" +// #include "gpio.h" +// #include "main.h" +#define BUFFER_SIZE 2000 +extern uint8_t rx_buffer[256]; +extern uint8_t tx_buffer[256]; +extern uint16_t rx_buff_len; +// extern __IO uint8_t recv_end_flag; +extern uint8_t recv_end_flag; +extern void modbus_recv_mode(void); +extern void usart2_dma_recv_start(void); +extern void modbus_send(uint8_t *buf, uint8_t len); +// extern void save_flow_cfg(void); +extern int check_mastrt_recv(void); + +void ModBusWordWriteHook(uint16_t addr, uint16_t length); + +#endif + diff --git a/main/stm32/ads1220.c b/main/stm32/ads1220.c new file mode 100644 index 0000000..a97d9f9 --- /dev/null +++ b/main/stm32/ads1220.c @@ -0,0 +1,426 @@ +#include "ads1220.h" +// #include "main.h" +#include "config.h" +#include "ModbusS.h" +#include "ModbusM.h" +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "driver/spi_master.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "freertos/queue.h" +#include "utils.h" +#include "config.h" +#include "driver/mcpwm.h" +#include "depth.h" +#include "led.h" + +#define TAG "ADS1220" + +static spi_device_handle_t spi2; +QueueHandle_t ads1220_drdy_queue = NULL; +const uint8_t ch_cmd[4] = {0x0C, 0xA1, 0x0C, 0xB1}; + +int ad_value[4]; +uint32_t ad_update_time[4]; +extern flow_t *pflow; + +static int ch = 0; + +void ADS1220_Init(void) +{ + // ESP_LOGI(TAG, "Start init ADS1220.\n"); + ADS1220_Config(); + // ESP_LOGI(TAG, "Start ADS1220_Config.\n"); + ch = 0; + + ADS1220_WriteReg(ADS1220_REG0, ch_cmd[0]); + ADS1220_WriteCommand(ADS1220_CMD_START); +} + +static void IRAM_ATTR ads1220_done_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, + const cap_event_data_t *edata, void *arg) +{ + // uint32_t gpio_num = (uint32_t)arg; + // if (ch == 1) + // { + // pflow[0].update_time = xTaskGetTickCount(); + // } + // if (ch == 3) + // { + // pflow[1].update_time = xTaskGetTickCount(); + // } + // ESP_LOGI(TAG, "ads done"); + ad_update_time[ch] = edata->cap_value; + xQueueSendFromISR(ads1220_drdy_queue, &ad_update_time[ch], NULL); +} + +static void GPIO_Init(void) +{ + // interrupt of rising edge + // io_conf.intr_type = GPIO_INTR_NEGEDGE; + // // bit mask of the pins, use GPIO4/5 here + // io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL; + // // set as input mode + // io_conf.mode = GPIO_MODE_INPUT; + // // enable pull-up mode + // io_conf.pull_up_en = 1; + // gpio_config(&io_conf); + + // change gpio intrrupt type for one pin + // gpio_set_intr_type(GPIO_INPUT_IO_39, GPIO_INTR_NEGEDGE); + + // create a queue to handle gpio event from isr + ads1220_drdy_queue = xQueueCreate(1, sizeof(uint32_t)); + // install gpio isr service + // gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); + // // hook isr handler for specific gpio pin + // gpio_isr_handler_add(GPIO_INPUT_IO_39, gpio_isr_handler, (void *)GPIO_INPUT_IO_39); + + ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_1, GPIO_INPUT_IO_39)); + // enable pull down CAP0, to reduce noise + ESP_ERROR_CHECK(gpio_pullup_en(GPIO_INPUT_IO_39)); + // enable both edge capture on CAP0 + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_NEG_EDGE, + .cap_prescale = 1, + .capture_cb = ads1220_done_handler, // 绑定深度中断处理函数 + .user_data = NULL}; + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP1, &conf)); +} + +uint8_t ret = 0; + +/**** + * ADS1220���Ĵ��� + **/ +u8 ADS1220_ReadReg(u8 reg) +{ + u8 Val; + esp_err_t ret; + spi_transaction_t t; + memset(&t, 0, sizeof(t)); // Zero out the transaction + t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; + t.tx_data[0] = ADS1220_CMD_RREG | ((reg & 0x03) << 2); + t.length = 2 * 8; + ret = spi_device_polling_transmit(spi2, &t); // Transmit! + assert(ret == ESP_OK); + Val = t.rx_data[1]; + return Val; +} +/*** + * ��ADS1220������д��24Bits + * + **/ + +// static u32 ADS1220_ReadWrite24Bits(u32 dat) +// { +// uint8_t tmp[3]; +// static int val = 0; + +// HAL_SPI_TransmitReceive(&spi2, (uint8_t *)&dat, (uint8_t *)tmp, 3, 500); + +// val = ((uint32_t)tmp[0] << 16) + ((uint32_t)tmp[1] << 8) + ((uint32_t)tmp[2] << 0); + +// // ������λ 23λ ��1 ��Ϊ �з��� +// if (val & 0x800000) +// { +// val |= 0xFF000000; +// } +// return val; +// } + +// ADS1220������ +s32 ADS1220_ReadData(void) +{ + s32 Val = 0; + esp_err_t ret; + spi_transaction_t t; + memset(&t, 0, sizeof(t)); // Zero out the transaction + t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; + t.tx_data[0] = ADS1220_CMD_RDATA; + t.length = 4 * 8; // Command is 24 bits + ret = spi_device_polling_transmit(spi2, &t); // Transmit! + assert(ret == ESP_OK); + Val = (t.rx_data[1] << 16) | (t.rx_data[2] << 8) | t.rx_data[3]; + if (Val & 0x800000) + { + Val |= 0xFF000000; + } + return Val; +} +// ADS1220д�Ĵ��� +void ADS1220_WriteReg(u8 reg, u8 dat) +{ + esp_err_t ret; + spi_transaction_t t; + memset(&t, 0, sizeof(t)); // Zero out the transaction + t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; + // t.flags = SPI_TRANS_USE_TXDATA; + t.tx_data[0] = ADS1220_CMD_WREG | ((reg & 0x03) << 2); + t.tx_data[1] = dat; + t.length = 2 * 8; // Command is 16 bits + ret = spi_device_polling_transmit(spi2, &t); // Transmit! + assert(ret == ESP_OK); +} + +// ADS1220д���� +void ADS1220_WriteCommand(u8 cmd) +{ + + esp_err_t ret; + spi_transaction_t t; + memset(&t, 0, sizeof(t)); // Zero out the transaction + t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; + t.length = 8 * 2; // Command is 8 bits + t.tx_data[0] = cmd; // The data is the cmd itself + // ESP_LOGI(TAG, "spi_device_polling_transmit befor.\n"); + ret = spi_device_polling_transmit(spi2, &t); // Transmit! + // ESP_LOGI(TAG, "spi_device_polling_transmit after.\n"); + assert(ret == ESP_OK); + // // ADS1220_CS=0; + // ADS1220_nCS_LOW(); + // ADS1220_ReadWriteByte(cmd); + // // ADS1220_CS=1; + // ADS1220_nCS_HIGH(); +} + +// ADS1220�������ģʽ +void ADS1220_PowerDown(void) +{ + ADS1220_WriteCommand(ADS1220_CMD_POWERDOWN); // +} + +// ADS1220����ת�� +void ADS1220_StartConv(u8 channal) +{ + /* + u8 val ; + val = ADS1220_ReadReg(ADS1220_REG0); + + ADS1220.CurrentCH = ADS1220_Channal1; + val = val & 0x0f | Channal1; + ADS1220_WriteReg(ADS1220_REG0, val ); // �Ĵ���0 ����: AIN P = AIN0, AIN N = AIN1 ���ģʽ ʹ��PGA 64 (110) ����PGA (0) + */ + ADS1220_WriteCommand(ADS1220_CMD_START); // ����ת�� +} + +// ADS1220��λ +void ADS1220_Reset(void) +{ + ADS1220_WriteCommand(ADS1220_CMD_RESET); // ��λADS1220 +} + +// ADS1220 PGA���� +void ADS1220_PGASet(u8 gain) +{ + u8 val; + val = ADS1220_ReadReg(ADS1220_REG0); + val = (val & 0xF1) | gain; + + ADS1220_WriteReg(ADS1220_REG0, val); + // val = ADS1220_ReadReg(ADS1220_REG0); + ADS1220_StartConv(ADS1220_Channal1); // ����ת�� +} +// static uint8_t dara_rate = 0x40; +void ADS1220_Config(void) +{ + static uint8_t read[4]; + ADS1220_WriteCommand(ADS1220_CMD_RESET); // ��λADS1220 + vTaskDelay(10); + // ESP_LOGI(TAG, "ADS1220_WriteCommand.\n"); + ADS1220_WriteReg(ADS1220_REG0, 0xa0); // �Ĵ���0 ����: ����: AIN P = AIN0, AIN N = AVSS ����ģʽ ʹ��PGA1 (100) ����PGA(0) + + ADS1220_WriteReg(ADS1220_REG1, 0x20); // �Ĵ���1 ����: Turboģʽ 40.SPS(00000)��ʹ���¶ȴ�����(0) �رյ������(0) + + ADS1220_WriteReg(ADS1220_REG2, 0x20); // �Ĵ���2 ����: ��ѹ��׼ �ڲ�2.048-v�ο�(00) ʹ��оƬFIR�˲�50Hz(10) ����Դ0ma // Low-side��Դ���� Ĭ��(0) ����Դ �ر� + ADS1220_WriteReg(ADS1220_REG3, 0x00); // �Ĵ���3 ����: : IDAC1 connect to AIN2 : IDAC2 disabled + + read[0] = ADS1220_ReadReg(ADS1220_REG0); + read[1] = ADS1220_ReadReg(ADS1220_REG1); + read[2] = ADS1220_ReadReg(ADS1220_REG2); + read[3] = ADS1220_ReadReg(ADS1220_REG3); + printf("ads1220 reg %02x %02x %02x %02x \n", read[0], read[1], read[2], read[3]); +} + +static void SPI2_Init(void) +{ + esp_err_t ret; + + spi_bus_config_t buscfg2 = { + .miso_io_num = SPI2_PIN_NUM_MISO, + .mosi_io_num = SPI2_PIN_NUM_MOSI, + .sclk_io_num = SPI2_PIN_NUM_CLK, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 8}; + + spi_device_interface_config_t devcfg2 = { + .clock_speed_hz = 1 * 1000 * 1000, // Clock out at 1 MHz + .mode = 0, // SPI mode 0 + .cs_ena_posttrans = 2, // Keep the CS low 2 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than SPI CLK + .spics_io_num = SPI2_PIN_NUM_CS, // CS pin + .queue_size = 1, // We want to be able to queue 7 transactions at a time + // .address_bits = 8, + // .pre_cb = lcd_spi_pre_transfer_callback, // Specify pre-transfer callback to handle D/C line + // .command_bits = 8, + }; + // Initialize the SPI bus + ret = spi_bus_initialize(ADS1220_HOST, &buscfg2, SPI_DMA_CH_AUTO); + ESP_ERROR_CHECK(ret); + // Attach the ADS1220 to the SPI bus + ret = spi_bus_add_device(ADS1220_HOST, &devcfg2, &spi2); + ESP_ERROR_CHECK(ret); +} + +extern void zero_totalflow(int ch); + +extern int zero_totalflow_req; +extern int abs_sub(uint32_t enc_update_time, uint32_t _enc_update_time); +extern cal_4_20ma_t *cal_4_20ma; +extern flow_config_t *flow_config; +extern flow_t *pflow; +extern int flow_rem[2]; + +void ads1220_task(void) +{ + uint32_t io_num; + // static uint32_t ad_flow_tick = 10; + while (1) + { + // ESP_LOGI(TAG, "xQueueReceive before\n "); + if (xQueueReceive(ads1220_drdy_queue, &io_num, 200)) + { + int ad_ch; + int ad_raw = ADS1220_ReadData(); + // if (ch == 3) + // ESP_LOGI(TAG, "ads1220 ch3 ad_rad:%d", (int)ad_raw); + ad_value[ch] = ad_raw / 128; + ad_ch = ch; + gWordVar[AD_RAW_REG_ADDR + ch] = ad_value[ch] / 2; + // ESP_LOGI(TAG, "channel : %d ad_value: %d\n ", ch, ad_value[ch]); + ch++; + if (ch >= sizeof(ch_cmd)) + { + ch = 0; + } + ADS1220_WriteReg(ADS1220_REG0, ch_cmd[ch]); + ADS1220_WriteCommand(ADS1220_CMD_START); + if (ad_ch == 1) + LED_Toggle(LED2_GPIO_PIN); + int flow_ch = ad_ch / 2; + if ((ad_ch == 1 || ad_ch == 3) && flow_config->input_type == 1) + { + if ((depth_data->pile_work_state_and_direction & 0xff00) != PILE_STATE_WORK) + { + // ESP_LOGI(TAG, "not work"); + goto out; + } + int time_diff = abs_sub(ad_update_time[ad_ch], pflow[flow_ch].update_time); + ad_flow_cal_t *cal = flow_config->ad_cal; + int t_flow; // time_diff时间段总流量 + pflow[flow_ch].flow_ = scale(ad_value[ad_ch], cal_4_20ma->ch[flow_ch].ad_4ma, cal_4_20ma->ch[flow_ch].ad_20ma, cal[flow_ch].flow_min, cal[flow_ch].flow_max); + if (pflow[flow_ch].flow_ < flow_config->min_flow[flow_ch]) // 小流量切除 + { + pflow[flow_ch].flow = 0; + } + else + { + pflow[flow_ch].flow = pflow[flow_ch].flow_; + } + + if (pflow[flow_ch].update_time == 0) goto out; // 首次无法计算时间差 + // 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为1us + // flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s + // t_diff = time_diff / 1000 将时间差换算成秒 + // t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL + // 取出0.01L的整数部分累加,余数部分和下次值累加 + // t_flow = pflow[i].flow * 1000 * time_diff / 1000000 / 60; + int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000); + // if (ad_ch == 1) ESP_LOGI(TAG, "time_diff_us:%d", time_diff_us); + t_flow = pflow[flow_ch].flow * (long long)time_diff_us / 60 / 100; //(5 * 60); + // ESP_LOGI(TAG, "sub:%d total:%d", sub_flow, (int)pflow[flow_ch].total_flow); + flow_rem[flow_ch] += t_flow; + int sub_flow = flow_rem[flow_ch] / 10000; + // ESP_LOGI(TAG, "sub:%d total:%d", sub_flow, (int)pflow[flow_ch].total_flow); + pflow[flow_ch].total_flow += sub_flow; + flow_rem[flow_ch] = flow_rem[flow_ch] - sub_flow * 10000; +out: + pflow[flow_ch].update_time = ad_update_time[ad_ch]; + // if (ad_ch == 1) ESP_LOGI(TAG, "flow:%d total_flow:%d", (int)pflow[flow_ch].flow, (int)pflow[flow_ch].total_flow); + // ESP_LOGI(TAG, "(type1) flow_rem[%d].flow: %u time_diff=%d", flow_ch ,pflow[flow_ch].flow,time_diff); + // ESP_LOGI(TAG, "ads1220 ch:%d time_diff:%d flow:%d total_flow:%d", flow_ch, time_diff, pflow[flow_ch].flow, pflow[flow_ch].total_flow); + } + } + else + { + ESP_LOGI(TAG, "wait queue failed"); + ADS1220_Init(); + } + } +} + + +void zero_flow1(void) +{ + memset(pflow, 0, sizeof(flow_t) * 2); + for (int i = 0; i < 2; i++) + { + flow_rem[i] = 0; + } +} + +void ads1220_task_start(void) +{ + SPI2_Init(); + GPIO_Init(); + ADS1220_Init(); + xTaskCreate(ads1220_task, "ads1220_task", 4096, NULL, 10, NULL); +} + +// void ADS1220_set_rate(int i) +//{ +// switch (i) +// { +// case 1 :dara_rate = 0x00;//20SPS +// break; +// case 2 :dara_rate = 0x20;//45SPS +// break; +// case 3 :dara_rate = 0x40;//90SPS +// break; +// case 4 :dara_rate = 0x60;//175SPS +// break; +// default:dara_rate = 0x00;//20SPS +// break; +// } +// } + +// int ADS1220_get_rate(void) +//{ +// switch (dara_rate) +// { +// case 0x00 :return 20*100;//20SPS +// break; +// case 0x20 :return 45*100;//45SPS +// break; +// case 0x40 :return 90*100;//90SPS +// break; +// case 0x60 :return 175*100;//175SPS +// break; +// default:return 20*100;//20SPS +// break; +// } +// } +// ch0 0.5V 3478 +// ch0 1.0V 0 +// ch0 1.5V 10429 + +// ch1 4.000ma 12783 +// ch1 12.00ma 38349 + +// ch2 4.000ma 12764 +// ch2 12.00ma 38336 diff --git a/main/stm32/ads1220.h b/main/stm32/ads1220.h new file mode 100644 index 0000000..efb6f96 --- /dev/null +++ b/main/stm32/ads1220.h @@ -0,0 +1,110 @@ +#ifndef __ADS1220_H +#define __ADS1220_H +// #include "main.h" +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "driver/spi_master.h" +#include "driver/gpio.h" + +typedef uint8_t u8; +typedef uint32_t u32; +typedef int32_t s32; + + +#define ADS1220_HOST SPI2_HOST +#define SPI2_PIN_NUM_MISO 6 +#define SPI2_PIN_NUM_MOSI 5 +#define SPI2_PIN_NUM_CLK 16 +#define SPI2_PIN_NUM_CS 15 +#define PARALLEL_LINES 16 + +#define ADS1220_nCS_HIGH() gpio_set_level(GPIO_NUM_38, 1) +#define ADS1220_nCS_LOW() gpio_set_level(GPIO_NUM_38, 0) + +#define ADS1220_CMD_WREG 0x40 +#define ADS1220_CMD_RREG 0x20 +#define ADS1220_CMD_RESET 0x06 +#define ADS1220_CMD_START 0x08 +#define ADS1220_CMD_POWERDOWN 0x02 +#define ADS1220_CMD_RDATA 0x10 + +#define Channal1 0x00 +#define Channal2 0x10 +#define Channal3 0x20 +#define Channal4 0x30 + +#define ADS1220_REG0 0x00 +#define ADS1220_REG1 0x01 +#define ADS1220_REG2 0x02 +#define ADS1220_REG3 0x03 + +#define PGAGain1 0x00 +#define PGAGain2 0x02 +#define PGAGain4 0x04 +#define PGAGain8 0x06 +#define PGAGain16 0x08 +#define PGAGain32 0x0A +#define PGAGain64 0x0C +#define PGAGain128 0x0E + +#define ADS1220_Standby 0 +#define ADS1220_ConvStart 1 +#define ADS1220_ConvFinish 2 + +#define ADS1220_Channal1 0 +#define ADS1220_Channal2 1 +#define ADS1220_Channal3 2 +#define ADS1220_Channal4 3 + +#define GPIO_INPUT_IO_39 7 +#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO_39) +#define ESP_INTR_FLAG_DEFAULT 0 + + + +typedef struct +{ + + int ch0_4ma; + int ch0_12ma; + float ch0_4ma_yl; + float ch0_12ma_yl; + + int ch1_4ma; + int ch1_12ma; + float ch1_4ma_yl; + float ch1_12ma_yl; + + int ch2_4ma; + int ch2_12ma; + float ch2_4ma_yl; + float ch2_12ma_yl; +}ads_cali_t; + +//extern ads_cali_t ads_cali; + + +uint32_t get_now_20us(void); +int32_t tim_diff(uint32_t a,uint32_t b); +int ADS1220_get_rate(void); +void ADS1220_set_rate(int i); +void ADS1220_Init(void); // ADS1220��ʼ�� +void ADS1220_Config(void); // ADS1220���� +void ADS1220_StartConv(u8 channal); // ADS1220����ת�� +void ADS1220_Reset(void); // ADS1220��λ +void ADS1220_PowerDown(void); // ADS1220�������ģʽ +void ADS1220_PGASet(u8 gain); // ADS1220 PGA���� +void ADS1220_WriteCommand(u8 cmd); // ADS1220д���� +s32 ADS1220_ReadData(void); // ADS1220������ +void ADS1220_WriteReg(u8 reg,u8 dat); // ADS1220д�Ĵ��� +u8 ADS1220_ReadReg(u8 reg); // ADS1220���Ĵ��� +u8 ADS1220_ReadWriteByte(u8 dat); // ��SPI������д��һ�ֽ� +u32 ADS1220_ReadWrite24Bits(u32 dat); // ��ADS1220������д��24Bits + +void zero_flow1(void); +int scale(int raw, int raw_min, int raw_max,int eng_min, int eng_max); +#endif diff --git a/main/peripheral/bl0939.c b/main/stm32/bl0939.c similarity index 92% rename from main/peripheral/bl0939.c rename to main/stm32/bl0939.c index 1aa47ed..3a7d68d 100644 --- a/main/peripheral/bl0939.c +++ b/main/stm32/bl0939.c @@ -1,3 +1,11 @@ +#include "bl0939.h" +#include "string.h" +#include "utils.h" +// #include "ModbusS.h" +#include "config.h" + +#include +#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -5,16 +13,21 @@ #include "driver/spi_master.h" #include "driver/gpio.h" #include "esp_log.h" - -#include "bl0939.h" -#include "depth.h" -#include "gwordvar.h" -#include "utils.h" +#include "pile_id.h" #define TAG "BL0939" +#define BL0939_HOST SPI3_HOST + +#define SPI1_PIN_NUM_MISO 37 +#define SPI1_PIN_NUM_MOSI 36 +#define SPI1_PIN_NUM_CLK 35 +#define SPI1_PIN_NUM_CS 40 + + +extern move_t *pMoveCtx; + static spi_device_handle_t spi1; -move_t *pMoveCtx = (move_t *)&gWordVar[MOVE_REG_ADDR]; static void SPI1_Init(void) { @@ -241,11 +254,13 @@ void BL0939_task() } if (gWordVar[AC_CURRENT_REG_ADDR + move_current_channel] > depth_config->current_on_threshold) { - if (++pMoveCtx->time_count > depth_config->move_on_duratino) + if (++pMoveCtx->time_count > depth_config->move_on_duratino) // 时间单位和采样时间有关,100ms { pMoveCtx->status = 1; pMoveCtx->time_count = 0; + pMoveCtx->work_time = 0; pMoveCtx->pile_inc_req = 1; + pMoveCtx->work_stop_state_flag = 0; // ESP_LOGI(TAG, "cur > th, status trun to on"); } @@ -254,18 +269,22 @@ void BL0939_task() else if (pMoveCtx->status == 1) { // ESP_LOGI(TAG, "mov status is on"); + pMoveCtx->work_time++; int move_current_channel = depth_config->move_current_channel; if (move_current_channel > 2 || move_current_channel < 0) { move_current_channel = 2; } - if (gWordVar[AC_CURRENT_REG_ADDR + 2] < depth_config->current_off_threshold) + if (gWordVar[AC_CURRENT_REG_ADDR + move_current_channel] < depth_config->current_off_threshold) { if (++pMoveCtx->time_count > depth_config->move_off_duration) { pMoveCtx->status = 0; pMoveCtx->time_count = 0; - + if (pMoveCtx->work_time >= CURRENT2_TIMEOUT_TH) + { + pMoveCtx->work_stop_state_flag = 1; + } // ESP_LOGI(TAG, "cur > th, status trun to off"); } } diff --git a/main/stm32/bl0939.h b/main/stm32/bl0939.h new file mode 100644 index 0000000..bc25657 --- /dev/null +++ b/main/stm32/bl0939.h @@ -0,0 +1,31 @@ +#ifndef BL0939_H__ +#define BL0939_H__ + + + +// #include "main.h" +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "driver/spi_master.h" +#include "driver/gpio.h" + + + +void bl0939_reset(void); +int bl0939_get_current_A(void); +int bl0939_get_current_B(void); +int bl0939_get_voltage(void); + +//DMA +void bl0939_get_abv(uint8_t * buf); +int bl0939_parse_abv(uint8_t * buf,unsigned int * data); + + +#endif + + + diff --git a/main/stm32/capture.c b/main/stm32/capture.c new file mode 100644 index 0000000..3194dd3 --- /dev/null +++ b/main/stm32/capture.c @@ -0,0 +1,153 @@ +/* + +*/ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_log.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "driver/mcpwm.h" +#include "driver/gpio.h" + +const static char *TAG = "capture"; + +typedef struct capture_event +{ + int ch; + uint32_t val; +} capture_event_t; + +#define FLOW1_PIN_ECHO GPIO_NUM_39 // 捕获GPIO端口 +#define FLOW2_PIN_ECHO GPIO_NUM_38 // 捕获GPIO端口 + +#define TRIGGER_THREAD_PRIORITY 5 + +typedef struct +{ + uint32_t capture_signal; + mcpwm_capture_signal_t sel_cap_signal; +} capture; + +static uint32_t cap_val_begin_of_flow1 = 0; +static uint32_t cap_val_end_of_flow1 = 0; +static uint32_t cap_val_begin_of_flow2 = 0; +static uint32_t cap_val_end_of_flow2 = 0; + +// static xQueueHandle cap_queue; +extern uint32_t rtc_clk_apb_freq; +uint32_t volatile t15_ccr[2]; +uint16_t volatile t15_ccr_times[2]; + +static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, + void *arg) +{ + // calculate the interval in the ISR, + // so that the interval will be always correct even when cap_queue is not handled in time and overflow. + BaseType_t high_task_wakeup = pdFALSE; + + cap_val_end_of_flow1 = edata->cap_value; + capture_event_t cap_event = {.val = 0, .ch = 1}; + cap_event.val = cap_val_end_of_flow1 - cap_val_begin_of_flow1; + t15_ccr_times[0] = cap_event.val * (1000000.0 / rtc_clk_apb_freq); + t15_ccr[0]++; + return high_task_wakeup == pdTRUE; +} + +void capture_flow1_init() +{ + ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO)); + // enable pull down CAP0, to reduce noise + ESP_ERROR_CHECK(gpio_pullup_en(FLOW1_PIN_ECHO)); + // enable both edge capture on CAP0 + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_NEG_EDGE, + .cap_prescale = 1, + .capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数 + .user_data = NULL}; + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf)); + mcpwm_set_frequency(MCPWM_UNIT_1, MCPWM_TIMER_1, 1000000); + int value = mcpwm_capture_signal_get_value(MCPWM_UNIT_1, MCPWM_SELECT_CAP1); + ESP_LOGI(TAG, "capture_flow_init value=%d", value); +} + +static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, + void *arg) +{ + // calculate the interval in the ISR, + // so that the interval will be always correct even when cap_queue is not handled in time and overflow. + BaseType_t high_task_wakeup = pdFALSE; + + cap_val_end_of_flow2 = edata->cap_value; + capture_event_t cap_event = {.val = 0, .ch = 2}; + cap_event.val = cap_val_end_of_flow2 - cap_val_begin_of_flow2; + t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq); + t15_ccr[1]++; + // send measurement back though queue + // xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup); + + return high_task_wakeup == pdTRUE; +} + +void capture_flow2_init() +{ + ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO)); + // enable pull down CAP0, to reduce noise + ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO)); + // enable both edge capture on CAP0 + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_NEG_EDGE, + .cap_prescale = 1, + .capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数 + .user_data = NULL}; + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf)); + mcpwm_set_frequency(MCPWM_UNIT_1, MCPWM_TIMER_2, 1000000); + // ESP_LOGI(TAG, "capture_flow_init"); +} + +// void capture_task(void) +// { +// while (true) { +// capture_event_t cap_event = {.val = 0, .ch = 1}; +// uint32_t pulse_width_us = 0; +// // block and wait for new measurement +// // ESP_LOGI(TAG, "xQueueReceive started"); +// xQueueReceive(cap_queue, &cap_event, portMAX_DELAY); +// // ESP_LOGI(TAG, "xQueueReceive after"); +// // ESP_LOGI(TAG, " cap_event.val: %d, cap_event.ch : %d", cap_event.val, cap_event.ch); +// switch (cap_event.ch) +// { +// case 1: //flow1 capture +// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq); + +// ESP_LOGI(TAG, " (flow1 capture) Pulse width: %uus", pulse_width_us); +// break; +// case 2: //flow2 capture +// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq); +// ESP_LOGI(TAG, "(flow2 capture) Pulse width: %uus", pulse_width_us); +// break; +// default: ESP_LOGI(TAG, " default\n"); +// break; +// } +// } +// } + +// void capture_depth_init(); +// void pcnt_rotary_encoder_init(void); +void capture_init(void) +{ + // cap_queue = xQueueCreate(3, sizeof(capture_event_t)); + // if (cap_queue == NULL) { + // ESP_LOGE(TAG, "failed to alloc cap_queue"); + // return; + // } + + // capture_depth_init(); + capture_flow1_init(); + capture_flow2_init(); + // start gcapture_task + // xTaskCreate(capture_task, "capture_task", 4096, NULL, TRIGGER_THREAD_PRIORITY, NULL); + // ESP_LOGI(TAG, "capture_task started"); + // pcnt_rotary_encoder_init(); +} diff --git a/main/stm32/comm.c b/main/stm32/comm.c new file mode 100644 index 0000000..a2d0f71 --- /dev/null +++ b/main/stm32/comm.c @@ -0,0 +1,104 @@ +#include "stdlib.h" +#include "utils.h" +#include "fram.h" +#include "ModbusS.h" +#include "ads1220.h" +// #include "SEGGER_RTT.h" +#include "ModbusM.h" + +extern void modbus_master_poll(int n); +extern int modbus_master_on_revice(int ch, uint8_t *rxbuf, int length); + +extern uint8_t uart1_txbuf[]; +extern uint8_t uart1_rxbuf[]; + +extern uint8_t uart2_txbuf[]; +extern uint8_t uart2_rxbuf[]; + +extern int uart1_rx_start(void); +extern int uart1_rx_check(void); +extern int uart1_tx_start(uint8_t *data, int length); + + +extern int uart2_rx_start(void); +extern int uart2_rx_check(void); +extern int uart2_tx_start(uint8_t *data, int length); + +void RS485_init(); +void print_init(); + +extern uint8_t led_toggle_count; + + + +void comm_poll(void) +{ + + static uint32_t modbus_master_tick = 0; + static uint32_t tick_100ms = 0; + static int uart1_timeout = 0; + static int uart2_timeout = 0; + int rxlen,txlen; +// if((rxlen = uart1_rx_check()) > 0){ +// txlen = ModbusSlaveProcess(uart1_txbuf,uart1_rxbuf,rxlen,1); +// if(txlen > 0) +// { +// HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); +// uart1_tx_start(uart1_txbuf,txlen); +// } +// else{ +// uart1_rx_start(); +// } +// } + if((rxlen = uart2_rx_check()) > 0){ + + txlen = ModbusSlaveProcess(uart2_txbuf,uart2_rxbuf,rxlen,1); + if(txlen > 0) + { + uart2_tx_start(uart2_txbuf,txlen); + } + else{ + uart2_rx_start(); + } + led_toggle_count = 0; + uart1_timeout = 0; + } + if(TickDiff(tick_100ms) > 100) + { + tick_100ms = xTaskGetTickCount(); + if(++uart1_timeout > 100){ + uart1_timeout = 0; +// HAL_UART_MspDeInit(&huart2); +// MX_USART2_UART_Init(); + uart2_rx_start(); + } + if(++uart2_timeout > 1000){ + uart2_timeout = 0; +// HAL_UART_MspDeInit(&huart1); +// MX_USART1_UART_Init(); + } + } + if(TickDiff(modbus_master_tick) > 10) + { + modbus_master_tick = xTaskGetTickCount(); + modbus_master_poll(0); + } + if((rxlen = uart1_rx_check()) > 0){ // 做一个uart1_rx_check 读串口 + modbus_master_on_revice(0,uart1_rxbuf,rxlen); + uart2_timeout = 0; + } +} + +void comm_init(void) +{ + // MX_USART1_UART_Init(); + // MX_USART2_UART_Init(); + RS485_init(); + print_init(); + ModbusM_init(); + uart2_rx_start(); +} + + + + diff --git a/main/peripheral/config/config.c b/main/stm32/config.c similarity index 74% rename from main/peripheral/config/config.c rename to main/stm32/config.c index 3c45d4b..1a82410 100644 --- a/main/peripheral/config/config.c +++ b/main/stm32/config.c @@ -1,20 +1,23 @@ -#include -#include "esp_log.h" - #include "config.h" #include "fram.h" -#include "flow.h" -#include "depth.h" +#include "utils.h" +#include "modbuss.h" +#include "stdint.h" +#include "esp_log.h" +// #include "flow.h" +// #include "depth.h" +// config_data_t * config_para = (config_data_t*)&gWordVar[256]; +// extern real_t * real; static const char *TAG = "config"; -extern cal_4_20ma_t *cal_4_20ma; //电流数据结构体 -extern flow_config_t *flow_config; //流量数据结构体 -extern depth_config_t *depth_config; //深度数据结构体 +extern cal_4_20ma_t *cal_4_20ma;//电流数据结构体 +extern flow_config_t *flow_config;//流量数据结构体 +extern depth_config_t *depth_config;//深度数据结构体 -extern float ac_current_coef[3]; //可能表示交流电电流的系数或校准参数 ? +extern float ac_current_coef[3];//可能表示交流电电流的系数或校准参数 ? // 三标一号机 -const cal_4_20ma_t default_cal_4_20ma = {0, {{12740, 63845}, {12760, 63953}}}; +const cal_4_20ma_t default_cal_4_20ma = {0, {{12740, 63845}, {12760, 63953}}}; const flow_config_t default_flow_cfg = {0, 1, {0, 0}, {{0, 10000}, {0, 10000}}, {6944, 6944}}; // 4~20MA 输入6m/H 100.00L/min /* const flow_config_t default_flow_cfg = { @@ -48,13 +51,46 @@ const depth_config_t default_depth_cfg = { .move_on_duratino = 150, .move_off_duration = 150, .move_current_channel = 2, -}; // 方向脉冲编码器 10线2倍频 + }; // 方向脉冲编码器 10线2倍频 // const depth_config_t default_depth_cfg = {0,3,0,3800,-200,16000,100,-200}; //200线开漏型正交 // const depth_config_t default_depth_cfg = {0,1,0,76000,-200,16000,100,-200}; +#define MAGIC 30627 +#define EE_CAL_4_20MA_ADDR 16 +#define EE_FLOW_CFG_ADDR (EE_CAL_4_20MA_ADDR + sizeof(default_cal_4_20ma)) +#define EE_DEPTH_CFG_ADDR (EE_FLOW_CFG_ADDR + sizeof(default_flow_cfg)) + +extern uint16_t *cur_pile_id; + +extern void init_comm(void); + +// void sys_init(void) +// { +// // HAL_Delay(100); +// // GetCompileDateTime(&gWordVar[0]); +// // flash_load(); +// // modbus_addr = config_para->modbus_addr; +// // sliding_window_filter_init(&sliding_window_a,real->data_long,200); +// // HAL_TIM_Base_Start(&htim6);//ms��ʱ�� +// // HAL_TIM_Base_Start_IT(&htim17);//us��ʱ�� +// //// HAL_TIM_Encoder_Start_IT(&htim1,TIM_CHANNEL_ALL);//enc +// // HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);//enc +// // HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);//ll +// // HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);//ll +// // HAL_TIM_IC_Start_IT(&htim15,TIM_CHANNEL_1);//ll +// // HAL_TIM_IC_Start_IT(&htim15,TIM_CHANNEL_2);//ll +// // HAL_UART_Receive_IT(&huart1,&temp_rx_data,1); +// // init_comm(); +// // if(config_para->traffic_mode == MA_4_20) +// // { +// // ADS1220_Init(); +// // } +// // HAL_GPIO_WritePin(GPS_PWR_EN_GPIO_Port, GPS_PWR_EN_Pin, GPIO_PIN_SET); +// // HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin,0); +// // HAL_Delay(500); +// } -uint16_t last_pile_id = 0; /*fram_read */ /* 通过 I2C 总线读取 ESP32 上连接的 FRAM(非易失性存储器)芯片中指定地址的数据 @@ -69,7 +105,7 @@ void config_load(void) { if (temp[0] == MAGIC) { - last_pile_id = temp[1]; + *cur_pile_id = temp[1]; } } fram_read(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma)); @@ -89,7 +125,6 @@ void config_load(void) } ESP_LOGW(TAG, "load flow_cfg:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", (unsigned int)flow_config->magic, (unsigned int)flow_config->input_type, (unsigned int)flow_config->min_flow[0], (unsigned int)flow_config->min_flow[1], (unsigned int)flow_config->ad_cal[0].flow_min, (unsigned int)flow_config->ad_cal[0].flow_max, (unsigned int)flow_config->ad_cal[1].flow_min, (unsigned int)flow_config->ad_cal[1].flow_max, (unsigned int)flow_config->pulse_coef[0], (unsigned int)flow_config->pulse_coef[1]); -#if 1 fram_read(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); if (depth_config->magic != MAGIC) { @@ -102,7 +137,14 @@ void config_load(void) (unsigned int)depth_config->sample_depth, (unsigned int)depth_config->depth_offset, (unsigned int)depth_config->min_valid_depth, \ (unsigned int)depth_config->inc_pile_depth, (unsigned int)depth_config->current_on_threshold, (unsigned int)depth_config->current_off_threshold, \ (unsigned int)depth_config->move_on_duratino, (unsigned int)depth_config->move_off_duration, (unsigned int)depth_config->move_current_channel); -#endif + + + // fram_read(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); + // if (depth_config->magic != MAGIC) + // { + // ESP_LOGW(TAG, "fram_read depth_config failed, use default value"); + // memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg)); + // } } //恢复默认配置 @@ -110,10 +152,10 @@ void restore_default(void) { memcpy(cal_4_20ma, &default_cal_4_20ma, sizeof(default_cal_4_20ma)); memcpy(flow_config, &default_flow_cfg, sizeof(default_flow_cfg)); - // memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg)); + memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg)); fram_write(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma)); fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg)); - // fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); + fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); } void save_cal_4_20ma(void) @@ -131,7 +173,6 @@ void save_flow_cfg(void) flow_config->magic = fram_write(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg)); } -#if 1 void save_depth_cfg(void) { ESP_LOGW(TAG, "save_depth_cfg: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", \ @@ -143,19 +184,9 @@ void save_depth_cfg(void) depth_config->magic = MAGIC; depth_config->magic = fram_write(EE_DEPTH_CFG_ADDR, depth_config, sizeof(default_depth_cfg)); } -#endif void save_pile_id(void) { - uint16_t temp[2] = {MAGIC, last_pile_id}; + uint16_t temp[2] = {MAGIC, *cur_pile_id}; fram_write(0, &temp, sizeof(temp)); } - -void config_init(void) -{ - ESP_ERROR_CHECK(i2c_master_init()); - restore_default(); - save_cal_4_20ma(); - save_flow_cfg(); - config_load();//读取保存在FRAM里的数据 -} diff --git a/main/stm32/config.h b/main/stm32/config.h new file mode 100644 index 0000000..dba4a49 --- /dev/null +++ b/main/stm32/config.h @@ -0,0 +1,196 @@ +#ifndef SYS_H__ +#define SYS_H__ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" + + +#define FLOW_REG_ADDR 0 +#define DEPTH_REG_ADDR 12 +#define AC_CURRENT_REG_ADDR 24 +#define MOVE_REG_ADDR 27 +#define TILT_SENSER_ADDR 30 +#define RECORD_REG_ADDR 32 + +#define TIME 264 + +#define CAL_4_20MA_ADDR 384 +#define FLOW_CONFIG_ADDR (CAL_4_20MA_ADDR + (sizeof(cal_4_20ma_t) + 15) / 16 * 8) +#define DEPTH_CONFIG_ADDR (FLOW_CONFIG_ADDR + (sizeof(flow_config_t) + 15) / 16 * 8) + +#define AD_RAW_REG_ADDR 444 +#define LAST_PILE_ID_ADDR 509 +#define DEPTH_RESET_ADDR 510 +#define REBOOT_REW_ADDR 511 + +#define REG_GPS_MESSAGE (512 + 48) +#define REG_GPS_WRITE_DATA (REG_GPS_MESSAGE + sizeof(gps_message_t)) + +// // GPS数据 +// typedef struct gps_message +// { +// uint8_t gps_status; // GPS定位状态 +// uint8_t gps_view; // GPS可视状态 +// uint8_t gps_use; // GPS使用状态 +// uint8_t reg[1]; // 保留 +// uint32_t utc; // utc时间 +// double x; // 大地平面坐标 +// double y; +// double dir; // 方向 +// double pitch; // 俯仰角 +// } gps_message_t; +// extern gps_message_t *gpsMessageP; + + +#define WRITE_DOWN_MAGIC 0x55BB // 控制gps采用参数进行运算 +#define WRITE_SAVE_MAGIC 0x55AA // 控制gps将参数保存成json文件,开机的时候自动加载 +typedef struct gps_write_data // addr 600 +{ + uint16_t magic; // 600 2 + uint16_t ellipsoidal_datum; // 椭圆基准 601 2 + uint8_t reg[4]; + + // 604 8 + int16_t x0; // 卫星接收器点坐标(坐标系以基站为原点建立) + int16_t y0; + int16_t x1; // 待求点坐标 + int16_t y1; + + // 608 16 + uint64_t central_meridian; // 中央子午线 + uint64_t elevation; // 投影高程 + + // 616 16 + int64_t dx; // x轴平移 + int64_t ax; // x轴旋转 + // 624 16 + int64_t dy; // y轴平移 + int64_t ay; // y轴旋转 + // 632 16 + int64_t dz; // z轴平移 + int64_t az; // z轴旋转 + // 640 8 + int64_t k; // 缩放比例 +} gps_write_data_t; +extern gps_write_data_t *gpsWriteDataP; + + +typedef struct +{ + uint16_t magic; + struct _ch + { + uint16_t ad_4ma; + uint16_t ad_20ma; + } ch[2]; +} cal_4_20ma_t; + +typedef struct +{ + int16_t flow_min; + int16_t flow_max; +} ad_flow_cal_t; //存储ad转换的最大流量和最小流量 + +typedef struct +{ + uint16_t magic; //可能是一个用于标识流量配置的特殊字段或标志? + uint16_t input_type; // 1 : 4~20ma 2: 0~3.6K + int16_t min_flow[2]; // 小流量切除 + ad_flow_cal_t ad_cal[2]; + uint16_t pulse_coef[2]; //可能代表了脉冲输出的系数或倍率? + uint16_t rsv[6]; //可能是预留给未来扩展使用的保留字段? +} flow_config_t; + +typedef struct +{ + uint16_t magic; + uint8_t input_type; // 0:正交 1:正交反向 2:方向脉冲 3:方向脉冲反向 + uint8_t port; // 编码器端口 + uint16_t N; //编码器系数分子 + uint16_t M; //编码器系数分母 + // int pluse_coef; // 脉冲系数0.001mm + int16_t min_depth; // 最小深度 mm + int16_t max_depth; // 最大深度 mm + int16_t sample_depth; // 采样深度 mm + int16_t depth_offset; // 默认深度偏移 + int16_t min_valid_depth; // 最小有效深度 + int16_t inc_pile_depth; // 允许换桩深度 + uint16_t current_on_threshold; // 行走电机开启电流 + uint16_t current_off_threshold; // 行走电机关闭电流 + uint16_t move_on_duratino; // 持续时间 + uint16_t move_off_duration; // 持续时间 + uint16_t move_current_channel; //行走电流通道 +} depth_config_t; + +typedef struct +{ + int16_t flow_; + int16_t flow; + int32_t total_flow; + uint32_t update_time; +} flow_t; + +typedef struct +{ + uint16_t status; // 0:未开始 1:开始 2:结束 + uint16_t time_count; // 持续时间 单位100ms + uint16_t work_time; // 行走的时间 + uint16_t work_stop_state_flag; + uint16_t pile_inc_req; +} move_t; + +typedef struct +{ + uint16_t pile_work_state_and_direction; // 12 + int16_t speed; // 13 + int16_t depth; // 14 + uint16_t sample_count; // 15 + uint16_t depth_flow[2]; // 16~17 + uint32_t last_total_flow[2]; // + int16_t depth_offset; // 22 + uint16_t one_pile_work_time;//23 系统工作时间 + // uint32_t update_time; + // int16_t tilt_x; + // int16_t tilt_y; + // uint16_t current1; + // uint16_t current2; + // uint16_t current3; +} depth_t; + + +typedef struct +{ + int16_t max_depth; + uint16_t pile_id; + uint16_t count; + // uint16_t work_time; + struct _item + { + int16_t speed; + int16_t depth; + int16_t flow[2]; + uint32_t total_flow[2]; + int16_t tilt_x; + int16_t tilt_y; + uint16_t current1; + uint16_t current2; + } item[10]; +} record_t; + +extern depth_config_t *depth_config; + + +void config_load(void); +void save_cal_4_20ma(void); +void save_flow_cfg(void); +void save_depth_cfg(void); +void restore_default(void); +void save_pile_id(void); + +#endif diff --git a/main/stm32/depth.c b/main/stm32/depth.c new file mode 100644 index 0000000..7c64805 --- /dev/null +++ b/main/stm32/depth.c @@ -0,0 +1,1011 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_timer.h" +#include "stdlib.h" +#include "config.h" +#include "utils.h" +#include "ads1220.h" +#include "fram.h" +#include "ModbusM.h" +#include "ModbusS.h" +#include "depth.h" + +#include "rotary_encoder.h" +#include "esp_log.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "driver/mcpwm.h" +// #include "driver/mcpwm_prelude.h" +#include "config.h" +#include "../../../../components/bt/host/bluedroid/api/include/api/esp_gatts_api.h" +// #include "bt_server.h" +// #include "../ble_gatts_server.h" + +#include "esp_system.h" +#include "driver/uart.h" +#include "string.h" +#include "driver/gpio.h" + +#include +#include + +static const char *TAG = "depth"; + +typedef struct +{ + uint32_t capture_signal; + mcpwm_capture_signal_t sel_cap_signal; +} capture; + +typedef struct capture_event +{ + int ch; + uint32_t val; +} capture_event_t; + +// #define DEPTH_PIN_CLK GPIO_NUM_36 // 捕获GPIO端口 +// #define GPIO_PCNT_PIN_1 36 // Set GPIO 18 as phaseA/C1 +// #define GPIO_PCNT_PIN_2 35 // Set GPIO 19 as phaseB/C2 +// #define DEPTH_PIN_PULSE 36 //深度脉冲GPIO端口 +// #define DEPTH_PIN_CTRL 35 //深度控制GPIO端口 + +#define FLOW_SYNC_PIN 7 // 捕获GPIO端口 SPI2_nIRQ + +#define DEPTH_PIN_PULSE 39 // 深度脉冲GPIO端口 TIM15_CH1 +#define DEPTH_PIN_CTRL 38 // 深度控制GPIO端口 TIM15_CH2 +#define DEPTH_PIN_ENC_A 42 // 深度脉冲GPIO端口 TIM3_CH1 +#define DEPTH_PIN_ENC_B 41 // 深度控制GPIO端口 TIM3_CH2 +#define SEND_DATA_TEST 0 + +#define PILE_DIR_NONE 0x01 +#define PILE_DIR_UP 0x02 +#define PILE_DIR_DOWN 0x03 + +// #define DEPTH_PIN_ENC_A 36 // 深度脉冲GPIO端口 +// #define DEPTH_PIN_ENC_B 35 // 深度控制GPIO端口 + +void add_recod_item(void); + +extern int get_total_flow_by_time(int ch, uint32_t time); +extern void zero_totalflow(int ch); + +extern void reset_depth(void); +// extern esp_err_t ec11_pcnt_clear(pcnt_unit_t unit); + +void capture_depth_init(); +extern flow_t *pflow; +// extern uint16_t last_pile_id; +extern uint16_t *cur_pile_id; +uint32_t enc1_update_time; +uint32_t _enc1_update_time; +int32_t enc1_value; + +uint32_t enc2_update_time; +uint32_t _enc2_update_time; +int32_t enc2_value; + +extern rotary_encoder_t *encoder; + +// typedef struct +// { +// int16_t max_depth; +// uint16_t pile_id; +// uint16_t count; +// // uint16_t work_time; +// struct _item +// { +// int16_t speed; +// int16_t depth; +// int16_t flow[2]; +// uint32_t total_flow[2]; +// int16_t tilt_x; +// int16_t tilt_y; +// uint16_t current1; +// uint16_t current2; +// } item[10]; +// } record_t; + +// 18字节 +#pragma pack(1) +typedef struct +{ + uint8_t TAG; + int16_t speed; + int16_t depth; + int16_t flow[2]; + uint32_t total_flow[2]; + uint16_t current1; + uint16_t current2; +} send_to_bt_t1; + +// 16字节 +typedef struct +{ + uint8_t TAG; + uint8_t status; + uint8_t LAT[5]; + uint8_t LOG[5]; + int16_t ALT; // 海拔高度 + int16_t speed; + uint32_t UTC; + // uint16_t dir; + // uint16_t speed; + // int16_t tilt_x; + // int16_t tilt_y; +} position_t; + +typedef struct +{ + uint8_t TAG; + int16_t distence; + int16_t pitch; + int16_t azimuth; + int16_t tilt_x; + int16_t tilt_y; +}direction_t; + +typedef struct +{ + uint8_t TAG; + uint8_t status; + uint8_t LAT[5]; + uint8_t LOG[5]; + int16_t ALT; // 海拔高度 + int16_t speed; + uint32_t UTC; + // uint16_t dir; + // uint16_t speed; + // int16_t tilt_x; + // int16_t tilt_y; +} send_to_bt_t2; + +#pragma pack() + +// typedef struct +// { +// uint16_t pile_work_state_and_direction; // 12 +// int16_t speed; // 13 +// int16_t depth; // 14 +// uint16_t sample_count; // 15 +// uint16_t depth_flow[2]; // 16~17 +// uint32_t last_total_flow[2]; // +// int16_t depth_offset; // 22 +// uint16_t one_pile_work_time;//23 系统工作时间 +// // uint32_t update_time; +// // int16_t tilt_x; +// // int16_t tilt_y; +// // uint16_t current1; +// // uint16_t current2; +// // uint16_t current3; +// } depth_t; + +record_t *record = (record_t *)&gWordVar[RECORD_REG_ADDR]; +depth_t *depth_data = (depth_t *)&gWordVar[DEPTH_REG_ADDR]; +move_t *pMoveCtx = (move_t *)&gWordVar[MOVE_REG_ADDR]; +depth_config_t *depth_config = (depth_config_t *)&gWordVar[DEPTH_CONFIG_ADDR]; + +rotary_encoder_t *encoder = NULL; // 编码器测量深度参数 + +// static uint32_t cap_val_begin_of_depth = 0; +// static uint32_t cap_val_end_of_depth = 0; +// extern uint32_t rtc_clk_apb_freq; +/** + * @brief this is an ISR callback, we take action according to the captured edge + */ +static bool depth_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, + void *arg) +{ + + // 双边沿触发中断,只有一个边缘会更新值,所以只有在值发生变化时才更新时间 + int value = encoder->get_counter_value(encoder); + if (value != enc1_value) + { + enc1_value = value; + enc1_update_time = edata->cap_value; + } + return false; +} + +void capture_depth_init() +{ + int pulse_pin; + if (depth_config->port) + { + pulse_pin = DEPTH_PIN_ENC_A; + } + else + { + pulse_pin = DEPTH_PIN_PULSE; + } + ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, pulse_pin)); + // enable pull down CAP0, to reduce noise + ESP_ERROR_CHECK(gpio_pullup_en(pulse_pin)); + // enable both edge capture on CAP0 + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_NEG_EDGE, + .cap_prescale = 1, + .capture_cb = depth_isr_handler, // 绑定深度中断处理函数 + .user_data = NULL + }; + if (depth_config->input_type > 1) + { + conf.cap_edge = MCPWM_BOTH_EDGE; + } + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, &conf)); + ESP_LOGI(TAG, "capture_depth_init"); +} + +void pcnt_rotary_encoder_init(void) +{ + // Rotary encoder underlying device is represented by a PCNT unit in this example + uint32_t pcnt_unit = 0; + int pulse_pin; + int ctrl_pin; + if (depth_config->port) + { + pulse_pin = DEPTH_PIN_ENC_A; + ctrl_pin = DEPTH_PIN_ENC_B; + } + else + { + pulse_pin = DEPTH_PIN_PULSE; + ctrl_pin = DEPTH_PIN_CTRL; + } + // Create rotary encoder instance + rotary_encoder_config_t config = ROTARY_ENCODER_DEFAULT_CONFIG((rotary_encoder_dev_t)pcnt_unit, pulse_pin, ctrl_pin); + config.flags = depth_config->input_type; + ESP_ERROR_CHECK(rotary_encoder_new_ec11(&config, &encoder)); + // Filter out glitch (1us) + ESP_ERROR_CHECK(encoder->set_glitch_filter(encoder, 10)); + // Start encoder + ESP_ERROR_CHECK(encoder->start(encoder)); +} + +void depth_init(void) +{ + // if (depth_config->input_type == 1) + // { // 电压型 方向+脉冲信号 使用比较器通道,IO口中断方式采集 + + // // GPIO_InitTypeDef GPIO_InitStruct = {0}; + // // /*Configure GPIO pin : PtPin */ + // // GPIO_InitStruct.Pin = ROLLER_DIR_Pin; + // // GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + // // GPIO_InitStruct.Pull = GPIO_PULLUP; + // // HAL_GPIO_Init(ROLLER_GPIO_Port, &GPIO_InitStruct); + + // // /*Configure GPIO pin : PtPin */ + // // GPIO_InitStruct.Pin = ROLLER_CLK_Pin; + // // GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + // // GPIO_InitStruct.Pull = GPIO_PULLUP; + // // HAL_GPIO_Init(ROLLER_GPIO_Port, &GPIO_InitStruct); + // } + // else if (depth_config->input_type == 2) + // { // 电压型 正交编码器 使用比较器通道,TIM1编码器通道采集 + // MX_TIM1_Init(); + // pcnt_rotary_encoder_init(); // 编码器初始化 + // capture_depth_init(); + // HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL); + // } + // else if (depth_config->input_type == 3) + // { // 开漏输出 正交编码器 使用光耦输入通道,TIM3编码器通道采集 + // // MX_TIM3_Init(); + // // HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); + // } + depth_data->depth_offset = -depth_config->depth_offset; + depth_data->pile_work_state_and_direction = (PILE_STATE_STOP | PILE_DIR_NONE); // 默认不工作 +} + +enum +{ + REST = -1, + STOP = 0, + DOWN = 1, + UP = 2, +}; + +int last_enc_value = 0; +uint32_t _enc_update_time; +uint32_t enc_update_time; +int last_sample_depth = 0; +int last_flow[2] = {0}; +int16_t prev_depth = 0; +uint32_t prev_update_time = 0; +int16_t target_sample_depth = 0; + +// 正交编码器的深度 : encoder->get_counter_value(encoder) + +int abs_sub(uint32_t enc_update_time, uint32_t _enc_update_time) +{ + if (enc_update_time >= _enc_update_time) + { + return enc_update_time - _enc_update_time; + } + else + { + return (0xffffffff - _enc_update_time + enc_update_time + 1); + } +} + +send_to_bt_t1 send_to_bt1; +send_to_bt_t2 send_to_bt2; +extern bool is_connected; +// extern uint16_t spp_handle_table[IDX_NB]; +extern uint16_t spp_conn_id; +extern esp_gatt_if_t spp_gatts_if; +extern flow_t *pflow; +/*把两个结构体中的数据通过蓝牙发送*/ +void send_data_to_bt(void) +{ + +// #if SEND_DATA_TEST +// send_to_bt1.TAG = 1; +// send_to_bt1.speed = 2; +// send_to_bt1.depth = 3; +// send_to_bt1.tilt_x = 4; +// send_to_bt1.tilt_y = 5; +// send_to_bt1.current1 = 6; +// send_to_bt1.current2 = 7; + +// send_to_bt2.TAG = 2; +// send_to_bt2.flow[0] = 3; +// send_to_bt2.flow[1] = 4; +// send_to_bt2.total_flow[0] = 5; +// send_to_bt2.total_flow[1] = 6; +// ESP_LOGI(TAG, "set text data that send to bt\n"); +// #else +// ESP_LOGI(TAG, "use real time data that send to bt\n"); +// send_to_bt1.TAG = 1; +// send_to_bt1.tilt_x = (short)gWordVar[TILT_SENSER_ADDR]; +// send_to_bt1.tilt_y = (short)gWordVar[TILT_SENSER_ADDR + 1]; +// send_to_bt1.speed = depth_data->speed; +// send_to_bt1.depth = depth_data->depth; +// if (depth_config->move_current_channel == 2) +// { +// send_to_bt1.current1 = gWordVar[AC_CURRENT_REG_ADDR]; +// send_to_bt1.current2 = gWordVar[AC_CURRENT_REG_ADDR + 1]; +// } +// else if (depth_config->move_current_channel == 1) +// { +// send_to_bt1.current1 = gWordVar[AC_CURRENT_REG_ADDR]; +// send_to_bt1.current2 = gWordVar[AC_CURRENT_REG_ADDR + 2]; +// } +// else +// { +// send_to_bt1.current1 = gWordVar[AC_CURRENT_REG_ADDR + 1]; +// send_to_bt1.current2 = gWordVar[AC_CURRENT_REG_ADDR + 2]; +// } +// send_to_bt2.TAG = 2; +// send_to_bt2.flow[0] = pflow[0].flow; +// send_to_bt2.flow[1] = pflow[1].flow; +// send_to_bt2.total_flow[0] = pflow[0].total_flow; +// send_to_bt2.total_flow[1] = pflow[1].total_flow; +// #endif +// ESP_LOGI(TAG, "flow 1 :%d\n", send_to_bt2.flow[0]); +// ESP_LOGI(TAG, "flow 2 :%d\n", send_to_bt2.flow[1]); +// ESP_LOGI(TAG, "total_flow 1 :%d\n", send_to_bt2.total_flow[0]); +// ESP_LOGI(TAG, "total_flow 2 :%d\n", send_to_bt2.total_flow[1]); +// if (is_connected == true) +// { +// ESP_LOGI(TAG, "is connected\n"); +// esp_err_t err = esp_ble_gatts_send_indicate(spp_gatts_if, +// spp_conn_id, +// spp_handle_table[4], +// sizeof(send_to_bt1), +// (uint8 *)&send_to_bt1, +// false); +// if (err == ESP_OK) +// ESP_LOGI(TAG, "send data to bt 1 sucessfully\n"); +// else +// ESP_LOGI(TAG, "send data to bt 1 failed\n"); + +// err = esp_ble_gatts_send_indicate(spp_gatts_if, +// spp_conn_id, +// spp_handle_table[4], +// sizeof(send_to_bt2), +// (uint8 *)&send_to_bt2, +// false); +// if (err == ESP_OK) +// ESP_LOGI(TAG, "send data to bt 2 sucessfully\n"); +// else +// ESP_LOGI(TAG, "send data to bt 2 failed\n"); +// } +} + + +void calculate_depth_speed(int speed_enc_value) +{ + static int speed_last_enc_value = -1; + static int64_t speed_last_time = -1; + int64_t speed_time = esp_timer_get_time(); + + if (speed_last_enc_value == -1) // 第一次,记录值,并不计算 + { + goto exit; + } + + depth_data->speed = (speed_enc_value - speed_last_enc_value) * depth_config->N / depth_config->M * 600000ll / (speed_time - speed_last_time); + // ESP_LOGI(TAG, "speed:%d", depth_data->speed); +exit: + speed_last_enc_value = speed_enc_value; + speed_last_time = speed_time; +} + + +int last_depth_flag = 0; // 0小于允许换桩深度,1大于允许换桩深度 +int depth_over_inc_pile_flag = 0; // 深度过允许换桩深度标志 +/** + * _enc1_update_time 编码器1上一次更新时间 + * enc1_update_time 编码器1当前更新时间 + * time_diff 两次编码器更新时间的绝对差值 + * depth_config 预设好的深度数据 + * enc1_value 编码器1值,在深度中断中获得 + * prev_depth 上一次的深度 +*/ +void depth_task(void *arg) +{ + ESP_LOGI(TAG, "depth_task start\n"); + + int time_diff = 0; + int speed_calc_count = 0; + int enc_value = 0; + int64_t work_start_time = 0; + uint16_t last_work_state = 0; + + // depth_data->depth_offset = -depth_config->depth_offset; + depth_data->pile_work_state_and_direction = PILE_STATE_STOP; + last_work_state = PILE_STATE_STOP; + // record->pile_id = ++last_pile_id; + // record->pile_id = *cur_pile_id; + // send_to_bt1.pile_id = ++last_pile_id; + + // gWordVar[LAST_PILE_ID_ADDR] = last_pile_id; + + while (1) + { + depth_data->depth_offset = -depth_config->depth_offset; + record->pile_id = *cur_pile_id; + + if (_enc1_update_time != enc1_update_time) /* 深度数据更新 */ + { + // ESP_LOGI(TAG, "_enc1_update_time != enc1_update_time\n"); + enc_update_time = enc1_update_time; + enc_value = enc1_value; + time_diff = abs_sub(enc_update_time, _enc1_update_time); + _enc1_update_time = enc_update_time; + } + + if (time_diff != 0) + { + // ESP_LOGI(TAG, "time_diff = %d\n",time_diff); + int16_t depth = enc_value * depth_config->N / depth_config->M; // 1mm + depth_data->depth = depth - depth_data->depth_offset; + + /*深度补偿修正*/ + if (depth_data->depth > depth_config->max_depth) + { + // ESP_LOGI(TAG, "depth_data->depth > depth_config->max_depth\n"); + depth_data->depth_offset = depth - depth_config->max_depth; + depth_data->depth = depth_config->max_depth; + } + else if (depth_data->depth < depth_config->min_depth) + { + // ESP_LOGI(TAG, "depth_data->depth < depth_config->min_depth\n"); + depth_data->depth_offset = depth - depth_config->min_depth; + depth_data->depth = depth_config->min_depth; + } + + /*更新记录值*/ + if (depth_data->depth > record->max_depth) + { + // ESP_LOGI(TAG, "depth_data->depth > record->max_depth\n"); + record->max_depth = depth_data->depth; + // send_to_bt1.max_depth = depth_data->depth; + } + + // ESP_LOGI(TAG, "depth_data->depth:0x%x", (unsigned int)depth_data->depth); + + uint16_t pile_work_state = (depth_data->pile_work_state_and_direction & 0xff00); + if (pile_work_state == PILE_STATE_WORK) + { + // ESP_LOGI(TAG, "pile_work_state == PILE_STATE_WORK\n"); + /*如果机器从停止状态->工作状态,则重新记录工作开始时间*/ + if(last_work_state == PILE_STATE_STOP){ + work_start_time = esp_timer_get_time(); + depth_data->one_pile_work_time = 0; + } + int64_t current_work_time = esp_timer_get_time(); + if(work_start_time != 0){ + depth_data->one_pile_work_time = (uint16_t)((current_work_time - work_start_time)/1000000); // s + // ESP_LOGI(TAG, "time : %ud", (int)depth_data->one_pile_work_time); + } + + /*下钻,深度增加 计算采样深度流量*/ + if (enc_value > last_enc_value) + { + // ESP_LOGI(TAG, "enc_value > last_enc_value\n"); + uint8_t pile_work_dir = (depth_data->pile_work_state_and_direction & 0xff); + if(pile_work_dir != PILE_DIR_DOWN) + { + // 方向改变,更新目标采样深度 + depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_DOWN); + target_sample_depth = (depth_data->depth / depth_config->sample_depth) * depth_config->sample_depth; + + // 小于半个采样长度的合并到下一个采样点 + if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2) + { + target_sample_depth += depth_config->sample_depth; + } + } + + // 到达或超过目标采样点 + if (depth_data->depth >= target_sample_depth) + { + // 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点 + // 当使用10线编码器时每个脉冲深度达6.25cm,当采样间隔为10cm时抖动值太大 + if ((prev_depth - depth_data->depth) != 0) + { + int i; + //uint32_t time = (target_sample_depth - prev_depth) * (enc_update_time - prev_update_time) / (depth_data->depth - prev_depth) + prev_update_time; + for (i = 0; i < 2; i++) + { + // int total_flow = get_total_flow_by_time(i, time); + int total_flow = get_total_flow_by_time(i, pflow[i].update_time); + int flow = total_flow - depth_data->last_total_flow[i]; + if (flow < 0) + { + flow = 0; + } + depth_data->depth_flow[i] = flow; /* 采样深度对应的流量 */ + depth_data->last_total_flow[i] = total_flow; + } + depth_data->sample_count++; + target_sample_depth += depth_config->sample_depth; + add_recod_item(); + } + } + } + /*上钻,深度减少*/ + else if (enc_value < last_enc_value) + { + // ESP_LOGI(TAG, "enc_value < last_enc_value\n"); + uint8_t pile_work_dir = (depth_data->pile_work_state_and_direction & 0xff); + if (pile_work_dir != PILE_DIR_UP) + { + // 方向改变 + depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_UP); + target_sample_depth = (depth_data->depth / depth_config->sample_depth - 1) * depth_config->sample_depth; + + if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2) + { + // 小于半个采样长度的合并到下一个采样点 + target_sample_depth -= depth_config->sample_depth; + } + } + if (depth_data->depth <= target_sample_depth) + { + // 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点 + // 当使用10线编码器时每个脉冲深度达7.6cm,当采样间隔为10cm时抖动值太大 + if ((prev_depth - depth_data->depth) != 0) + { + int i; + //uint32_t time = (prev_depth - target_sample_depth) * (enc_update_time - prev_update_time) / (prev_depth - depth_data->depth) + prev_update_time; + for (i = 0; i < 2; i++) + { + // int total_flow = get_total_flow_by_time(i, time); + int total_flow = get_total_flow_by_time(i, pflow[i].update_time); + int flow = total_flow - depth_data->last_total_flow[i]; + if (flow < 0) + { + flow = 0; + } + depth_data->depth_flow[i] = flow; + depth_data->last_total_flow[i] = total_flow; + } + depth_data->sample_count++; + add_recod_item(); + target_sample_depth -= depth_config->sample_depth; + } + } + } + else + { + depth_data->pile_work_state_and_direction = ((depth_data->pile_work_state_and_direction & 0xff00) | PILE_DIR_NONE); + } + + if (last_depth_flag == 0 && depth_data->depth >= depth_config->inc_pile_depth) + { + depth_over_inc_pile_flag = 1; + } + + if (depth_data->depth < depth_config->inc_pile_depth) + { + last_depth_flag = 0; + } + else + { + last_depth_flag = 1; + } + + + // if (depth_data->depth < depth_config->inc_pile_depth) // 小于指定深度时才允许行走清零 + // { + // if (pMoveCtx->pile_inc_req == 1) + // { + // pMoveCtx->pile_inc_req = 0; + // reset_depth(); + // } + // } + // else + // { + // if (pMoveCtx->pile_inc_req == 1) + // { + // pMoveCtx->pile_inc_req = 0; + // } + // } + } + else if((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_PAUSE) + { + + } + else if((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_STOP) + { + work_start_time = 0; + } + last_work_state = pile_work_state; + prev_depth = depth_data->depth; + prev_update_time = enc_update_time; + last_enc_value = enc_value; + } + + vTaskDelay(pdMS_TO_TICKS(100)); + + // 500ms计算一次速度 + if (++speed_calc_count >= 5) + { + calculate_depth_speed(enc1_value); + speed_calc_count = 0; + } + } +} + +#if 0 +void depth_task(void *arg) +{ + ESP_LOGI(TAG, "go to depth_task sucessfully\n"); + // int enc_value; + int time_diff = 0; + int speed_timeout = 0; + int last_speed_enc_value = 0; // 上次速度计算的编码器值 + int speed_enc_update_time = 0; + int speed_calc_count = 0; + int enc_value = 0; + //int count = 0; + int bt_time_count = 0; + depth_data->depth_offset = -depth_config->depth_offset; + depth_data->up_down = 1; // 默认工作 + + record->pile_id = ++last_pile_id; + //send_to_bt1.pile_id = ++last_pile_id; + + gWordVar[LAST_PILE_ID_ADDR] = last_pile_id; + + /*获取当前时间*/ + uint16_t work_start_time = 0; + uint8_t is_work = 0; + + while (1) + { + if (_enc1_update_time != enc1_update_time) + { + ESP_LOGI(TAG, "_enc1_update_time != enc1_update_time\n"); + // int enc_update_time = enc1_update_time; + enc_update_time = enc1_update_time; + enc_value = enc1_value; + time_diff = abs_sub(enc_update_time, _enc1_update_time); + _enc1_update_time = enc_update_time; + } + + if (time_diff != 0) + { + ESP_LOGI(TAG, "time_diff = %d\n",time_diff); + int16_t depth = enc_value * depth_config->N / depth_config->M; // 1mm + depth_data->depth = depth - depth_data->depth_offset;//为什么要减去深度偏移 + + /*深度补偿修正*/ + if (depth_data->depth > depth_config->max_depth) + { + ESP_LOGI(TAG, "depth_data->depth > depth_config->max_depth\n"); + depth_data->depth_offset = depth - depth_config->max_depth; + depth_data->depth = depth_config->max_depth; + } + else if (depth_data->depth < depth_config->min_depth) + { + ESP_LOGI(TAG, "depth_data->depth < depth_config->min_depth\n"); + depth_data->depth_offset = depth - depth_config->min_depth; + depth_data->depth = depth_config->min_depth; + } + /*更新记录值*/ + if (depth_data->depth > record->max_depth) + { + ESP_LOGI(TAG, "depth_data->depth > record->max_depth\n"); + record->max_depth = depth_data->depth; + //send_to_bt1.max_depth = depth_data->depth; + } + + // 500ms计算一次速度 + if (speed_calc_count++ > 50) + { + ESP_LOGI(TAG, "speed_calc_count++ > 50\n"); + speed_calc_count = 0; + int speed_time_diff = abs_sub(enc_update_time, speed_enc_update_time); + int time_diff_us = speed_time_diff / (APB_CLK_FREQ / 1000000); + if (time_diff_us > 0 && time_diff_us < 5000000) + { + ESP_LOGI(TAG, "time_diff_us:%d,dist_diff=%d", time_diff_us, enc_value - last_speed_enc_value); + // speed = dist_diff / speed_time_diff speed 单位mm/min dist_diff 单位mm speed_time_diff 单位us + depth_data->speed = (enc_value - last_speed_enc_value) * depth_config->N / depth_config->M * 600000ll / time_diff_us; + speed_timeout = 0; + speed_enc_update_time = enc_update_time; + last_speed_enc_value = enc_value; + } + else + { + if (++speed_timeout > 10) + { + depth_data->speed = 0; + speed_timeout = 0; + speed_enc_update_time = enc_update_time; + last_speed_enc_value = enc_value; + } + } + } + + if (depth_data->up_down > STOP) + { + is_work ++; + if(is_work == 1){ + int64_t time = esp_timer_get_time(); + if(time < 0){ + work_start_time = 0; + } + work_start_time = (uint16_t)(time/1000000); + depth_data->one_pile_work_time = 0; + } + else{ + int64_t time = esp_timer_get_time(); + if(time > 0){ + if((uint16_t)(time/1000000) > work_start_time){ + depth_data->one_pile_work_time = ((uint16_t)(time/1000000) - work_start_time); + } + } + } + + ESP_LOGI(TAG, "depth_data->up_down > STOP\n"); + // 下钻,深度增加 + if (enc_value > last_enc_value) + { + if (depth_data->up_down != 1) + { + // 方向改变,更新目标采样深度 + depth_data->up_down = 1; + target_sample_depth = (depth_data->depth / depth_config->sample_depth) * depth_config->sample_depth; + + // 小于半个采样长度的合并到下一个采样点 + if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2) + { + target_sample_depth += depth_config->sample_depth; + } + } + + // 到达或超过目标采样点 + if (depth_data->depth >= target_sample_depth) + { + // 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点 + // 当使用10线编码器时每个脉冲深度达6.25cm,当采样间隔为10cm时抖动值太大 + if ((prev_depth - depth_data->depth) != 0) + { + int i; + // uint32_t time = (target_sample_depth - prev_depth) * (enc_update_time - prev_update_time) / (depth_data->depth - prev_depth) + prev_update_time; + for (i = 0; i < 2; i++) + { + // int total_flow = get_total_flow_by_time(i, time); + int total_flow = get_total_flow_by_time(i, pflow[i].update_time); + int flow = total_flow - depth_data->last_total_flow[i]; + if (flow < 0) + { + flow = 0; + } + depth_data->depth_flow[i] = flow; + depth_data->last_total_flow[i] = total_flow; + } + depth_data->sample_count++; + target_sample_depth += depth_config->sample_depth; + add_recod_item(); + } + } + } + else if (enc_value < last_enc_value) + { + if (depth_data->up_down != 2) + { // 方向改变 + depth_data->up_down = 2; + // target_sample_depth -= depth_config->sample_depth; + target_sample_depth = (depth_data->depth / depth_config->sample_depth - 1) * depth_config->sample_depth; + if (abs(depth_data->depth - target_sample_depth) < depth_config->sample_depth / 2) + { // 小于半个采样长度的合并到下一个采样点 + target_sample_depth -= depth_config->sample_depth; + } + } + if (depth_data->depth <= target_sample_depth) + { + // 由于编码器精度问题不能确保数据在采样点上,需要通过插值计算采样点 + // 当使用10线编码器时每个脉冲深度达7.6cm,当采样间隔为10cm时抖动值太大 + if ((prev_depth - depth_data->depth) != 0) + { + int i; + // uint32_t time = (prev_depth - target_sample_depth) * (enc_update_time - prev_update_time) / (prev_depth - depth_data->depth) + prev_update_time; + for (i = 0; i < 2; i++) + { + // int total_flow = get_total_flow_by_time(i, time); + int total_flow = get_total_flow_by_time(i, pflow[i].update_time); + int flow = total_flow - depth_data->last_total_flow[i]; + if (flow < 0) + { + flow = 0; + } + depth_data->depth_flow[i] = flow; + depth_data->last_total_flow[i] = total_flow; + } + depth_data->sample_count++; + add_recod_item(); + target_sample_depth -= depth_config->sample_depth; + } + } + } + else + { + // depth_data->up_down = 0; + } + + if (depth_data->depth < depth_config->inc_pile_depth) // 小于指定深度时才允许行走清零 + { + if (pMoveCtx->pile_inc_req == 1) + { + pMoveCtx->pile_inc_req = 0; + reset_depth(); + } + } + else + { + if (pMoveCtx->pile_inc_req == 1) + { + pMoveCtx->pile_inc_req = 0; + } + } + } + else{ + is_work = 0; + depth_data->one_pile_work_time = 0; + } + prev_depth = depth_data->depth; + prev_update_time = enc_update_time; + last_enc_value = enc_value; + } + //////////////////////////////////////////////////////////////////// + // 每隔500ms向蓝牙发送一次数据 + if (bt_time_count++ > 50) + { + ESP_LOGI(TAG, "bt_time_count++ > 50\n"); + bt_time_count = 0; + send_data_to_bt(); + } + //////////////////////////////////////////////////////////////////// + // if (++count > 100) + // { + // count = 0; + // ESP_LOGI(TAG, "encoder:%d", encoder->get_counter_value(encoder)); + // } + vTaskDelay(10); + } +} +#endif +void add_recod_item(void) +{ + // 每10cm计算一次 + record->count = depth_data->sample_count; + // ESP_LOGI(TAG, "add_recod_item:id:%d count:%d", record->pile_id, record->count); + memmove(&record->item[1], &record->item[0], sizeof(record->item[0]) * 9); + record->item[0].flow[0] = depth_data->depth_flow[0]; + record->item[0].flow[1] = depth_data->depth_flow[1]; + record->item[0].total_flow[0] = depth_data->last_total_flow[0]; + record->item[0].total_flow[1] = depth_data->last_total_flow[1]; + + if (depth_config->move_current_channel == 2) // 1 + { + record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR]; + record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 1]; + } + else if (depth_config->move_current_channel == 1) + { + record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR]; + record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 2]; + } + else + { + record->item[0].current1 = gWordVar[AC_CURRENT_REG_ADDR + 1]; + record->item[0].current2 = gWordVar[AC_CURRENT_REG_ADDR + 2]; + } + + record->item[0].tilt_x = (short)gWordVar[TILT_SENSER_ADDR]; + record->item[0].tilt_y = (short)gWordVar[TILT_SENSER_ADDR + 1]; + + record->item[0].speed = depth_data->speed; // 每500ms计算一次 + record->item[0].depth = depth_data->depth; // 每10ms计算一次 +} +extern int zero_totalflow_req; +extern void save_pile_id(void); +// void reset_depth(void) +// { +// // uint16_t pile_id; +// last_sample_depth = 0; +// last_flow[0] = 0; +// last_flow[1] = 0; +// prev_depth = 0; +// prev_update_time = 0; +// target_sample_depth = 0; +// zero_totalflow_req = 1; +// if (record->count > 0) +// { +// record->count = 0; +// memset(record->item, 0, sizeof(record->item)); +// } +// memset(depth_data, 0, sizeof(*depth_data)); +// if (record->max_depth >= depth_config->min_valid_depth) // 上一个桩有一定深度数据 +// { +// save_pile_id(); +// last_pile_id++; +// gWordVar[LAST_PILE_ID_ADDR] = last_pile_id; +// } +// memset(record, 0, sizeof(*record)); +// record->pile_id = last_pile_id; +// // ec11_pcnt_clear(0); +// depth_data->depth_offset = -depth_config->depth_offset; +// depth_data->depth = depth_config->depth_offset; +// enc1_value = 0; +// enc1_update_time = 0; +// depth_data->pile_work_state_and_direction = PILE_STATE_STOP | PILE_DIR_NONE; // 默认不工作 +// } + +void zero_depth(void) +{ + prev_depth = 0; + prev_update_time = 0; + target_sample_depth = 0; + + // depth_data->depth = 0; + depth_data->depth_flow[0] = 0; + depth_data->depth_flow[1] = 0; + depth_data->last_total_flow[0] = 0; + depth_data->last_total_flow[1] = 0; + depth_data->one_pile_work_time = 0; + depth_data->sample_count = 0; + depth_data->speed = 0; + + memset(record, 0, sizeof(*record)); + // enc1_value = 0; + // enc1_update_time = 0; +} + + +void DEPTH_init() +{ + + // depth_init(); + + pcnt_rotary_encoder_init(); + capture_depth_init(); + xTaskCreate(depth_task, "depth_task", 4096, NULL, 10, NULL); +} diff --git a/main/stm32/depth.h b/main/stm32/depth.h new file mode 100644 index 0000000..b33a20d --- /dev/null +++ b/main/stm32/depth.h @@ -0,0 +1,14 @@ +#ifndef __DEPTH_H +#define __DEPTH_H + +#include "config.h" + +#define PILE_STATE_STOP 0x0100 +#define PILE_STATE_PAUSE 0x0200 +#define PILE_STATE_WORK 0x0300 + +extern depth_t *depth_data; + +void zero_depth(void); + +#endif \ No newline at end of file diff --git a/main/stm32/flow.c b/main/stm32/flow.c new file mode 100644 index 0000000..9a6f0cc --- /dev/null +++ b/main/stm32/flow.c @@ -0,0 +1,334 @@ +#include "stdlib.h" +#include "utils.h" +#include "config.h" +#include "ads1220.h" +#include "fram.h" +#include "modbuss.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "driver/mcpwm.h" +int zero_totalflow_req = 0; +const static char *TAG = "flow"; + + +typedef struct capture_event +{ + int ch; + uint32_t val; +} capture_event_t; + +#define FLOW1_PIN_ECHO GPIO_NUM_39 // 捕获GPIO端口 +#define FLOW2_PIN_ECHO GPIO_NUM_38 // 捕获GPIO端口 + +#define TRIGGER_THREAD_PRIORITY 5 + +extern int abs_sub(uint32_t enc_update_time, uint32_t _enc_update_time); + +typedef struct +{ + uint32_t capture_signal; + mcpwm_capture_signal_t sel_cap_signal; +} capture; + +// static uint32_t cap_val_begin_of_flow1 = 0; +// static uint32_t cap_val_end_of_flow1 = 0; +// static uint32_t cap_val_begin_of_flow2 = 0; +// static uint32_t cap_val_end_of_flow2 = 0; + +//static xQueueHandle cap_queue; +extern uint32_t rtc_clk_apb_freq; +uint32_t volatile t15_ccr[2]; +uint16_t volatile t15_ccr_times[2]; + +cal_4_20ma_t *cal_4_20ma = (cal_4_20ma_t *)&gWordVar[CAL_4_20MA_ADDR]; +flow_config_t *flow_config = (flow_config_t *)&gWordVar[FLOW_CONFIG_ADDR]; +flow_t *pflow = (flow_t *)&gWordVar[FLOW_REG_ADDR]; + +void capture_flow1_init(); +void capture_flow2_init(); +extern void ADS1220_Init(void); + +uint32_t volatile last_ccr[2] = {0}; + +extern int ad_value[4]; +extern int ad_update_time[4]; + +extern uint8_t ad_watchdog_cnt; + +extern int ad_values[4]; +extern int ad_update_time[4]; +uint32_t flow_update_time[2]; +uint8_t timeout[2] = {0}; +int flow_rem[2] = {0}; + +static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, + void *arg) +{ + // calculate the interval in the ISR, + // so that the interval will be always correct even when cap_queue is not handled in time and overflow. + BaseType_t high_task_wakeup = pdFALSE; + + t15_ccr[0] = edata->cap_value; + t15_ccr_times[0]++; + return high_task_wakeup == pdFALSE; +} + +void capture_flow1_init() +{ + ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO)); + // enable pull down CAP0, to reduce noise + ESP_ERROR_CHECK(gpio_pulldown_en(FLOW1_PIN_ECHO)); + // enable both edge capture on CAP0 + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_NEG_EDGE, + .cap_prescale = 1, + .capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数 + .user_data = NULL}; + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf)); + ESP_LOGI(TAG, "capture_flow_init"); +} + +static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, + void *arg) +{ + // calculate the interval in the ISR, + // so that the interval will be always correct even when cap_queue is not handled in time and overflow. + BaseType_t high_task_wakeup = pdFALSE; + + t15_ccr[1] = edata->cap_value; + // t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq); + t15_ccr_times[1]++; + // send measurement back though queue + // xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup); + + return high_task_wakeup == pdFALSE; +} + +void capture_flow2_init() +{ + ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO)); + // enable pull down CAP0, to reduce noise + ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO)); + // enable both edge capture on CAP0 + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_NEG_EDGE, + .cap_prescale = 1, + .capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数 + .user_data = NULL}; + ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf)); + ESP_LOGI(TAG, "capture_flow_init"); +} + +// void capture_task(void) +// { +// while (true) { +// capture_event_t cap_event = {.val = 0, .ch = 1}; +// uint32_t pulse_width_us = 0; +// // block and wait for new measurement +// // ESP_LOGI(TAG, "xQueueReceive started"); +// xQueueReceive(cap_queue, &cap_event, portMAX_DELAY); +// // ESP_LOGI(TAG, "xQueueReceive after"); +// // ESP_LOGI(TAG, " cap_event.val: %d, cap_event.ch : %d", cap_event.val, cap_event.ch); +// switch (cap_event.ch) +// { +// case 1: //flow1 capture +// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq); + +// ESP_LOGI(TAG, " (flow1 capture) Pulse width: %uus", pulse_width_us); +// break; +// case 2: //flow2 capture +// pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq); +// ESP_LOGI(TAG, "(flow2 capture) Pulse width: %uus", pulse_width_us); +// break; +// default: ESP_LOGI(TAG, " default\n"); +// break; +// } +// } +// } + +void flow_init(void) +{ + // // 流量 初始化捕获定时器 + + // // capture_flow2_init(); + // // MX_TIM15_Init(); + // // HAL_TIM_Base_Start_IT(&htim15); + // if (flow_config->input_type == 1) + // { // 4~20ma + // // ADS1220_Init(); + // } + // else if (flow_config->input_type == 2) + // { // freq + // // HAL_TIM_IC_Start_IT(&htim15, TIM_CHANNEL_1); + // // HAL_TIM_IC_Start_IT(&htim15, TIM_CHANNEL_2); + // capture_flow1_init(); + // capture_flow2_init(); + // } + + capture_flow1_init(); + capture_flow2_init(); +} +extern void zero_totalflow(int ch); +void flow_task(void *arg) +{ + static uint32_t cp_flow_tick = 0; + static uint32_t ad_flow_tick = 100; + //int lock_time_out = 0; + while (1) + { + vTaskDelay(pdMS_TO_TICKS(100)); + + if (flow_config->input_type == 2 && TickDiff(cp_flow_tick) > 100) + { + int ch; + cp_flow_tick = xTaskGetTickCount(); + for (ch = 0; ch < 2; ch++) + { + if (t15_ccr_times[ch] > 0) + { + int ccr_times; + int time_diff; + uint32_t ccr; + // __disable_irq(); + ccr_times = t15_ccr_times[ch]; + + t15_ccr_times[ch] = 0; + ccr = t15_ccr[ch]; + ccr = ccr / (rtc_clk_apb_freq / 1000000); + // __enable_irq(); + time_diff = ccr - last_ccr[ch]; + ESP_LOGI(TAG, "(type2) t15_ccr_times[%d]: %lu %d time_diff: %d", ch, ccr, ccr_times, time_diff); + ESP_LOGI(TAG,"rtc_clk_apb_freq : %lu\n", rtc_clk_apb_freq); + if (time_diff != 0) + { + int t_flow; + + pflow[ch].flow_ = flow_config->pulse_coef[ch] * 600 * (int64_t)ccr_times / time_diff; + if (pflow[ch].flow_ < flow_config->min_flow[ch]) + { + pflow[ch].flow = 0; + } + else + { + pflow[ch].flow = pflow[ch].flow_; + } + t_flow = pflow[ch].flow * time_diff / (5 * 60); + flow_rem[ch] += t_flow; + pflow[ch].total_flow += flow_rem[ch] / 10000; + flow_rem[ch] = flow_rem[ch] % 10000; + pflow[ch].update_time = ccr; + last_ccr[ch] = ccr; + timeout[ch] = 0; + // ESP_LOGI(TAG, "(type2) pflow[%d].flow: %u", ch ,pflow[ch].flow); + } + } + if (++timeout[ch] > 5) + { + timeout[ch] = 0; + pflow[ch].flow = 0; + pflow[ch].flow_ = 0; + } + } + } + // if (flow_config->input_type == 1 && TickDiff(ad_flow_tick) > 200) + // { + // int i; + // ad_flow_cal_t *cal = flow_config->ad_cal; + // ad_flow_tick = xTaskGetTickCount(); + // for (i = 0; i < 2; i++) + // { + // int ad_ch = i * 2 + 1; + // int time_diff = abs_sub(ad_update_time[ad_ch], pflow[i].update_time); + // if (time_diff != 0) + // { + // int t_flow; // time_diff时间段总流量 + // pflow[i].flow_ = scale(ad_value[ad_ch], cal_4_20ma->ch[i].ad_4ma, cal_4_20ma->ch[i].ad_20ma, cal[i].flow_min, cal[i].flow_max); + // if (pflow[i].flow_ < flow_config->min_flow[i]) + // { + // pflow[i].flow = 0; + // } + // else + // { + // pflow[i].flow = pflow[i].flow_; + // } + // // 累计流量计算 pflow[i].flow 单位为0.01L/分钟 time_diff 单位为20uS + // // flow = pflow[i].flow / 60.0 * 10000; 将流量换算成uL/s + // // t_diff = time_diff / 50000 将时间差换算成秒 + // // t_flow = flow * t_diff 计算t_diff时间段的流量 单位uL + // // 取出0.01L的整数部分累加,余数部分和下次值累加 + // // t_flow = pflow[i].flow * 1000 * time_diff / 500000 / 60; + // int time_diff_us = time_diff / (APB_CLK_FREQ / 1000000); + // t_flow = pflow[i].flow * time_diff_us / 60 / 100; + // flow_rem[i] += t_flow; + // pflow[i].total_flow += flow_rem[i] / 10000; + // flow_rem[i] = flow_rem[i] % 10000; + // pflow[i].update_time = ad_update_time[ad_ch]; + // timeout[i] = 0; + // ESP_LOGI(TAG, "(type1) flow_rem[%d].flow: %u", i, pflow[i].flow); + // } + // if (++timeout[i] > 10) + // { + // timeout[i] = 0; + // pflow[i].flow = 0; + // pflow[i].flow_ = 0; + // } + // } + // } + // if(zero_totalflow_req){ + // zero_totalflow_req = 0; + // zero_totalflow(0); + // zero_totalflow(1); + // } + } +} + +// 获取给定时刻累计流量 +int get_total_flow_by_time(int ch, uint32_t time) +{ + int delta_t; + int delta_flow; + if (ch > 1) + { + return 0; + } + delta_t = abs_sub(time, pflow[ch].update_time) / (APB_CLK_FREQ / 1000000); // 换算成us + delta_flow = pflow[ch].flow * delta_t / 60 / 100; + return pflow[ch].total_flow + delta_flow; +} + +void zero_totalflow(int ch) +{ + if (ch > 1) + { + return; + } + pflow[ch].total_flow = 0; + flow_rem[ch] = 0; +} + +void zero_flow2(void) +{ + memset(pflow, 0, sizeof(flow_t) * 2); + // ESP_LOGI(TAG, "%d %d", (int)pflow[0].total_flow, (int)pflow[1].total_flow); + for (int i = 0; i < 2; i++) + { + last_ccr[i] = 0; + flow_rem[i] = 0; + timeout[i] = 0; + + t15_ccr[i] = 0; + t15_ccr_times[i] = 0; + } +} + +void FLOW_init() +{ + flow_init(); + xTaskCreate(flow_task, "flow_task", 4096, NULL, 10, NULL); +} diff --git a/main/stm32/flow.h b/main/stm32/flow.h new file mode 100644 index 0000000..fd7b81d --- /dev/null +++ b/main/stm32/flow.h @@ -0,0 +1,7 @@ +#ifndef __FLOW_H +#define __FLOW_H + + +void zero_flow2(void); + +#endif \ No newline at end of file diff --git a/main/peripheral/config/fram.c b/main/stm32/fram.c similarity index 54% rename from main/peripheral/config/fram.c rename to main/stm32/fram.c index 3ff385a..02a435b 100644 --- a/main/peripheral/config/fram.c +++ b/main/stm32/fram.c @@ -1,14 +1,55 @@ +#include "fram.h" +#include "string.h" + #include +#include "esp_log.h" #include "driver/i2c.h" #include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_system.h" +#include "sdkconfig.h" #include "driver/gpio.h" -#include "esp_log.h" -#include "fram.h" +static const char *TAG = "i2c-simple-example"; -static const char *TAG = "fram"; +#define I2C_MASTER_SCL_IO 1 /*!< GPIO number used for I2C master clock */ +#define I2C_MASTER_SDA_IO 2 /*!< GPIO number used for I2C master data */ +#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ +#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ +#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_TIMEOUT_MS 1000 +#define MPU9250_SENSOR_ADDR 0x68 /*!< Slave address of the MPU9250 sensor */ +#define MPU9250_WHO_AM_I_REG_ADDR 0x75 /*!< Register addresses of the "who am I" register */ + +#define MPU9250_PWR_MGMT_1_REG_ADDR 0x6B /*!< Register addresses of the power managment register */ +#define MPU9250_RESET_BIT 7 + +#define WRITE_BIT I2C_MASTER_WRITE +#define ACK_CHECK_EN 0x1 +#define TAG "FREM" + +/** + * @brief Read a sequence of bytes from a MPU9250 sensor registers + */ +// static esp_err_t mpu9250_register_read(uint8_t reg_addr, uint8_t *data, size_t len) +// { +// return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS); +// } + +/** + * @brief Write a byte to a MPU9250 sensor register + */ +// static esp_err_t mpu9250_register_write_byte(uint8_t reg_addr, uint8_t data) +// { +// int ret; +// uint8_t write_buf[2] = {reg_addr, data}; + +// ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS); + +// return ret; +// } /** * @brief i2c master initialization @@ -31,7 +72,7 @@ esp_err_t i2c_master_init(void) return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); } -int fram_write(uint16_t addr, void *buf,uint32_t len) +int fram_write(uint16_t addr, void * buf,uint32_t len) { esp_err_t ret; uint8_t slave_addr = (0xA0) | ((addr >> 8) & 0x7);/*page select*/ @@ -55,7 +96,6 @@ int fram_write(uint16_t addr, void *buf,uint32_t len) i2c_cmd_link_delete(cmd); return ret; } - int fram_read(uint16_t addr,void * buf,uint32_t len) { // esp_err_t err = i2c_param_config(i2c_master_port, &conf); @@ -78,12 +118,10 @@ void save_para(void) { } - void save_encode(void) { } - void read_para() { diff --git a/main/stm32/fram.h b/main/stm32/fram.h new file mode 100644 index 0000000..7c680d2 --- /dev/null +++ b/main/stm32/fram.h @@ -0,0 +1,31 @@ +#ifndef FRAM_H__ +#define FRAM_H__ + + + +// #include "main.h" +// #include "i2c.h" +#include +#include "esp_log.h" +#include "driver/i2c.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" + + + +int fram_write(uint16_t addr, void * buf,uint32_t len); +int fram_read(uint16_t addr,void * buf,uint32_t len); +//extern void fram_write_para(fram_para_t *para,uint32_t len); +//extern void fram_read_para(fram_para_t *para,uint32_t len); + + +void save_para(void); +void save_encode(void); +void read_para(void); +void clear_para(void); +#endif + + diff --git a/main/peripheral/led.c b/main/stm32/led.c similarity index 100% rename from main/peripheral/led.c rename to main/stm32/led.c diff --git a/main/peripheral/inc/led.h b/main/stm32/led.h similarity index 100% rename from main/peripheral/inc/led.h rename to main/stm32/led.h diff --git a/main/stm32/master.c b/main/stm32/master.c new file mode 100644 index 0000000..0c6273e --- /dev/null +++ b/main/stm32/master.c @@ -0,0 +1,296 @@ +// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "string.h" +#include "esp_log.h" +#include "modbus_params.h" // for modbus parameters structures +#include "mbcontroller.h" +#include "sdkconfig.h" + +#define MB_PORT_NUM (CONFIG_MB_UART_PORT_NUM) // Number of UART port used for Modbus connection +#define MB_DEV_SPEED (CONFIG_MB_UART_BAUD_RATE) // The communication speed of the UART + +// Note: Some pins on target chip cannot be assigned for UART communication. +// See UART documentation for selected board and target to configure pins using Kconfig. + +// The number of parameters that intended to be used in the particular control process +#define MASTER_MAX_CIDS num_device_parameters + +// Number of reading of parameters from slave +#define MASTER_MAX_RETRY 30 + +// Timeout to update cid over Modbus +#define UPDATE_CIDS_TIMEOUT_MS (500) +#define UPDATE_CIDS_TIMEOUT_TICS (UPDATE_CIDS_TIMEOUT_MS / portTICK_RATE_MS) + +// Timeout between polls +#define POLL_TIMEOUT_MS (1) +#define POLL_TIMEOUT_TICS (POLL_TIMEOUT_MS / portTICK_RATE_MS) + +// The macro to get offset for parameter in the appropriate structure +#define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) +#define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) +#define COIL_OFFSET(field) ((uint16_t)(offsetof(coil_reg_params_t, field) + 1)) +// Discrete offset macro +#define DISCR_OFFSET(field) ((uint16_t)(offsetof(discrete_reg_params_t, field) + 1)) + +#define STR(fieldname) ((const char*)( fieldname )) +// Options can be used as bit masks or parameter limits +#define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val } + +static const char *TAG = "MASTER_TEST"; + +// Enumeration of modbus device addresses accessed by master device +enum { + MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here) +}; + +// Enumeration of all supported CIDs for device (used in parameter definition table) +enum { + CID_INP_DATA_0 = 0, + CID_HOLD_DATA_0, + CID_INP_DATA_1, + CID_HOLD_DATA_1, + CID_INP_DATA_2, + CID_HOLD_DATA_2, + CID_HOLD_TEST_REG, + CID_RELAY_P1, + CID_RELAY_P2, + CID_COUNT +}; + +// Example Data (Object) Dictionary for Modbus parameters: +// The CID field in the table must be unique. +// Modbus Slave Addr field defines slave address of the device with correspond parameter. +// Modbus Reg Type - Type of Modbus register area (Holding register, Input Register and such). +// Reg Start field defines the start Modbus register number and Reg Size defines the number of registers for the characteristic accordingly. +// The Instance Offset defines offset in the appropriate parameter structure that will be used as instance to save parameter value. +// Data Type, Data Size specify type of the characteristic and its data size. +// Parameter Options field specifies the options that can be used to process parameter value (limits or masks). +// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc). +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_INP_DATA_0, STR("Data_channel_0"), STR("Volts"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2, + INPUT_OFFSET(input_data0), PARAM_TYPE_FLOAT, 4, OPTS( -10, 10, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_HOLD_DATA_0, STR("Humidity_1"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2, + HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_INP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 2, + INPUT_OFFSET(input_data1), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_HOLD_DATA_1, STR("Humidity_2"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2, 2, + HOLD_OFFSET(holding_data1), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_INP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 4, 2, + INPUT_OFFSET(input_data2), PARAM_TYPE_FLOAT, 4, OPTS( -40, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_HOLD_DATA_2, STR("Humidity_3"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 4, 2, + HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 10, 58, + HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, 116, OPTS( 0, 100, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_RELAY_P1, STR("RelayP1"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0, 8, + COIL_OFFSET(coils_port0), PARAM_TYPE_U16, 2, OPTS( BIT1, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_RELAY_P2, STR("RelayP2"), STR("on/off"), MB_DEVICE_ADDR1, MB_PARAM_COIL, 8, 8, + COIL_OFFSET(coils_port1), PARAM_TYPE_U16, 2, OPTS( BIT0, 0, 0 ), PAR_PERMS_READ_WRITE_TRIGGER } +}; + +// Calculate number of parameters in the table +const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0])); + +// The function to get pointer to parameter storage (instance) according to parameter description table +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; + case MB_PARAM_INPUT: + instance_ptr = ((void*)&input_reg_params + param_descriptor->param_offset - 1); + break; + case MB_PARAM_COIL: + instance_ptr = ((void*)&coil_reg_params + param_descriptor->param_offset - 1); + break; + case MB_PARAM_DISCRETE: + instance_ptr = ((void*)&discrete_reg_params + param_descriptor->param_offset - 1); + break; + default: + instance_ptr = NULL; + break; + } + } else { + ESP_LOGE(TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); + assert(instance_ptr != NULL); + } + return instance_ptr; +} + +// User operation function to read slave values and check alarm +static void master_operation_func(void *arg) +{ + esp_err_t err = ESP_OK; + float value = 0; + bool alarm_state = false; + const mb_parameter_descriptor_t* param_descriptor = NULL; + + ESP_LOGI(TAG, "Start modbus test..."); + + for(uint16_t retry = 0; retry <= MASTER_MAX_RETRY && (!alarm_state); retry++) { + // Read all found characteristics from slave(s) + for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < MASTER_MAX_CIDS; cid++) + { + // Get data from parameters description table + // and use this information to fill the characteristics description table + // and having all required fields in just one table + err = mbc_master_get_cid_info(cid, ¶m_descriptor); + if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { + void* temp_data_ptr = master_get_param_data(param_descriptor); + assert(temp_data_ptr); + uint8_t type = 0; + if ((param_descriptor->param_type == PARAM_TYPE_ASCII) && + (param_descriptor->cid == CID_HOLD_TEST_REG)) { + // Check for long array of registers of type PARAM_TYPE_ASCII + err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, + (uint8_t*)temp_data_ptr, &type); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (char*)param_descriptor->param_units, + *(uint32_t*)temp_data_ptr); + // Initialize data of test array and write to slave + if (*(uint32_t*)temp_data_ptr != 0xAAAAAAAA) { + memset((void*)temp_data_ptr, 0xAA, param_descriptor->param_size); + *(uint32_t*)temp_data_ptr = 0xAAAAAAAA; + err = mbc_master_set_parameter(cid, (char*)param_descriptor->param_key, + (uint8_t*)temp_data_ptr, &type); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x), write successful.", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (char*)param_descriptor->param_units, + *(uint32_t*)temp_data_ptr); + } else { + ESP_LOGE(TAG, "Characteristic #%d (%s) write fail, err = 0x%x (%s).", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (int)err, + (char*)esp_err_to_name(err)); + } + } + } 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)); + } + } else { + err = mbc_master_get_parameter(cid, (char*)param_descriptor->param_key, + (uint8_t*)&value, &type); + if (err == ESP_OK) { + *(float*)temp_data_ptr = value; + if ((param_descriptor->mb_param_type == MB_PARAM_HOLDING) || + (param_descriptor->mb_param_type == MB_PARAM_INPUT)) { + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %f (0x%x) read successful.", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (char*)param_descriptor->param_units, + value, + *(uint32_t*)temp_data_ptr); + if (((value > param_descriptor->param_opts.max) || + (value < param_descriptor->param_opts.min))) { + alarm_state = true; + break; + } + } else { + uint16_t state = *(uint16_t*)temp_data_ptr; + const char* rw_str = (state & param_descriptor->param_opts.opt1) ? "ON" : "OFF"; + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %s (0x%x) read successful.", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (char*)param_descriptor->param_units, + (const char*)rw_str, + *(uint16_t*)temp_data_ptr); + if (state & param_descriptor->param_opts.opt1) { + alarm_state = true; + break; + } + } + } 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(POLL_TIMEOUT_TICS); // timeout between polls + } + } + vTaskDelay(UPDATE_CIDS_TIMEOUT_TICS); // + } + + if (alarm_state) { + ESP_LOGI(TAG, "Alarm triggered by cid #%d.", + param_descriptor->cid); + } else { + ESP_LOGE(TAG, "Alarm is not triggered after %d retries.", + MASTER_MAX_RETRY); + } + ESP_LOGI(TAG, "Destroy master..."); + ESP_ERROR_CHECK(mbc_master_destroy()); +} + +// Modbus master initialization +static esp_err_t master_init(void) +{ + // Initialize and start Modbus controller + mb_communication_info_t comm = { + .port = MB_PORT_NUM, +#if CONFIG_MB_COMM_MODE_ASCII + .mode = MB_MODE_ASCII, //串口 +#elif CONFIG_MB_COMM_MODE_RTU + .mode = MB_MODE_RTU, //RS485 +#endif + .baudrate = MB_DEV_SPEED, + .parity = MB_PARITY_NONE + }; + void* master_handler = NULL; + + esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); + MB_RETURN_ON_FALSE((master_handler != 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).", + (uint32_t)err); + err = mbc_master_setup((void*)&comm); + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, + "mb controller setup fail, returns(0x%x).", + (uint32_t)err); + + // Set UART pin numbers + err = uart_set_pin(MB_PORT_NUM, CONFIG_MB_UART_TXD, CONFIG_MB_UART_RXD, + CONFIG_MB_UART_RTS, 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).", (uint32_t)err); + + err = mbc_master_start(); + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, + "mb controller start fail, returns(0x%x).", + (uint32_t)err); + + // Set driver mode to Half Duplex + err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX); + MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, + \ No newline at end of file diff --git a/main/stm32/pile_id.c b/main/stm32/pile_id.c new file mode 100644 index 0000000..ab689bc --- /dev/null +++ b/main/stm32/pile_id.c @@ -0,0 +1,101 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_log.h" + +#include "pile_id.h" +#include "config.h" +#include "modbusS.h" +#include "flow.h" +#include "depth.h" +#include "../communication_pad/inc/communication_pad.h" +#include "ads1220.h" + +#define TAG "pile_id" + +uint16_t *cur_pile_id = &gWordVar[LAST_PILE_ID_ADDR]; +gps_message_t *gps_message = (gps_message_t *)&gWordVar[REG_GPS_MESSAGE]; +double gps_xy[2]; +double inc_pile_distance = 5; +int none_flag = 1; + +extern move_t *pMoveCtx; +extern int depth_over_inc_pile_flag; + +static double double_abs(double a, double b) +{ + if (a > b) return a - b; + else return b - a; +} + +int gps_distance_check(void) +{ + if (gps_message->gps_status != 4) // gps信号不是精准定位则不启用 + { + none_flag = 1; + return 0; + } + if (none_flag) return 0; + if (double_abs(gps_message->x, gps_xy[0]) > inc_pile_distance) return 1; + if (double_abs(gps_message->y, gps_xy[1]) > inc_pile_distance) return 1; + return 0; +} + +void inc_pile_fun(void) +{ + ESP_LOGI(TAG, "inc pile"); + // 增加桩号 + (*cur_pile_id)++; + save_pile_id(); + // 更新判断的标志数据 + depth_over_inc_pile_flag = 0; + pMoveCtx->work_time = 0; + pMoveCtx->work_stop_state_flag = 0; + gps_xy[0] = gps_message->x; + gps_xy[1] = gps_message->y; + none_flag = 0; + // 清空数据 + zero_flow1(); + zero_flow2(); + zero_depth(); +} + +// 轮询检查是否换桩 +void pile_id_check_task(void) +{ + static uint16_t last_pile_work_state = PILE_STATE_STOP; + while (1) + { + // 自动更新工作状态 + if (last_pile_work_state == PILE_STATE_STOP) // 判断是否开始 + { + if (gWordVar[AC_CURRENT_REG_ADDR + 0] > CURRENT0_TH && depth_over_inc_pile_flag == 1) // 钻头电流开 && 深度超过阈值 + { + depth_data->pile_work_state_and_direction = (depth_data->pile_work_state_and_direction & 0XFF) | PILE_STATE_WORK; + } + } + + if (last_pile_work_state == PILE_STATE_WORK) // 判断是否结束 + { + if (pMoveCtx->work_stop_state_flag == 1 || gps_distance_check()) + { + depth_data->pile_work_state_and_direction = (depth_data->pile_work_state_and_direction & 0XFF) | PILE_STATE_STOP; + } + } + + + // 开始则换桩 + if ((depth_data->pile_work_state_and_direction & 0xff00) == PILE_STATE_WORK && last_pile_work_state == PILE_STATE_STOP) + { + inc_pile_fun(); + } + last_pile_work_state = depth_data->pile_work_state_and_direction & 0xff00; + + vTaskDelay(pdMS_TO_TICKS(100)); + } +} + +void pile_id_init(void) +{ + xTaskCreate(pile_id_check_task, "ads1220_task", 4096, NULL, 10, NULL); +} diff --git a/main/stm32/pile_id.h b/main/stm32/pile_id.h new file mode 100644 index 0000000..6f42d7e --- /dev/null +++ b/main/stm32/pile_id.h @@ -0,0 +1,9 @@ +#ifndef __PILE_ID_H +#define __PILE_ID_H + +#define CURRENT0_TH 1000 +#define CURRENT2_TIMEOUT_TH 200 // 单位100ms + +void pile_id_init(void); + +#endif \ No newline at end of file diff --git a/main/stm32/uart0_modbus_slave.c b/main/stm32/uart0_modbus_slave.c new file mode 100644 index 0000000..2955f0b --- /dev/null +++ b/main/stm32/uart0_modbus_slave.c @@ -0,0 +1,143 @@ +/* UART Echo Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" +#include "driver/gpio.h" +#include "sdkconfig.h" +#include "esp_log.h" +#include "uart.h" + +static const char *TAG = "UART0"; + +#define BAUD_RATE (460800) +#define UART_PORT_NUM (0) +#define BUF_SIZE (256) +#define UART_READ_TOUT (50 / portTICK_PERIOD_MS) + +#define LED1_GPIO_PIN 9 + +uint8_t txbuf[BUF_SIZE]; +uint8_t rxbuf[BUF_SIZE]; +extern int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc); +extern uint16_t gWordVar[]; + +void LED1_Toggle(void) +{ + static unsigned char flg = 1; + if (flg) + { + gpio_set_level(LED1_GPIO_PIN, 0); + flg = 0; + } + else + { + gpio_set_level(LED1_GPIO_PIN, 1); + flg = 1; + } +} + +void uart0_init(void) +{ + const int uart_num = UART_PORT_NUM; + uart_config_t uart_config = { + .baud_rate = BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 122, + .source_clk = UART_SCLK_APB, + }; + // Set UART log level + // esp_log_level_set(TAG, ESP_LOG_NONE); + + ESP_LOGI(TAG, "Start RS485 application test and configure UART."); + + // Install UART driver (we don't need an event queue here) + // In this example we don't even use a buffer for sending data. + ESP_ERROR_CHECK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE, 0, NULL, 0)); + + // Configure UART parameters + ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config)); + ESP_LOGI(TAG, "UART set pins, mode and install driver."); + // Set UART pins as per KConfig settings + //ESP_ERROR_CHECK(uart_set_pin(uart_num, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN));之前没解开注释 + //ESP_ERROR_CHECK(uart_set_pin(uart_num, 11, 13, 12, -1)); + // Set RS485 half duplex mode + ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX)); + // Set read timeout of UART TOUT feature + ESP_ERROR_CHECK(uart_set_rx_timeout(uart_num, UART_READ_TOUT)); +} + +void uart0_modbus_slave_task(void *arg) +{ + uart0_init(); + + while (1) + { + int txlen = 0; + // for (int i = 0; i < 70; i++) + // txbuf[i] = i; + // int uart_write_length = uart_write_bytes(UART_PORT_NUM, txbuf, 70); + // ESP_LOGI("modbus_slave","-----------------------------txlen:%d uart_write_length:%d", txlen, uart_write_length); + // for (int i = 0; i < uart_write_length; i++) + // ESP_LOGI("modbus_slave","uart0 return: 0x%x", txbuf[i]); + + // vTaskDelay(1000 / portTICK_PERIOD_MS); + // vTaskDelay(1000 / portTICK_PERIOD_MS); + // continue; + // ESP_LOGI("modbus_slave","---------"); + + int len = uart_read_bytes(UART_PORT_NUM, rxbuf, BUF_SIZE, UART_READ_TOUT); + /*uint32_t tick = */xTaskGetTickCount(); + // ESP_LOGI("modbus_slave","-----------------------------rxlen:%d", len); + // for (int i = 0; i < len; i++) + // ESP_LOGI("modbus_slave","uart0 get: 0x%x", rxbuf[i]); + + + if (len > 0) + { + txlen = ModbusSlaveProcess(txbuf, rxbuf, len, 1); + if (txlen > 0) + { + LED1_Toggle(); + int uart_write_length = uart_write_bytes(UART_PORT_NUM, txbuf, txlen); + // ESP_LOGI("modbus_slave","-----------------------------txlen:%d uart_write_length:%d", txlen, uart_write_length); + // for (int i = 0; i < uart_write_length; i++) + // ESP_LOGI("modbus_slave","uart0 return: 0x%x", txbuf[i]); + } + } + + // if (tick - last_rxtick >= PACKET_READ_TICS) + // { + // com_poll_modbus_master_poll(0); + // // if (++mcu_watch_dog_cnt > mcu_watch_dog_timeout) //如果通讯中断会相互重启,计数器不起作用 + // if (gpio_get_level(0)) // cpu 启动后会拉低GPIO0 + // { + // mcu_watch_dog_cnt = 0; + // if (mcu_pwr_off_cnt < 2) + // { + // mcu_pwr_off_cnt++; + // gpio_set_level(12, 1); // 3v8 off + // vTaskDelay(3000 / portTICK_RATE_MS); + // gpio_set_level(12, 0); // 3v8 off + // mcu_watch_dog_timeout = 12000 / (portTICK_RATE_MS * PACKET_READ_TICS); + // } + // } + // } + // last_rxtick = tick; + } +} + +void uart0_modbus_slave_init(void) +{ + xTaskCreate(uart0_modbus_slave_task, "uart0_modbus_slave_task", 4096, NULL, 10, NULL); +} diff --git a/main/stm32/uart1_modbus_master.c b/main/stm32/uart1_modbus_master.c new file mode 100644 index 0000000..a8f6654 --- /dev/null +++ b/main/stm32/uart1_modbus_master.c @@ -0,0 +1,112 @@ +/* UART Echo Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" +#include "driver/gpio.h" +#include "sdkconfig.h" +#include "esp_log.h" +#include "uart.h" + +/** + * This is an example which echos any data it receives on configured UART back to the sender, + * with hardware flow control turned off. It does not use UART driver event queue. + * + * - Port: configured UART + * - Receive (Rx) buffer: on + * - Transmit (Tx) buffer: off + * - Flow control: off + * - Event queue: off + * - Pin assignment: see defines below (See Kconfig) + */ + +#define UART_TXD_PIN 11 +#define UART_RXD_PIN 13 +#define UART_RTS_PIN 12 +#define UART_CTS_PIN (-1) + +static const char *TAG = "UART1"; + +#define BAUD_RATE (9600) +#define UART_PORT_NUM (1) +#define RX_BUF_SIZE (256) +#define TX_BUF_SIZE (256) + +#define UART_READ_TOUT (5 / portTICK_PERIOD_MS) + +static void uart1_rs485_init(void) +{ + + uart_config_t uart_config = { + .baud_rate = BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 122, + .source_clk = UART_SCLK_APB, + }; + + ESP_LOGI(TAG, "Start RS485 application test and configure UART."); + + // Install UART driver (we don't need an event queue here) + // In this example we don't even use a buffer for sending data. + ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, RX_BUF_SIZE, TX_BUF_SIZE, 0, NULL, 0)); + + // Configure UART parameters + ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config)); + + ESP_LOGI(TAG, "UART set pins, mode and install driver."); + + // Set UART pins as per KConfig settings + ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN)); + + // Set RS485 half duplex mode + ESP_ERROR_CHECK(uart_set_mode(UART_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX)); + + // Set read timeout of UART TOUT feature + ESP_ERROR_CHECK(uart_set_rx_timeout(UART_PORT_NUM, UART_READ_TOUT)); +} + +static void uart0_com_poll_task(void *arg) +{ + + uint32_t last_rxtick = 0; + uint8_t rx_data[RX_BUF_SIZE]; + uint8_t tx_data[RX_BUF_SIZE]; + while (1) + { + // Read data from UART + int len = uart_read_bytes(UART_PORT_NUM, rx_data, RX_BUF_SIZE, UART_READ_TOUT); + uint32_t tick = xTaskGetTickCount(); + // Write data back to UART + if (len > 0) + { + // ESP_LOGI(TAG, "uart_read_bytes len=%d", len); + int err = com_poll_modbus_master_on_revice(0, data, len); + if (err == 0) + { + } + } + if (tick - last_rxtick >= UART_READ_TOUT) + { + com_poll_modbus_master_poll(0); + // if (++mcu_watch_dog_cnt > mcu_watch_dog_timeout) //如果通讯中断会相互重启,计数器不起作用 + } + } + vTaskDelete(NULL); +} + +void uart1_task_init(void) +{ + ESP_LOGI(TAG, "uart1_com_poll_task"); + // A uart read/write example without event queue; + xTaskCreate(uart0_com_poll_task, "uart0_com_poll_task", 1024, NULL, 9, NULL); +} diff --git a/main/stm32/uart2_printer.c b/main/stm32/uart2_printer.c new file mode 100644 index 0000000..16b2bcf --- /dev/null +++ b/main/stm32/uart2_printer.c @@ -0,0 +1,61 @@ +/* UART Echo Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" +#include "driver/gpio.h" +#include "sdkconfig.h" +#include "esp_log.h" +#include "uart.h" + +/** + * This is an example which echos any data it receives on configured UART back to the sender, + * with hardware flow control turned off. It does not use UART driver event queue. + * + * - Port: configured UART + * - Receive (Rx) buffer: on + * - Transmit (Tx) buffer: off + * - Flow control: off + * - Event queue: off + * - Pin assignment: see defines below (See Kconfig) + */ + +#define UART_TXD_PIN 14 +#define UART_RXD_PIN 21 +#define UART_RTS_PIN (-1) +#define UART_CTS_PIN 47 + +static const char *TAG = "UART2"; +#define UART2_BAUD_RATE (115200) +#define UART_PORT_NUM (2) +#define BUF_SIZE (1024) + +static void uart2_init(void) +{ + uart_config_t uart_config = { + .baud_rate = UART2_BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_APB, + }; + int intr_alloc_flags = 0; + +#if CONFIG_UART_ISR_IN_IRAM + intr_alloc_flags = ESP_INTR_FLAG_IRAM; +#endif + + ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); + ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config)); + ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TXD_PIN, UART_RXD_PIN, UART_RTS_PIN, UART_CTS_PIN)); +} + + \ No newline at end of file diff --git a/main/utils.c b/main/stm32/utils.c similarity index 100% rename from main/utils.c rename to main/stm32/utils.c diff --git a/main/inc/utils.h b/main/stm32/utils.h similarity index 65% rename from main/inc/utils.h rename to main/stm32/utils.h index 57470ff..f74bbdc 100644 --- a/main/inc/utils.h +++ b/main/stm32/utils.h @@ -2,11 +2,8 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#include - int GetCompileDateTime(uint16_t *DateTime); uint32_t TickDiff(uint32_t comptime); -int scale(int raw, int raw_min, int raw_max,int eng_min, int eng_max); int abs_sub_uint32(uint32_t a, uint32_t b); #endif diff --git a/main/uart.h b/main/uart.h new file mode 100644 index 0000000..ecaf7a9 --- /dev/null +++ b/main/uart.h @@ -0,0 +1,28 @@ +#ifndef _UART_H_ +#define _UART_H_ + +#define RS485_TXD_PIN 17 +#define RS485_RXD_PIN 18 +#define RS485_RTS_PIN 8 +#define RS485_CTS_PIN (-1) + +// #define MCU_TXD_PIN 17 +// #define MCU_RXD_PIN 18 + + +#define PRINT_TXD_PIN 16 +#define PRINT_RXD_PIN 15 +#define PRINT_RTS_PIN (-1) +#define PRINT_CTS_PIN 3 + + +#define RS485_UART_PORT_NUM (0) +#define RS485_UART_BAUD_RATE (115200) +#define RS485_TASK_STACK_SIZE (1024) + +#define PRINT_UART_PORT_NUM (1) +#define PRINT_UART_BAUD_RATE (115200) +#define PRINT_TASK_STACK_SIZE (1024) + + +#endif diff --git a/main/uart_example.c b/main/uart_example.c new file mode 100644 index 0000000..de7364e --- /dev/null +++ b/main/uart_example.c @@ -0,0 +1,97 @@ +/* UART Echo Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/uart.h" +#include "driver/gpio.h" +#include "sdkconfig.h" +#include "esp_log.h" +#include "uart.h" + +/** + * This is an example which echos any data it receives on configured UART back to the sender, + * with hardware flow control turned off. It does not use UART driver event queue. + * + * - Port: configured UART + * - Receive (Rx) buffer: on + * - Transmit (Tx) buffer: off + * - Flow control: off + * - Event queue: off + * - Pin assignment: see defines below (See Kconfig) + */ + +#define RS485_TXD_PIN 17 +#define RS485_RXD_PIN 18 +#define RS485_RTS_PIN 8 +#define RS485_CTS_PIN (-1) + +// #define MCU_TXD_PIN 17 +// #define MCU_RXD_PIN 18 + + +#define PRINT_TXD_PIN 16 +#define PRINT_RXD_PIN 15 +#define PRINT_RTS_PIN (-1) +#define PRINT_CTS_PIN 3 + + +#define RS485_UART_PORT_NUM (0) +#define RS485_UART_BAUD_RATE (115200) +#define RS485_TASK_STACK_SIZE (1024) + +#define PRINT_UART_PORT_NUM (1) +#define PRINT_UART_BAUD_RATE (115200) +#define PRINT_TASK_STACK_SIZE (1024) + +// static const char *TAG = "UART"; + +#define BUF_SIZE (1024) + +void RS485_init(void) +{ + uart_config_t uart_config = { + .baud_rate = RS485_UART_BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_APB, + }; + int intr_alloc_flags = 0; + +#if CONFIG_UART_ISR_IN_IRAM + intr_alloc_flags = ESP_INTR_FLAG_IRAM; +#endif + + ESP_ERROR_CHECK(uart_driver_install(RS485_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); + ESP_ERROR_CHECK(uart_param_config(RS485_UART_PORT_NUM, &uart_config)); + ESP_ERROR_CHECK(uart_set_pin(RS485_UART_PORT_NUM, RS485_TXD_PIN, RS485_RXD_PIN, RS485_RTS_PIN, RS485_CTS_PIN)); +} + +void print_init(void) +{ + uart_config_t uart_config = { + .baud_rate = PRINT_UART_BAUD_RATE, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .source_clk = UART_SCLK_APB, + }; + int intr_alloc_flags = 0; + +#if CONFIG_UART_ISR_IN_IRAM + intr_alloc_flags = ESP_INTR_FLAG_IRAM; +#endif + + ESP_ERROR_CHECK(uart_driver_install(PRINT_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); + ESP_ERROR_CHECK(uart_param_config(PRINT_UART_PORT_NUM, &uart_config)); + ESP_ERROR_CHECK(uart_set_pin(PRINT_UART_PORT_NUM, PRINT_TXD_PIN, PRINT_RXD_PIN, PRINT_RTS_PIN, PRINT_CTS_PIN)); +}