This commit is contained in:
snow 2024-03-30 18:47:02 +08:00
parent 24e496ead0
commit 8352283480
68 changed files with 4914 additions and 169 deletions

View File

@ -1,30 +1,26 @@
set(SRCS
"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"
"./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"
"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"
)
set(INCLUDE_DIRS "." "./communication_pad/inc")
set(INCLUDE_DIRS
"." "./inc"
"./modbus/inc"
"./peripheral/inc"
"./peripheral/flow/inc"
"./peripheral/config/inc"
)
idf_component_register(SRCS ${SRCS}
INCLUDE_DIRS ${INCLUDE_DIRS})

12
main/inc/utils.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _UTILS_H_
#define _UTILS_H_
#include <stdint.h>
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

View File

@ -1,110 +1,22 @@
/* 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 <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.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 <stdio.h>
#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 "esp_log.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)
#include "config.h"
#include "uart0_modbus_slave.h"
#include "flow.h"
#include "bl0939.h"
#include "depth.h"
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 cal_4_20ma_t *cal_4_20ma;//电流数据结构体
extern flow_config_t *flow_config;//流量数据结构体
extern depth_config_t *depth_config;//深度数据结构体
extern void pcnt_rotary_encoder_init_(void);
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)
{
@ -112,56 +24,12 @@ void app_main(void)
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(i2c_master_init());
//restore_default();
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();
ads1220_task_start(); /* 两路电流AD采样获取瞬时流量计算累计流量目前配置的是10HZ取决于SPS */
BL0939_init(); /* 实时采集通道电流根据depth_config_t中配置的启动与结束电流以及持续时间进行move_t机器开关状态的判断 */
DEPTH_init(); /* 编码器计算深度同时进行流量的按深度计数以及record的记录 */
FLOW_init(); /* 两一种计算流量的方法,计算累计流量 */
config_init();
uart0_modbus_slave_init();
// ble_gatts_server_init();
pad_communication_init();
// bt_client_init();//ok
//ESP32_Uart_Receive_Data();
flow_init();
BL0939_init();
// pcnt_rotary_encoder_init_();
DEPTH_init();
}
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);
}

354
main/modbus/ModbusS.c Normal file
View File

