#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" #define TAG "ADS1220" #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 // To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use, // but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this. #define PARALLEL_LINES 16 static spi_device_handle_t spi2; /*************************************************** * *ADS1220���� *1.������ADS1220�������ӵ����Ŷ˿� * * * * */ /****************ADS1220���ź궨��*******************/ #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 // ͨ��1 #define Channal2 0x10 // ͨ��2 #define Channal3 0x20 // ͨ��3 #define Channal4 0x30 // ͨ��4 #define ADS1220_REG0 0x00 // �Ĵ��� 0 #define ADS1220_REG1 0x01 // �Ĵ��� 1 #define ADS1220_REG2 0x02 // �Ĵ��� 2 #define ADS1220_REG3 0x03 // �Ĵ��� 3 #define PGAGain1 0x00 // PGA���� Ĭ�� #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 // ͨ��1 #define ADS1220_Channal2 1 // ͨ��2 #define ADS1220_Channal3 2 // ͨ��3 #define ADS1220_Channal4 3 // ͨ��4 #define LED1_GPIO_PIN 9 #define LED2_GPIO_PIN 10 #define GPIO_OUTPUT_PIN_SEL ((1ULL << LED1_GPIO_PIN) | (1ULL << LED2_GPIO_PIN)) #define GPIO_INPUT_IO_39 7 #define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO_39) // #define GPIO_INPUT_IO_1 5 // #define GPIO_INPUT_PIN_SEL ((1ULL<cap_value; xQueueSendFromISR(gpio_evt_queue, &ad_update_time[ch], NULL); } static void GPIO_Init(void) { // zero-initialize the config structure. gpio_config_t io_conf = {}; // disable interrupt io_conf.intr_type = GPIO_INTR_DISABLE; // set as output mode io_conf.mode = GPIO_MODE_OUTPUT; // bit mask of the pins that you want to set,e.g.GPIO18/19 io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; // disable pull-down mode io_conf.pull_down_en = 0; // disable pull-up mode io_conf.pull_up_en = 0; // configure GPIO with the given settings gpio_config(&io_conf); // 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 gpio_evt_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, 0x00); // �Ĵ���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]); } void LED2_Toggle(void) { static unsigned char flg = 1; if (flg) { gpio_set_level(LED2_GPIO_PIN, 0); flg = 0; } else { gpio_set_level(LED2_GPIO_PIN, 1); flg = 1; } } 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 uint8_t timeout[2]; 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(gpio_evt_queue, &io_num, 200)) { int ad_ch; ads1220_watchdog = 0; 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); ad_watchdog_cnt = 0; LED2_Toggle(); if ((ad_ch == 1 || ad_ch == 3) && flow_config->input_type == 1) { int flow_ch = ad_ch / 2; 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_; } // 累计流量计算 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; pflow[flow_ch].update_time = ad_update_time[ad_ch]; timeout[flow_ch] = 0; //if (ad_ch == 3) 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 { ADS1220_Init(); } if (zero_totalflow_req) { zero_totalflow_req = 0; zero_totalflow(0); zero_totalflow(1); } } } 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