RuiViana

Frequencimetro.c

Aug 25th, 2020
208
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ESP32_FreqMeter_0.40.0.ino
  2.  
  3. // V01 Teste com pcnt
  4. // V02 teste com timer
  5. // V03 Teste de interrupt
  6. // V04 Definicao com escala baseada no prescaler
  7. // V05 Calculos com interrupt
  8. // V06 Versão inicial do frequeciimetro com ESP32 nao esta preciso , Seleciona a escala.
  9. // V07 Modificacoes no loop pra melhorar a escala  funcionou bem
  10. // V07_A Fixando o valor de prescaler em 80   Criada 5a escala
  11. // V07_B teste de erro na rotina pcnt
  12. // V08 Sem escala, fixando o prescaler e o timer e contando os overflows
  13. // V09 Limpando a V08
  14. // V10 Testes com rotina de contagem de overflow
  15. // V11 Teste de overflow de pcnt e timer  funciona  teste com frequenci DE 10 khZ  Copia do frequencimetro 2 modificado
  16. // V12 Resumir e limpar V11  enroscou a partir de 300 KHz
  17. // V13 Consegui bom resultado deste aqui até 20MHz Usando RMT com referencia de tempo
  18. // V14 Interrupt de pcnt e contar tempo de RMT
  19. // V15 Novo teste com RMT
  20. // V16 Qtde de pulsos entre ocorrencias de interrupt
  21. // V17 Outro teste de ocorrencias de interrupt
  22. // V18 Teste com rotina de interrupt com poucas funcoes
  23. // V19 Teste com esp-timer  e interrupt no fim do pulso do esp-timer
  24. // V20 Teste = V19
  25. // V20a Preparada para IDF
  26. // V20aGustavo Sem interrupt de esp-timer
  27. // V21 Inclusao de LCD com diretivas de compilacao
  28. // 0.0.21 = V21
  29. // 0.0.22  Pontuação do numero
  30. // V23 Teste com 2 rotinas de pontuacao
  31. // V24 Parametros de ledc calculados   Diretivas de compilacao para ARDUINO e IDF
  32. // V25 Nova rotina de pontuação
  33. // V26 Usando printf na rotina de pontuacao
  34. // V27 Teste com IDF  Compilou com a IDF do CEI
  35. // V28 Teste com nova rotina de pontuacao e printf
  36. // V30 Rotina de teste depois de erro no IDF e limpeza de variaveis desnecessarias e organização
  37. // V31 Nova Diretiva de compilação  ARDUINO   Inclusão de LCD  ok
  38. // V32 Novamente com rotinas de LCD Mudanca do formato dos port GPIO
  39. // V33 Calculo de Resolucao com base na frequencia e duty de 50%, inclusao de LCD I2C com diretiva e teste gpio matrix incluido
  40. // V34 medir o Duty do pulso recebido até 50HKz funcionou mas não ficou boa Removi
  41. // V35 testar LCD com IDF   Funcionou muito bem Necessita 1 blilioteca hd44780.h.   https://github.com/UncleRus/esp-idf-lib
  42. // V36  testar com LCD I2C IDF   teste Necessita 3 bliliotecas i2cdev.h, pcf8574.h, hd44780.h.  https://github.com/UncleRus/esp-idf-lib
  43. // V37  testar com LCD I2C IDF   Funcionou muito bem   Necessita 3 bliliotecas i2cdev.h, pcf8574.h, hd44780.h.  https://github.com/UncleRus/esp-idf-lib
  44. // V38 = V37 reorganizado e com diretivas  Necessita 3 bliliotecas i2cdev.h, pcf8574.h, hd44780.h.  https://github.com/UncleRus/esp-idf-lib
  45. //                                                          comentadas as linhas  #include "esp_idf_lib_helpers.h" nas 3 blibliotecas
  46. // V39  = V38  Removi os {}; dos inits e dos configs
  47.  
  48. // V40  = Entrada de frquencia via uart
  49.  
  50.  
  51. /*
  52.  
  53.   Desenvolvedores: Rui Viana e Gustavo Murta   08/jul/2020
  54.  
  55.   Para desenvolver este projeto, foram aproveitadas partes de códigos dos desenvolvedores
  56.   abaixo referenciados.
  57.  
  58.   O Projeto:
  59.   Um frequencímetro usando ESP32, sem necessidade de escalas e mostrando até 8 dígitos,
  60.   medindo com precisão até 20MHz ou mais.
  61.   Este projeto pode ser compilado com a IDE do arduino ou com o IDF
  62.  
  63.   Definições:
  64.  
  65.   #define PCNT_INPUT_SIG_IO     GPIO_NUM_34                                 // Freq Meter Input GPIO 34
  66.   #define LEDC_HS_CH0_GPIO      GPIO_NUM_25
  67.  
  68.   #define PCNT_INPUT_CTRL_IO    GPIO_NUM_35                                 // Count Control GPIO HIGH=count up, LOW=count down GPIO 25
  69.   #define OUTPUT_CONTROL_GPIO   GPIO_NUM_32                                 // Saida do timer GPIO 2
  70.  
  71.   PORT de entrada do frequencímetro PCNT_INPUT_SIG_IO (GPIO 34)
  72.   PORT de entrada de controle PCNT_INPUT_CTRL_IO      (GPIO 35)
  73.   PORT de saída do timer OUTPUT_CONTROL_GPIO          (GPIO 32)
  74.   O PORT de entrada de controle (GPIO 35) deve ser ligado ao PORT de saída do timer (GPIO 32).
  75.   Estes são os ports usados no projeto, mas podem ser modificados para sua melhor conveniência.
  76.  
  77.   O frequencímetro é dividido em 5 partes:
  78.     1. Contador de pulsos;
  79.     2. Controle de tempo de contagem;
  80.     3. Impressão do resultado;
  81.     4. Espaço para outras funções.
  82.     5. Gerador de sinais programado para 2  Hz  (ou 50.000)
  83.  
  84.   1. O contador de pulso usa o pcnt do ESP32.
  85.      O pcnt tem os seguintes parâmetros:
  86.       a. port de entrada;
  87.       b. canal de entrada;
  88.       c. port de controle;
  89.       d. contagem na subida do pulso;
  90.       e. contagem na descida do pulso;
  91.       f. contagem só com o controle em nível elevado;
  92.       g. limite máximo de contagem.
  93.  
  94.   2. O Controle de tempo de contagem usa o esp-timer.
  95.      O esp-timer tem o seguinte parâmetro:
  96.       a. controle do tempo;
  97.  
  98.   5. Gerador de frequncias para testes usa o ledc
  99.      O ledc tem o seguinte parâmetro:
  100.       a. port de saida;
  101.       b. canal de lcd;
  102.       c. frequencia;
  103.       d. resolucao do ledc;
  104.       e. duty cycle em 5;
  105.  
  106.  
  107.   Funcionamento:
  108.     O port de controle de contagem em nível alto, libera o contador para contar os pulsos que chegam no port de entrada de pulsos.
  109.   Os pulsos são contado tanto na subida quanto na descida do pulso, para melhorar a media de contagem.
  110.   O tempo de contagem é definido pelo esp-timer, e esta' definido em 1 segundo, na variável janela.
  111.   Se a contagem for maior que 20000 pulsos durante o tempo de contagem, ocorre overflow e a cada overflow que ocorre
  112.   e' contabilizado na variável multPulses, e o contador de pulso retorna a zero continuando a contar.
  113.     Quando o tempo de leitura termina, uma rotina é chamada e o valor do no contador de pulsos e' lido e salvo,
  114.     um flag e' ligado indicando que terminou a leitura dos pulsos
  115.  
  116.     No loop, ao verificar que o flag indica que terminou a leitura dos pulsos, o valor é calculado multiplicando
  117.   o numero de overflow por 20000 e somando ao numero de pulsos restantes e dividindo por 2, pois contou 2 vezes.
  118.   Como o pulsos são contados na subida e na descida, a contagem e´ o dobro da frequência.
  119.     Na frequência é insserido pontos e impressa no serial monitor.
  120.   Os registradores são resetados e o port de controle de entrada é novamente elevado para nível alto e a contagem de
  121.   pulsos se inicia.
  122.  
  123.   Tem também um gerador de sinais que gera 50.000 Hz, e pode ser usado para testes.
  124.   Este gerador pode ser alterado para gerar frequencias até 40 MHz.
  125.   Usamos o recurso ledc do ESP32 para gerar frequencia que pode ser usada como teste.
  126.     O valor da frequencia base é 2 (ou 50.000) Hz, mas pode ser digitavo outo valor no serial monitor
  127.     O duty foi fixado como 50%
  128.     A resulução é calculada.
  129.   O Port de saida deste gerador é definido na linha #define LEDC_GPIO.
  130.   Atualmente está definido como GPIO 25.
  131.  
  132.   Internamente usando GPIO matrix,o pulso de entrada foi direcionado para o LED nativo do ESP32,
  133.   assim o LED piscara na frequencia de entrada.
  134.  
  135.   O compilador usa as diretivas de compilacaoo para selecionar:
  136.    Compilador Arduino ou IDF    automatico
  137.    Uso de LCD                   LCD_ON ou LCD_OFF
  138.    Uso de LCD I2C               LCD_I2C_ON ou LCD_I2C_OFF
  139.  
  140.   Referências:
  141.   author=krzychb https://github.com/espressif/esp-idf/tree/master/examples/peripherals/pcnt
  142.   resposta by Deouss » Thu May 17, 2018 3:07 pm no tópico https://esp32.com/viewtopic.php?t=5734
  143.   Gerador de sinais Gustavo https://github.com/Gustavomurta/ESP32_frequenceMeter/blob/master/ESP32OscilatorV03.ino
  144.   Formatação de numero https://arduino.stackexchange.com/questions/28603/the-most-effective-way-to-format-numbers-on-arduino
  145.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
  146.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
  147.   Bibliotecas LCD e LCD I2C  https://github.com/UncleRus/esp-idf-lib
  148.   Exemplo uart https://github.com/espressif/esp-idf/blob/master/examples/peripherals/uart/uart_async_rxtxtasks/main/uart_async_rxtxtasks_main.c
  149.   25/08/2020
  150.  
  151.  */
  152. #define LCD_ON                                                            // Define LCD_ON, para usar LCD, se não, defina LCD_OFF
  153. #define LCD_I2C_OFF                                                       // Define LCD_I2C_ON, para usar LCD I2C, se não, defina LCD_I2C_OFF
  154.  
  155. #include "stdio.h"
  156. #include "string.h"
  157. #include "freertos/FreeRTOS.h"
  158. #include "freertos/portmacro.h"
  159. #include "freertos/task.h"
  160. #include "freertos/queue.h"
  161. #include "driver/periph_ctrl.h"
  162. #include "driver/ledc.h"
  163. #include "driver/gpio.h"
  164. #include "driver/pcnt.h"
  165. #include "driver/ledc.h"
  166. #include "esp_attr.h"
  167. #include "esp_log.h"
  168. #include "esp_timer.h"
  169. #include "sdkconfig.h"
  170. #include "driver/uart.h"
  171. #include "math.h"
  172. #include "driver/i2c.h"
  173. #include "hd44780.h"
  174. #include "pcf8574.h"
  175. #include "esp_err.h"
  176.  
  177. #define PCNT_COUNT_UNIT       PCNT_UNIT_0                                 // Unidade 0 do pcnt
  178. #define PCNT_COUNT_CHANNEL    PCNT_CHANNEL_0                              // Canal 0 do pcnt
  179.  
  180. //                 Para usar teste jumper GPIO 25 com GPIO 34
  181. //                 Port de entrada do frequencimetro  GPIO 34
  182. #define PCNT_INPUT_SIG_IO     GPIO_NUM_34                                 // Freq Meter Input GPIO 34
  183. #define LEDC_HS_CH0_GPIO      GPIO_NUM_25                                 // Saida do ledc gerador de pulsos
  184.  
  185. //                  Necessario jumper entre GPIO 32 e GPIO 35
  186. #define PCNT_INPUT_CTRL_IO    GPIO_NUM_35                                 // Count Control GPIO HIGH = count up, LOW = count down
  187. #define OUTPUT_CONTROL_GPIO   GPIO_NUM_32                                 // Saida do timer GPIO 32 Controla a contagem
  188.  
  189. #define IN_BOARD_LED          (gpio_num_t)2                               // LED nativo ESP32 GPIO 2
  190.  
  191. #define LEDC_HS_CH0_CHANNEL   LEDC_CHANNEL_0                              // LEDC no canal 0
  192. #define LEDC_HS_MODE          LEDC_HIGH_SPEED_MODE                        // LEDC em high speed
  193. #define LEDC_HS_TIMER         LEDC_TIMER_0                                // Usar timer0 do ledc
  194.  
  195. uint32_t         overflow  =  20000;                                      // Valor maximo para overflow de pcnt
  196. #define PCNT_H_LIM_VAL        overflow                                    // Limite superior de contagem
  197.  
  198. esp_timer_create_args_t create_args;                                      // Argumentos do esp-timer
  199. esp_timer_handle_t timer_handle;                                          // Instancia de esp-timer
  200.  
  201. //  Calculo do ajustes para cada faixa de frequencia
  202. //  Resolucao = log2(Clock(80MHz)/f) + 1   ex: 50.000 HZ = 80.0000/50.000 = 1.600 log2(1600) = 10 + 1 = 11
  203. //  Duty 50%  = (2**Resolucao)/2       ex: 2**11 = 2048   2048/2 = 1024
  204.  
  205. bool            flag          = true;                                     // Indicador de fim de contagem libera impressao
  206. int16_t         pulses        = 0;                                        // Contador de pulsos de entrada
  207. uint32_t        multPulses    = 0;                                        // Contador de overflows de pcnt
  208. uint32_t        janela        = 999999;                                  // Janela de 1 segundo para a contagem de pulsos
  209. uint32_t        oscilator     = 2;                                        // Frequencia em Hz
  210. uint32_t        mDuty         = 0;                                        // Valor calculado do duty
  211. uint32_t        resolucao         = 0;                                    // Valor calculado da resolucao
  212.  
  213. #ifdef LCD_I2C_ON                                                         // Se tem LCD I2C
  214. #define SDA_GPIO 22                                           // GPIO I2C SDA para o LCD
  215. #define SCL_GPIO 23                                           // GPIO I2C SCL para o LCD
  216. #define I2C_ADDR 0x38                                                     // Endereco I2C do PCF8574
  217. static i2c_dev_t pcf8574;                                                 // Instancia PCF8574
  218. #endif                                                                    // LCD I2C
  219.  
  220. #if defined LCD_ON || defined LCD_I2C_ON                                  // Se tem LCD
  221. hd44780_t lcd = {};                                                       // Instancia LCD
  222. #endif                                                                    // LCD
  223.  
  224. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;                     // variavel tipo portMUX_TYPE para sincronismo
  225.  
  226. static const int RX_BUF_SIZE = 1024;
  227.  
  228. #define TXD_PIN (GPIO_NUM_34)
  229. #define RXD_PIN (GPIO_NUM_35)
  230.  
  231. const uart_config_t uart_config = {
  232.         .baud_rate = 115200,
  233.         .data_bits = UART_DATA_8_BITS,
  234.         .parity = UART_PARITY_DISABLE,
  235.         .stop_bits = UART_STOP_BITS_1,
  236.         .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
  237. };
  238.  
  239. //----------------------------------------------------------------------------------------
  240. void initUART(void) {
  241.     // We won't use a buffer for sending data.
  242.     uart_driver_install(UART_NUM_0, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
  243.     uart_param_config(UART_NUM_0, &uart_config);
  244.     uart_set_pin(UART_NUM_0, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  245. }
  246. //----------------------------------------------------------------------------------------
  247. #ifdef LCD_I2C_ON                                                         // Se tem LCD I2C
  248. //----------------------------------------------------------------------------------------
  249. static esp_err_t write_lcd_data(const hd44780_t *lcd, uint8_t data)
  250. {
  251.     return pcf8574_port_write(&pcf8574, data);                              // Grava dados no PCF8574
  252. }
  253. //----------------------------------------------------------------------------------------
  254. void lcd_test()
  255. {
  256.     //hd44780_t lcd = {};
  257.     lcd.write_cb = write_lcd_data; // use callback to send data to LCD by I2C GPIO expander
  258.     lcd.font = HD44780_FONT_5X8;
  259.     lcd.lines = 2;
  260.  
  261.     lcd.pins.rs = 0;
  262.     lcd.pins.e  = 2;
  263.     lcd.pins.d4 = 4;
  264.     lcd.pins.d5 = 5;
  265.     lcd.pins.d6 = 6;
  266.     lcd.pins.d7 = 7;
  267.     lcd.pins.bl = 3;
  268.  
  269.     memset(&pcf8574, 0, sizeof(i2c_dev_t));
  270.     (pcf8574_init_desc(&pcf8574, 0, I2C_ADDR, SDA_GPIO, SCL_GPIO));
  271.  
  272.     (hd44780_init(&lcd));
  273.  
  274.     hd44780_switch_backlight(&lcd, true);
  275. }
  276. #endif                                                                    // LCD I2C
  277. //----------------------------------------------------------------------------------------
  278. #ifdef LCD_ON                                                             // Se tem LCD DIRETO
  279.  
  280. void lcd_init()                                                           // Rotina para inicialisar o LCD DIRETO
  281. {
  282.     lcd.font = HD44780_FONT_5X8,                                            // Define formato do caracter
  283.             lcd.lines = 2;                                                      // Numero de linhas do DIRETO
  284.                                                                                    // Pinos do LCD DIRETO
  285.             lcd.pins.rs = GPIO_NUM_5;                                                     // RS
  286.             lcd.pins.e  = GPIO_NUM_18;                                                    // Enable
  287.             lcd.pins.d4 = GPIO_NUM_19;                                                    // D4
  288.             lcd.pins.d5 = GPIO_NUM_21;                                                    // D5
  289.             lcd.pins.d6 = GPIO_NUM_22;                                                   // D6
  290.             lcd.pins.d7 = GPIO_NUM_23;                                                   // D7
  291.             lcd.pins.bl = HD44780_NOT_USED;                                                // LEd de iluminacao do LCD DIRETO
  292.  
  293.     ESP_ERROR_CHECK(hd44780_init(&lcd));                                    // Inicialisa o hd44780
  294. }
  295. #endif                                                                    // LCD DIRETO
  296. //----------------------------------------------------------------------------------------
  297. // Sem comentarios originais  https://arduino.stackexchange.com/questions/28603/the-most-effective-way-to-format-numbers-on-arduino
  298. char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos)
  299. {
  300.     int c;
  301.     if (val >= radix)
  302.         s = ultos_recursive(val / radix, s, radix, pos + 1);
  303.     c = val % radix;
  304.     c += (c < 10 ? '0' : 'a' - 10);
  305.     *s++ = c;
  306.     if (pos % 3 == 0) *s++ = '.';
  307.     return s;
  308. }
  309. //----------------------------------------------------------------------------------------
  310. // Sem comentarios originais  https://arduino.stackexchange.com/questions/28603/the-most-effective-way-to-format-numbers-on-arduino
  311. char *ltos(long val, char *s, int radix)
  312. {
  313.     if (radix < 2 || radix > 36) {
  314.         s[0] = 0;
  315.     } else {
  316.         char *p = s;
  317.         if (radix == 10 && val < 0) {
  318.             val = -val;
  319.             *p++ = '-';
  320.         }
  321.         p = ultos_recursive(val, p, radix, 0) - 1;
  322.         *p = 0;
  323.     }
  324.     return s;
  325. }
  326. //----------------------------------------------------------------------------
  327. void ledcInit ()
  328. {
  329.     resolucao = log((80000000 / oscilator) + 1) / log(2);                   // Calculo da resolucao para ledc
  330.     if (resolucao > 20) resolucao = 20;                                     // Maxima resolucao é 20
  331.     //  Serial.println(resolucao);                                          // Print
  332.     mDuty = (pow(2, resolucao)) / 2;                                        // Calculo do duty para ledc
  333.     //  Serial.println(mDuty);                                              // Print
  334.  
  335.     ledc_timer_config_t ledc_timer = {};                                    // Instancia a configuracao do timer do ledc
  336.  
  337.     ledc_timer.duty_resolution =  resolucao;              // Configura resolucao
  338.     //ledc_timer.duty_resolution = (ledc_timer_bit_t) + resolucao;          // Configura resolucao
  339.     ledc_timer.freq_hz    = oscilator;                                      // Frequencia de oscilacao
  340.     ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;                           // Mode de operacao em high speed
  341.     ledc_timer.timer_num = LEDC_TIMER_0;                                    // Usar timer0 do ledc
  342.     ledc_timer_config(&ledc_timer);                                         // Configurar o timer do ledc
  343.  
  344.     ledc_channel_config_t ledc_channel = {};                                // Instancia a configuracao canal do ledc
  345.  
  346.     ledc_channel.channel    = LEDC_HS_CH0_CHANNEL;                          // Configura canal0
  347.     ledc_channel.duty       = mDuty;                                        // Valor calculado do duty em %
  348.     ledc_channel.gpio_num   = LEDC_HS_CH0_GPIO;                             // Saida no GPIO defino no inicio
  349.     ledc_channel.intr_type  = LEDC_INTR_DISABLE;                            // Desabilita interrupt de ledc
  350.     ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;                         // Mode de operacao do canal em high speed
  351.     ledc_channel.timer_sel  = LEDC_TIMER_0;                                 // Usar timer0 do ledc
  352.  
  353.     ledc_channel_config(&ledc_channel);                                     // Configurar o canal do ledc
  354. }
  355. //----------------------------------------------------------------------------------
  356. void tempo_controle(void *p)                                              // Fim de tempo de leitura de pulsos
  357. {
  358.     gpio_set_level(OUTPUT_CONTROL_GPIO, 0);                                 // Controle do PCount - stop count
  359.     pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);                       // Obtem o valor contado
  360.     flag = true;                                                            // Informa que ocorreu interrupt de controle
  361. }
  362. //----------------------------------------------------------------------------------
  363. static void IRAM_ATTR pcnt_intr_handler(void *arg)                        // Overflow de contagem de pulsos
  364. {
  365.     portENTER_CRITICAL_ISR(&timerMux);                                      // Desabilita interrupção ?
  366.     multPulses++;                                                           // Incrementa contador de overflow
  367.     PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);                                // Limpa indicador de interrupt
  368.     portEXIT_CRITICAL_ISR(&timerMux);                                       // Libera novo interrupt
  369. }
  370. //----------------------------------------------------------------------------------
  371. void pcnt_init(void)                                                      // Rotina de inicializacao do pulse count
  372. {
  373.     pcnt_config_t pcnt_config = {};                                        // Instancia pulse config
  374.  
  375.     pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;                         // Port de entrada dos pulsos
  376.     pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;                         // Controle da contagem
  377.     pcnt_config.unit = PCNT_COUNT_UNIT;                                     // Unidade de contagem
  378.     pcnt_config.channel = PCNT_COUNT_CHANNEL;                               // Canal de contagem
  379.     pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;                             // Limite maximo de contagem
  380.     pcnt_config.pos_mode = PCNT_COUNT_INC;                                  // Conta na subida do pulso
  381.     pcnt_config.neg_mode = PCNT_COUNT_INC;                                  // Conta na descida do pulso
  382.     pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;                             // Nao usado
  383.     pcnt_config.hctrl_mode = PCNT_MODE_KEEP;                                // Se HIGH conta incrementando
  384.     pcnt_unit_config(&pcnt_config);                                         // Inicializa PCNT
  385.  
  386.     pcnt_counter_pause(PCNT_COUNT_UNIT);                                    // Inicializa o contador PCNT
  387.     pcnt_counter_clear(PCNT_COUNT_UNIT);                                    // Zera o contador PCNT
  388.  
  389.     pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);                     // Limite superior de contagem
  390.     pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);                    // Rotina de Interrupt de pcnt
  391.     pcnt_intr_enable(PCNT_COUNT_UNIT);                                      // Habilita interrup de pcnt
  392.  
  393.     pcnt_counter_resume(PCNT_COUNT_UNIT);                                   // inicia a contagem
  394. }
  395. //----------------------------------------------------------------------------------
  396. void myInit()
  397. {
  398.     initUART();
  399.  
  400. #ifdef LCD_ON                                                               // LCD direto
  401.     lcd_init();                                                             // LCD direto
  402. #endif                                                                      // LCD direto
  403.  
  404. #ifdef LCD_I2C_ON                                                           // LCD  I2C
  405.     i2cdev_init();                                         // LCD  I2C
  406.     lcd_test();                                                             // LCD  I2C
  407. #endif                                                                      // LCD  I2C
  408.  
  409.     ledcInit();                                                             // Inicializa o ledc
  410.     pcnt_init();                                                            // Inicializa o pulse count
  411.     gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);                              // Define o port decontrole
  412.     gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);              // Define o port de controle como saida
  413.  
  414.     create_args.callback = tempo_controle;                                  // Instancia o tempo de controle
  415.     esp_timer_create(&create_args, &timer_handle);                          // Cria parametros do timer
  416.  
  417.     gpio_set_direction(IN_BOARD_LED, GPIO_MODE_OUTPUT);                     // Port LED como saida
  418.  
  419.     gpio_matrix_in(PCNT_INPUT_SIG_IO, SIG_IN_FUNC226_IDX, false);           // Direciona a entrada de pulsos
  420.     gpio_matrix_out(IN_BOARD_LED, SIG_IN_FUNC226_IDX, false, false);        // Para o LED do ESP32
  421. }
  422. //---------------------------------------------------------------------------------
  423. void rxCalc()
  424. {
  425.     uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1);
  426.     const int rxBytes = uart_read_bytes(UART_NUM_0, data, RX_BUF_SIZE, 1000 / portTICK_RATE_MS);
  427.     if (rxBytes > 0)
  428.     {
  429.         char dInput[10];
  430.         oscilator = 0;
  431.         for (int i = 0; i < rxBytes; i++)
  432.         {
  433.             if(data[i] != 0x0A && data[i] != 0x0D )
  434.             {
  435.  
  436.                 dInput[i] =  data[i];
  437.             }
  438.             oscilator = atoi(dInput);
  439.         }
  440.         printf( "oscilator: %d\n",  oscilator);
  441.         if (oscilator != 0)                                                     // Se foi digitado algum valor
  442.         {
  443.             ledcInit();                                                           // Reconfigura ledc
  444.         }
  445.     }
  446.     free(data);
  447. }
  448. //---------------------------------------------------------------------------------
  449. void app_main(void)
  450. {
  451.     myInit();                                                               // IDF
  452.     while (1)                                                               // IDF
  453.     {
  454.         if (flag == true)                                                     // Se a contagem tiver terminado
  455.         {
  456.             flag = false;                                                       // Impede nova impresao
  457.             float frequencia = 0;                                               // Variavel para calculo de frequencia
  458.             frequencia = (pulses + (multPulses * overflow)) / 2  ;              // Calcula qtos pulsos ocorreram
  459.             char buf[32];                                                       // Buffer para guardar a pontuacao
  460.             printf("Frequencia: %s", (ltos(frequencia, buf, 10)));              // Imprime pontuado
  461.             printf(" Hz \n");                                                   // Sufixo
  462. #if defined LCD_ON || defined LCD_I2C_ON                                                        // LCD
  463.             hd44780_gotoxy(&lcd, 2, 0);                                         // Posiciona cusros na posicao 2 da linha 0
  464.             hd44780_puts(&lcd, "Frequencia:");                                  // Print
  465.             hd44780_gotoxy(&lcd, 2, 1);                                         // Posiciona cusros na posicao 2 da linha 1
  466.             hd44780_puts(&lcd, (ltos(frequencia, buf, 10)));                    // Print
  467.             hd44780_puts(&lcd, " Hz              ");                            // Print
  468. #endif
  469.             multPulses = 0;                                                     // Zera contador de overflow
  470.             // Aqui pode rodar qq funcao                                        // Espaco para qualquer função
  471.             rxCalc();
  472.             vTaskDelay(1);
  473.             // Aqui pode rodar qq funcao                                        // Espaco para qualquer função
  474.             pcnt_counter_clear(PCNT_COUNT_UNIT);                                // Zera o contador PCNT
  475.             esp_timer_start_once(timer_handle, janela);                         // Inicia contador de tempo de 1 segundo
  476.             gpio_set_level(OUTPUT_CONTROL_GPIO, 1);                             // Porta de controle habilita contagem dos pulsos
  477.         }
  478.     }                                                                       // IDF
  479. }
  480.  
RAW Paste Data