@ -0,0 +1,354 @@
#include <string.h>
// #include "driver/ledc.h"
// #include "esp_err.h"
#include "esp_log.h"
#include "ModbusS.h"
#include "gwordvar.h"
static const char *TAG = "main";
static const uint8_t auchCRCHi[] =
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRC??????*/
static const uint8_t auchCRCLo[] =
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
uint16_t crc16(uint8_t *puchMsg, uint16_t usDataLen)
{
uint8_t uchCRCHi = 0xFF ; /* ?CRC????? */
uint8_t uchCRCLo = 0xFF ; /* ?CRC ????? */
uint32_t uIndex ; /* CRC?????? */
while (usDataLen--) /* ??????? */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* ??CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)
#pragma pack(0x10)
uint16_t gWordVar[gWORD_SIZE];
uint8_t gBitVar[(gBIT_SIZE+7)/8];
#pragma pack()
int isBitHI(uint16_t Add)
{
if(gBitVar[(Add)>>3] & (1<<((Add)&0x07)))
{
return 1;
}
else
{
return 0;
}
}
void ModBusBitWriteHook(uint16_t addr, uint16_t length)
{
}
// 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);
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);
// }
}
int ModbusSlaveProcess(uint8_t *txbuf, uint8_t *rxbuf, uint16_t rxLen, int is_crc)
{
uint16_t crcData,crcChk;
uint8_t Offset,ByteAdd;
uint16_t ByteNumber;
uint16_t add;
uint16_t length;
int out_len = 0;
int i;
uint8_t *pDat;
uint16_t *pWordVar;
if(rxLen<4){
return 0;
}
/*地址校验*/
if((rxbuf[0]==MODBUS_SALVE_ADDRESS) || (rxbuf[0]==255)){
/*crc校验*/
if(is_crc != 0){
crcData = rxbuf[rxLen-1]+(rxbuf[rxLen-2]<<8);
crcChk = crc16(rxbuf,rxLen-2);
if( crcData != crcChk){
return 0;
}
}
add = ((uint16_t)rxbuf[2]<<8)+ rxbuf[3];
length = (rxbuf[4]<<8) | rxbuf[5];
txbuf[0] = rxbuf[0];
switch(rxbuf[1])
{
case 0x01: //Read Coils
if((add+length) > gBIT_SIZE)
{
txbuf[1] = 0x81;
txbuf[2] = 0x02; //ILLEGAL DATA ADDRESS
out_len = 3;
break;
}
txbuf[1]=0x01;
ByteNumber = (length+7)/8;
txbuf[2]= ByteNumber;
ByteAdd = add>>3; //add/8
Offset = add&0x07; //add%8
for(i=0; i<(ByteNumber-1); i++)
{
txbuf[3+i] = gBitVar[ByteAdd+i]>>Offset;
txbuf[3+i] |= gBitVar[ByteAdd+i+1]<<(8-Offset);
}
txbuf[3+ByteNumber-1] = gBitVar[ByteAdd+ByteNumber-1]>>Offset;
txbuf[3+ByteNumber-1] &= 0xff>>Offset;
out_len = ByteNumber+3;
break;
case 0x03:
case 0x04: //Read Holding Registers
if((add+length) > gWORD_SIZE)
{
txbuf[1] = 0x80 + rxbuf[1];
txbuf[2] = 0x02; //ILLEGAL DATA ADDRESS
out_len = 3;;
break;
}
if(length > 512)
{
length = 512;
}
if(rxbuf[1]==4)
{
add += 64;
}
txbuf[1]=rxbuf[1];
ByteNumber = length*2;
txbuf[2]= ByteNumber&0xff;
pDat = &txbuf[3];
pWordVar = (uint16_t *)&gWordVar[add];
for(i=0; i<length; i++)
{
*pDat++ = *pWordVar>>8;
*pDat++ = *pWordVar&0xff;
pWordVar++;
}
out_len = ByteNumber+3;
break;
case 0x05: //Write Single Coil
if(add >= gBIT_SIZE)
{
txbuf[1] = 0x85;
txbuf[2] = 0x02; //ILLEGAL DATA ADDRESS
out_len = 3;
break;
}
ByteAdd = add>>3; //same add/8
Offset = add&0x07; //same add%8
if(rxbuf[4] == 0)
{
clrBit(add);
}
else if(rxbuf[4] == 0xff)
{
setBit(add);
}
else
{
txbuf[1] = 0x85;
txbuf[2] = 0x03; //ILLEGAL DATA VALUE
out_len = 3;
break;
}
memcpy(txbuf,rxbuf,6);
ModBusBitWriteHook(add,1);
out_len = 6;
break;
case 0x06: //Write Single Register
// ESP_LOGI(TAG, "modbus 0x06");
if(add >= gWORD_SIZE)
{
txbuf[1] = 0x86;
txbuf[2] = 0x02; //ILLEGAL DATA ADDRESS
out_len = 3;
break;
}
gWordVar[add] = (rxbuf[4]<<8)+rxbuf[5];
// ESP_LOGI(TAG, "gWordVar[%d]=0x%04x", add, gWordVar[add]);
// ESP_LOGI(TAG, "%d %d", depth_config->input_type, depth_config->port);
memcpy(txbuf,rxbuf,6);
ModBusWordWriteHook(add,1);
out_len = 6;
break;
case 0x0F: //Write Multiple Coil
if((add+length) > gBIT_SIZE)
{
txbuf[1] = 0x8F;
txbuf[2] = 0x02; //ILLEGAL DATA ADDRESS
out_len = 3;
}
txbuf[1]=0x0F;
txbuf[2] = rxbuf[2];
txbuf[3] = rxbuf[3];
txbuf[4] = 0;
txbuf[5] = length&0xff;
pDat = rxbuf+7;
for(i=0; i<length; i++)
{
if(*(pDat+(i>>3)) & (1<<(i&0x07)))
setBit(i+add);
else
clrBit(i+add);
}
ModBusBitWriteHook(add,length);
out_len = 6;
break;
case 0x10: //Write Multiple registers
if((add+length) > gWORD_SIZE)
{
txbuf[1] = 0x90;
txbuf[2] = 0x02; //ILLEGAL DATA ADDRESS
crcChk = crc16(txbuf,3);
txbuf[3] = crcChk>>8;
txbuf[4] = crcChk;
out_len = 3;
}
txbuf[1]=0x10;
txbuf[2] = rxbuf[2];
txbuf[3] = rxbuf[3];
txbuf[4]= 0;
txbuf[5]= length&0xff;
pDat = rxbuf+7;
pWordVar = (uint16_t *)&gWordVar[add];
{
for(i=0; i<length; i++)
{
*pWordVar++ = (*pDat<<8)|*(pDat+1);
pDat+=2;
}
}
// ESP_LOGI(TAG, "write gWordVar:");
// for (i = 0; i < length; i++)
// ESP_LOGI(TAG, "gWordVar[%d]=0x%04x", add + i, gWordVar[add + i]);
// ESP_LOGI(TAG, "%d %d", depth_config->input_type, depth_config->port);
ModBusWordWriteHook(add,length);
out_len = 6;
break;
}//switch(rxbuf[1])
if(is_crc && out_len > 0)
{
crcChk = crc16(txbuf,out_len);
txbuf[out_len++] = crcChk>>8;
txbuf[out_len++] = crcChk & 0xff;
}
}
return out_len;
}

25
main/modbus/inc/ModbusS.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef _MODBUS_H
#define _MODBUS_H
#include <stdint.h>
#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

View File

@ -0,0 +1,29 @@
#ifndef __GWORDVAR_H
#define __GWORDVAR_H
#include <stdint.h>
#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

View File

@ -0,0 +1,11 @@
#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

View File

@ -0,0 +1,82 @@
#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);
}

282
main/peripheral/bl0939.c Normal file
View File

@ -0,0 +1,282 @@
#include <string.h>
#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 "bl0939.h"
#include "depth.h"
#include "gwordvar.h"
#include "utils.h"
#define TAG "BL0939"
static spi_device_handle_t spi1;
move_t *pMoveCtx = (move_t *)&gWordVar[MOVE_REG_ADDR];
static void SPI1_Init(void)
{
esp_err_t ret;
spi_bus_config_t buscfg1 = {
.miso_io_num = SPI1_PIN_NUM_MISO,
.mosi_io_num = SPI1_PIN_NUM_MOSI,
.sclk_io_num = SPI1_PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 128
};
spi_device_interface_config_t devcfg1 = {
.clock_speed_hz = 8 * 100 * 1000, // Clock out at 800kHz
.mode = 1, // SPI mode 1
.spics_io_num = SPI1_PIN_NUM_CS, // CS pin
.queue_size = 7, // We want to be able to queue 7 transactions at a time
// .command_bits = 8,
// .pre_cb = lcd_spi_pre_transfer_callback, // Specify pre-transfer callback to handle D/C line
};
// Initialize the SPI bus
ret = spi_bus_initialize(BL0939_HOST, &buscfg1, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
// Attach the ADS1220 to the SPI bus
ret = spi_bus_add_device(BL0939_HOST, &devcfg1, &spi1);
ESP_ERROR_CHECK(ret);
}
void bl0939_spi_reset(void);
static void BL0939_SPI_TransmitReceive(uint8_t *tbuff, uint8_t *rbuff,
uint16_t len)
{
esp_err_t ret;
spi_transaction_t t;
memset(&t, 0, sizeof(t)); // Zero out the transaction
t.tx_buffer = tbuff;
t.rx_buffer = rbuff;
t.length = len * 8; // Command is 16 bits
ret = spi_device_polling_transmit(spi1, &t); // Transmit!
assert(ret == ESP_OK);
}
static uint32_t bl0939_read_reg(uint8_t reg)
{
uint8_t tx_buf[6] = {0x55, reg, 0, 0, 0, 0};
uint8_t rx_buf[6] = {0};
// bl0939_spi_reset();
BL0939_SPI_TransmitReceive(tx_buf, rx_buf, 6);
if (rx_buf[5] == (uint8_t) ~(0x55 + reg + rx_buf[2] + rx_buf[3] + rx_buf[4]))
{
return (uint32_t)rx_buf[2] << 16 |
(uint32_t)rx_buf[3] << 8 |
(uint32_t)rx_buf[4] << 0;
}
return 0;
}
uint32_t r_temp = 0;
static int bl0939_write_reg(uint8_t reg, uint32_t val, int check)
{
int i = 5;
uint8_t h = val >> 16;
uint8_t m = val >> 8;
uint8_t l = val >> 0;
do
{
i--;
vTaskDelay(5);
// bl0939_spi_reset();
uint8_t tx_buf[6] = {0xA5, reg, h, m, l, ~(0XA5 + reg + h + m + l)};
uint8_t rx_buf[6] = {0};
BL0939_SPI_TransmitReceive(tx_buf, rx_buf, 6);
vTaskDelay(10);
if (0 == check)
return 0;
r_temp = bl0939_read_reg(reg);
if (r_temp == val)
return 0;
} while (i > 0);
return 1;
}
void bl0939_spi_reset(void)
{
uint8_t tx_buf[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 软复位SPI接口
uint8_t rx_buf[6] = {0};
BL0939_SPI_TransmitReceive(tx_buf, rx_buf, 6);
}
uint32_t comp_threshold(float mA)
{
return (uint32_t)(mA * 1 * 324004 * 0.00140625f * 0.95f / (600 * 1.218f));
}
void bl0939_reset(void)
{
bl0939_spi_reset();
bl0939_write_reg(0x19, 0x005a5a5a, 0); // 0x5a5a5a软件复位用户寄存器区
bl0939_write_reg(0x1a, 0x00000055, 1); // 寄存器写保护0x55可以写其他值不能写
bl0939_write_reg(0x10, 0xffff, 0); // Threshold A 电流通道快速有效值控制寄存器
bl0939_write_reg(0x1E, 0xffff, 1); // Threshold B
bl0939_write_reg(0x18, 0x00002000, 1); // 用户模式选择寄存器
bl0939_write_reg(0x1B, 0x000047ff, 0); // 温度模式控制寄存器
bl0939_write_reg(0x1a, 0x00000000, 1); // 开启寄存器写保护
}
// T = 40ms
int bl0939_get_current_A()
{
bl0939_spi_reset();
uint32_t Ia = bl0939_read_reg(0x00);
// return Ia * 1.218f / (float) ( 324004 * 1 );
return Ia;
}
// T = 40ms
int bl0939_get_current_B()
{
bl0939_spi_reset();
uint32_t Ib = bl0939_read_reg(0x07);
// return Ib * 1.218f / (float) ( 324004 * 1 );
return Ib;
}
// T = 400ms
int bl0939_get_voltage()
{
bl0939_spi_reset();
uint32_t v = bl0939_read_reg(0x06);
// return v * 1.218f * ( 2 + 2000 ) / (float) ( 79931 * 2 * 1000 );
return v;
}
/// @brief
uint8_t bl0939_cmd[36] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x55, 0x00, 0, 0, 0, 0, // A通道快速有效值无符号 24bit
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x55, 0x07, 0, 0, 0, 0, // B通道快速有效值无符号 24bit
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x55, 0x06, 0, 0, 0, 0}; // 电压有效值寄存器,无符号 24bit
int check_sum_ch(uint8_t *buf, int offset)
{
uint8_t sum = ~(0x55 + bl0939_cmd[offset - 1] + buf[offset] + buf[offset + 1] + buf[offset + 2]);
if (buf[offset + 3] == sum)
{
return 1;
}
return 0;
}
uint32_t readUint24LE(uint8_t *buf, int offset)
{
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
}
uint32_t readUint24BE(uint8_t *buf, int offset)
{
return buf[offset] << 16 | buf[offset + 1] << 8 | buf[offset + 2];
}
// __IO uint8_t bl0939_Transfer_done = 0;
uint8_t bl0939_Transfer_done = 0;
void bl0939_init(void)
{
bl0939_reset();
}
float ac_current_coef[3] = {
1.218f / (324004.f * 0.225 * 1000 / 2000) * 100.f,
1.218f / (324004.f * 0.23 * 1000 / 2000) * 100.f,
1.218f / (79931.f * 0.002 * 500) * 100.f};
uint8_t bl0939_rxbuf[2][36];
int32_t ac_ad_values[3] = {0};
int move_time = 0;
int move_req = 0;
extern uint16_t gWordVar[];
int move_status = 0;
void BL0939_task()
{
int index = 0;
while (1)
{
vTaskDelay(pdMS_TO_TICKS(100));
// ESP_LOGI(TAG, "BL0939_SPI_TransmitReceive before\n ");
bl0939_Transfer_done = 1;
BL0939_SPI_TransmitReceive(bl0939_cmd, bl0939_rxbuf[index & 1], 36);
if (!memcmp(bl0939_rxbuf[0], bl0939_rxbuf[1], sizeof(bl0939_rxbuf[0]))) /* 数据没有变化不处理 */
{
index++;
bl0939_Transfer_done = 0;
// ESP_LOGI(TAG, "bl0939 data not change");
// continue;
}
// ESP_LOGI(TAG, "BL0939_SPI_TransmitReceive after\n ");
if (bl0939_Transfer_done)
{
int ch;
// ESP_LOGI(TAG, "bl0939_Transfer_done \n ");
bl0939_Transfer_done = 0;
for (ch = 0; ch < 3; ch++)
{
if (check_sum_ch(bl0939_rxbuf[index & 1], 8 + ch * 12))
{
ac_ad_values[ch] = readUint24BE(bl0939_rxbuf[index & 1], 8 + ch * 12);
// ESP_LOGI(TAG, "bl0939 channel:%d ac_ad_values:%d", ch, ac_ad_values[ch]);
gWordVar[AC_CURRENT_REG_ADDR + ch] = ac_ad_values[ch] * ac_current_coef[ch];
// ESP_LOGI(TAG, "bl0939 channel:%d value:%d", ch, gWordVar[AC_CURRENT_REG_ADDR + ch]);
}
// ac_ad_values[ch] = readUint24BE(bl0939_rxbuf,8+ch*12);
// ESP_LOGI(TAG, "channel : %d ac_ad_values: %d\n ", ch, ac_ad_values[ch]);
}
if (pMoveCtx->status == 0)
{ // 停止状态,等待启动
// ESP_LOGI(TAG, "mov status is off");
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 + move_current_channel] > depth_config->current_on_threshold)
{
if (++pMoveCtx->time_count > depth_config->move_on_duratino)
{
pMoveCtx->status = 1;
pMoveCtx->time_count = 0;
pMoveCtx->pile_inc_req = 1;
// ESP_LOGI(TAG, "cur > th, status trun to on");
}
}
}
else if (pMoveCtx->status == 1)
{
// ESP_LOGI(TAG, "mov status is on");
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 (++pMoveCtx->time_count > depth_config->move_off_duration)
{
pMoveCtx->status = 0;
pMoveCtx->time_count = 0;
// ESP_LOGI(TAG, "cur > th, status trun to off");
}
}
}
}
}
}
void BL0939_init(void)
{
SPI1_Init();
bl0939_init();
xTaskCreate(BL0939_task, "BL0939_task", 4096, NULL, 10, NULL);
}

View File

@ -0,0 +1,161 @@
#include <string.h>
#include "esp_log.h"
#include "config.h"
#include "fram.h"
#include "flow.h"
#include "depth.h"
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 float ac_current_coef[3]; //可能表示交流电电流的系数或校准参数 ?
// 三标一号机
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 = {
.magic = 0,
.input_type = 1,
.min_flow = {0, 0},
.ad_cal = {
{ .flow_min = 0, .flow_max = 10000 },
{ .flow_min = 0, .flow_max = 10000 },
},
.pulse_coef = {6944, 6944},
.rsv = {0, 0, 0, 0, 0, 0}
};
*/
// const flow_config_t default_flow_cfg = {0,1,{60,60},{{0,20000},{0,20000}},{6944,6944}}; //脉冲输入 12m/H
// const depth_config_t default_depth_cfg = {0, 2,0, 1000, 32, -100, 12000, 100, -100, 1000,500, 500, 100, 150, 150}; // 方向脉冲编码器 10线2倍频
const depth_config_t default_depth_cfg = {
.magic = 0,
.input_type = 0,
.port = 1,
.N = 1000,
.M = 640,
.min_depth = -100,
.max_depth = 12000,
.sample_depth = 100,
.depth_offset = -100,
.min_valid_depth = 1000,
.inc_pile_depth = 5000,
.current_on_threshold = 500,
.current_off_threshold = 100,
.move_on_duratino = 150,
.move_off_duration = 150,
.move_current_channel = 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};
uint16_t last_pile_id = 0;
/*fram_read */
/*
I2C 线 ESP32 FRAM
param:
param:
param:
*/
void config_load(void)
{
uint16_t temp[2];
fram_read(0, &temp, sizeof(temp));//通过调用 fram_read 函数将 FRAM 中的两个 uint16_t 数据读取到 temp 数组中,起始地址为 0长度为两个 uint16_t 的大小
{
if (temp[0] == MAGIC)
{
last_pile_id = temp[1];
}
}
fram_read(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma));
if (cal_4_20ma->magic != MAGIC)
{
ESP_LOGI(TAG, "fram_read cal_4_20ma failed, use default value");
memcpy(cal_4_20ma, &default_cal_4_20ma, sizeof(default_cal_4_20ma));
}
ESP_LOGW(TAG, "load cal_4_20ma:0x%x 0x%x 0x%x 0x%x 0x%x", (unsigned int)cal_4_20ma->magic, (unsigned int)cal_4_20ma->ch[0].ad_4ma, (unsigned int)cal_4_20ma->ch[0].ad_20ma, (unsigned int)cal_4_20ma->ch[1].ad_4ma, (unsigned int)cal_4_20ma->ch[1].ad_20ma);
fram_read(EE_FLOW_CFG_ADDR, flow_config, sizeof(default_flow_cfg));
if (flow_config->magic != MAGIC)
{
ESP_LOGW(TAG, "fram_read flow_config failed, use default value");
memcpy(flow_config, &default_flow_cfg, sizeof(default_flow_cfg));
}
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)
{
ESP_LOGW(TAG, "fram_read depth_config failed, use default value");
memcpy(depth_config, &default_depth_cfg, sizeof(default_depth_cfg));
}
ESP_LOGW(TAG, "load 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", \
(unsigned int)depth_config->magic, (unsigned int)depth_config->input_type, (unsigned int)depth_config->port, \
(unsigned int)depth_config->N, (unsigned int)depth_config->M, (unsigned int)depth_config->min_depth, (unsigned int)depth_config->max_depth, \
(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
}
//恢复默认配置
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));
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));
}
void save_cal_4_20ma(void)
{
uint16_t a = 1;
ESP_LOGW(TAG, "save_cal_4_20ma:0x%x 0x%x 0x%x 0x%x 0x%x", (unsigned int)cal_4_20ma->magic, (unsigned int)cal_4_20ma->ch[0].ad_4ma, (unsigned int)cal_4_20ma->ch[0].ad_20ma, (unsigned int)cal_4_20ma->ch[1].ad_4ma, (unsigned int)cal_4_20ma->ch[1].ad_20ma);
cal_4_20ma->magic = MAGIC;
cal_4_20ma->magic = fram_write(EE_CAL_4_20MA_ADDR, cal_4_20ma, sizeof(default_cal_4_20ma));
}
void save_flow_cfg(void)
{
ESP_LOGW(TAG, "save_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]);
flow_config->magic = MAGIC;
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", \
(unsigned int)depth_config->magic, (unsigned int)depth_config->input_type, (unsigned int)depth_config->port, \
(unsigned int)depth_config->N, (unsigned int)depth_config->M, (unsigned int)depth_config->min_depth, (unsigned int)depth_config->max_depth, \
(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);
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};
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里的数据
}

View File

@ -0,0 +1,95 @@
#include <stdio.h>
#include "driver/i2c.h"
#include "freertos/FreeRTOS.h"
#include "esp_system.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "fram.h"
static const char *TAG = "fram";
/**
* @brief i2c master initialization
*/
esp_err_t i2c_master_init(void)
{
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
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)
{
esp_err_t ret;
uint8_t slave_addr = (0xA0) | ((addr >> 8) & 0x7);/*page select*/
uint8_t low_addr = addr &0xff;
// return HAL_I2C_Mem_Write(&hi2c1,slave_addr,addr&0xff,I2C_MEMADD_SIZE_8BIT,buf,len,200);
// ret = i2c_master_write_to_device(I2C_MASTER_NUM, slave_addr, txbuf, len+1, 10);
// // ret = i2c_master_write_read_device(I2C_MASTER_NUM, slave_addr, buf, len, 10);
// // assert(ret == ESP_OK);
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, slave_addr | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write(cmd, &low_addr, 1, ACK_CHECK_EN);
i2c_master_write(cmd, buf, len, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
if (ret != ESP_OK) {
printf("esp_err : %s \n", esp_err_to_name(ret));
return ret;
}
ESP_LOGI(TAG,"fram_write succeed\n");
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);
esp_err_t ret;
uint8_t slave_addr = (0xA0>>1) | ((addr >> 8) & 0x7);/*page select*/
uint8_t low_addr = addr &0xff;
// return HAL_I2C_Mem_Read(&hi2c1,slave_addr,addr&0xff,I2C_MEMADD_SIZE_8BIT,buf,len,200);
ret = i2c_master_write_read_device(I2C_MASTER_NUM, slave_addr, &low_addr,1, buf, len, 10);
if (ret != ESP_OK) {
ESP_LOGE(TAG,"esp_err : %s \n", esp_err_to_name(ret));
return ret;
}
ESP_LOGI(TAG,"fram_read succeed\n");
// ESP_LOGI(TAG, "buf value : %d \n ", buf[0]);
return 0;
}
void save_para(void)
{
}
void save_encode(void)
{
}
void read_para()
{
}
void clear_para()
{
}

View File

@ -0,0 +1,19 @@
#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

View File

@ -0,0 +1,24 @@
#ifndef __FRAM_H
#define __FRAM_H
#include <stdint.h>
#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

481
main/peripheral/depth.c Normal file
View File

@ -0,0 +1,481 @@
#include <string.h>
#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);
}

89
main/peripheral/depth_.c Normal file
View File

@ -0,0 +1,89 @@
#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 <string.h>
#include <stdio.h>
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_));
}

View File

@ -0,0 +1,233 @@
#include <stdlib.h>
#include <string.h>
#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;
}

216
main/peripheral/flow/flow.c Normal file
View File

@ -0,0 +1,216 @@
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -0,0 +1,70 @@
#ifndef __ADS1220_H
#define __ADS1220_H
#include <stdint.h>
#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

View File

@ -0,0 +1,51 @@
#ifndef __FLOW_H
#define __FLOW_H
#include <stdint.h>
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

View File

@ -0,0 +1,14 @@
#ifndef __INPUT_TYPE2_H
#define __INPUT_TYPE2_H
#include <stdint.h>
#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

View File

@ -0,0 +1,78 @@
#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();
}

View File

@ -0,0 +1,33 @@
#ifndef __BL0939_H
#define __BL0939_H
#include <stdint.h>
#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

View File

@ -0,0 +1,95 @@
#ifndef __DEPTH_H
#define __DEPTH_H
#include <stdint.h>
#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

13
main/peripheral/inc/led.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef __LED_H
#define __LED_H
#include "driver/gpio.h"
#define LED1_GPIO_PIN 9
#define LED2_GPIO_PIN 10
#define GPIO_OUTPUT_PIN_SEL ((1ULL << LED1_GPIO_PIN) | (1ULL << LED2_GPIO_PIN))
void led_init(void);
void LED_Toggle(gpio_num_t gpio_num);
#endif

28
main/peripheral/led.c Normal file
View File

@ -0,0 +1,28 @@
#include "led.h"
void led_init(void)
{
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
}
void LED_Toggle(gpio_num_t gpio_num)
{
static unsigned char flg = 1;
if (flg)
{
gpio_set_level(gpio_num, 0);
flg = 0;
}
else
{
gpio_set_level(gpio_num, 1);
flg = 1;
}
}

View File

@ -58,3 +58,15 @@ int scale(int raw, int raw_min, int raw_max,int eng_min, int eng_max)
}
return result;
}
int abs_sub_uint32(uint32_t a, uint32_t b)
{
if (a >= b)
{
return a - b;
}
else
{
return (0xffffffff - b + a + 1);
}
}

30
main_old/CMakeLists.txt Normal file
View File

@ -0,0 +1,30 @@
set(SRCS
"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"
"./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 "." "./communication_pad/inc")
idf_component_register(SRCS ${SRCS}
INCLUDE_DIRS ${INCLUDE_DIRS})

View File

@ -0,0 +1,45 @@
menu "Example Configuration"
config ESP_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config ESP_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config ESP_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
choice ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD
prompt "WiFi Scan auth mode threshold"
default ESP_WIFI_AUTH_OPEN
help
The weakest authmode to accept in the scan mode.
config ESP_WIFI_AUTH_OPEN
bool "OPEN"
config ESP_WIFI_AUTH_WEP
bool "WEP"
config ESP_WIFI_AUTH_WPA_PSK
bool "WPA PSK"
config ESP_WIFI_AUTH_WPA2_PSK
bool "WPA2 PSK"
config ESP_WIFI_AUTH_WPA_WPA2_PSK
bool "WPA/WPA2 PSK"
config ESP_WIFI_AUTH_WPA3_PSK
bool "WPA3 PSK"
config ESP_WIFI_AUTH_WPA2_WPA3_PSK
bool "WPA2/WPA3 PSK"
config ESP_WIFI_AUTH_WAPI_PSK
bool "WAPI PSK"
endchoice
endmenu

8
main_old/component.mk Normal file
View File

@ -0,0 +1,8 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#

167
main_old/main.c Normal file
View File

@ -0,0 +1,167 @@
/* 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 <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.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 <stdio.h>
#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"
/* 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 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)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(i2c_master_init());
//restore_default();
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();
ads1220_task_start(); /* 两路电流AD采样获取瞬时流量计算累计流量目前配置的是10HZ取决于SPS */
BL0939_init(); /* 实时采集通道电流根据depth_config_t中配置的启动与结束电流以及持续时间进行move_t机器开关状态的判断 */
DEPTH_init(); /* 编码器计算深度同时进行流量的按深度计数以及record的记录 */
FLOW_init(); /* 两一种计算流量的方法,计算累计流量 */
uart0_modbus_slave_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);
}

View File

@ -0,0 +1,89 @@
#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 <string.h>
#include <stdio.h>
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_));
}

1960
main_old/sdkconfig Normal file

File diff suppressed because it is too large Load Diff

72
main_old/stm32/utils.c Normal file
View File

@ -0,0 +1,72 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "utils.h"
#include <stdio.h>
#include <string.h>
int GetCompileDateTime(uint16_t *DateTime)
{
const int MONTH_PER_YEAR=13;
static char szEnglishMonth[][4] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
char szTmpDate[40]= {0};
char szTmpTime[20]= {0};
char szMonth[4]= {0};
int iYear,iMonth,iDay,iHour,iMin,iSec;//,,
int i;
//获取编译日期、时间
sprintf(szTmpDate,"%s",__DATE__); //"Sep 18 2010"
sprintf(szTmpTime,"%s",__TIME__); //"10:59:19"
sscanf(szTmpDate,"%s %d %d",szMonth,&iDay,&iYear);
sscanf(szTmpTime,"%d:%d:%d",&iHour,&iMin,&iSec);
for(i=0; MONTH_PER_YEAR; i++)
{
if(strncmp(szMonth,szEnglishMonth[i],3)==0)
{
iMonth=i+1;
break;
}
}
//printf("%d,%d,%d,%d,%d,%d\n",iYear,iMonth,iDay,iHour,iMin,iSec);
//sprintf(szDateTime,"%04d-%02d-%02d %02d:%02d:%02d",iYear,iMonth,iDay,iHour,iMin,iSec);
DateTime[0] = iYear;
DateTime[1] = iMonth*100;
DateTime[1] += iDay;
DateTime[2] = iHour*100;
DateTime[2] += iMin;
return 0;
}
uint32_t TickDiff(uint32_t comptime)
{
uint32_t nowtime = xTaskGetTickCount();
if(nowtime >= comptime)
return (nowtime - comptime);
else
return (0 - (comptime - nowtime));
}
int scale(int raw, int raw_min, int raw_max,int eng_min, int eng_max)
{
int result = 0;
if(raw_max != raw_min)
{
result = (raw - raw_min) * (eng_max - eng_min) / (raw_max - raw_min) + eng_min;
}
return result;
}
int abs_sub_uint32(uint32_t a, uint32_t b)
{
if (a >= b)
{
return a - b;
}
else
{
return (0xffffffff - b + a + 1);
}
}

View File

@ -1,6 +1,9 @@
#ifndef _UTILS_H_
#define _UTILS_H_
int GetCompileDateTime(uint16_t *DateTime);
extern uint32_t TickDiff(uint32_t comptime);
uint32_t TickDiff(uint32_t comptime);
int abs_sub_uint32(uint32_t a, uint32_t b);
#endif