RuiViana

Frequence_Meter_0.0.21

Jul 9th, 2020
1,204
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.   ESP32 Frequence_Meter_0.0.21
  3.  
  4.   Desenvolvedores: Rui Viana e Gustavo Murta   08/jul/2020
  5.  
  6.   Para desenvolver este projeto, foram aproveitadas partes de códigos dos seguintes desenvolvedores.
  7.  
  8.   author=krzychb https://github.com/espressif/esp-idf/tree/master/examples/peripherals/pcnt
  9.   resposta by Deouss » Thu May 17, 2018 3:07 pm no tópico https://esp32.com/viewtopic.php?t=5734
  10.  
  11.   O Projeto:
  12.   Um frequencímetro usando ESP32, sem necessidade de escalas e mostrando até 7 dígitos,
  13.   atingindo com precisão até 20MHz ou mais.
  14.  
  15.   Definições:
  16.   PORT de entrada do frequencímetro PCNT_INPUT_SIG_IO (GPIO 34)
  17.   PORT de entrada de controle PCNT_INPUT_CTRL_IO (GPIO 35)
  18.   PORT de saída do timer OUTPUT_CONTROL_GPIO (GPIO 32)
  19.   O PORT de entrada de controle (GPIO 35) deve ser ligado ao PORT de saída do timer (GPIO 32).
  20.   Estes são os ports usados no projeto, mas podem ser modificados para sua melhor conveniência.
  21.  
  22.   O frequencímetro é dividido em 4 partes:
  23.     1. Contador de pulsos;
  24.     2. Controle de tempo de contagem;
  25.     3. Impressão do resultado;
  26.     4. Espaço para outras funções.
  27.  
  28.   1. O contador de pulso usa o pcnt do ESP32.
  29.     O pcnt tem os seguintes parâmetros:
  30.       a. port de entrada;
  31.       b. canal de entrada;
  32.       c. port de controle;
  33.       d. contagem na subida do pulso;
  34.       e. contagem na descida do pulso;
  35.       f. contagem só com o controle em nível elevado;
  36.       g. limite máximo de contagem.
  37.  
  38.   2. O Controle de tempo de contagem usa o esp-timer.
  39.     O esp-timer tem o seguinte parâmetro:
  40.       a. controle do tempo;
  41.  
  42.   Funcionamento:
  43.     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.
  44.   Os pulsos são contado tanto na subida quanto na descida do pulso, para melhorar a media de contagem.
  45.   O tempo de contagem é definido pelo esp-timer, e esta' definido em 1 segundo, na variável janela.
  46.   Se a contagem for maior que 20000 pulsos durante o tempo de contagem, ocorra overflow e a cada overflow que ocorre
  47.   e' contabilizado na variável multPulses, e o contador de pulso retorna a zero continuando a contar.
  48.     Quando o port de controle contagem for para o nível baixo, ocorre um interrupt.
  49.   Neste interrupt o valor do no contador de pulsos e' lido e salvo, um flag e' ligado um flag indicando que terminou
  50.   a leitura dos pulsos.
  51.     No loop, ao verificar que 0 flag indica que terminou a leitura dos pulsos, o valor é calculado multiplicando
  52.   o numero de overflow por 20000 e somando ao numero de pulsos restantes e dividindo por 2, pois contou 2 vezes.
  53.   Como o pulsos são contados na subida e na descida, a contagem e´ o dobro da frequência.
  54.     A frequência é impressa no serial monitor.
  55.   Os registradores são resetados e o port de controle de entrada é novamente elevado para nível alto e a contagem de
  56.   pulsos se inicia.
  57.  
  58.     Se houver LCD plugado nos ESP, defina LCD_ON na linha inical, se não houver, defina LCD_OFF.
  59.  
  60.   Referências:
  61.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
  62.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
  63.  
  64. */
  65.  
  66. #define LCD_ON                                                            // Se tem LCD digite LCD_ON, digite LCD_OFF
  67.  
  68. unsigned long overflow = 20000;                                           // Valor maximo para overun de pcnt
  69. #include "driver/pcnt.h"                                                  // Pulse count library
  70.  
  71. #ifdef LCD_ON                                                             // Se tem LCD
  72. #include <LiquidCrystal.h>                                                // Inclue a bibliotea do LCD
  73. LiquidCrystal lcd(5, 18, 19, 21, 22, 23);                                 // Instancia e define port
  74. #endif
  75.  
  76. #define PCNT_COUNT_UNIT       PCNT_UNIT_0                                 // Unidade de pcnt
  77. #define PCNT_COUNT_CHANNEL    PCNT_CHANNEL_0                              // Canal pcnt
  78. #define PCNT_INPUT_SIG_IO     34                                          // Pulse Input GPIO
  79. #define PCNT_INPUT_CTRL_IO    35                                          // Control GPIO HIGH=count up, LOW=count down
  80. #define OUTPUT_CONTROL_GPIO   GPIO_NUM_32                                  // Saida de controle
  81.  
  82. #define PCNT_H_LIM_VAL      overflow                                      // Limite superior de contagem
  83.  
  84. esp_timer_create_args_t create_args;                                      // Argumentos do timer
  85. esp_timer_handle_t timer_handle;                                          // Instancia de timer
  86.  
  87. bool flag = true;                                                         // Indicador de fim de contagem libera impressao
  88. int16_t pulses = 0;                                                       // Contador de pulsos de entrada
  89. unsigned long multPulses = 0;                                             // Contador de overflows de pcnt
  90. unsigned long  janela = 1000000;                                          // Janela de contagem de pulsos
  91. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  92. //----------------------------------------------------------------------------------
  93. void tempo_controle(void *p)                                              // Fim de tempo de leitura de puslos
  94. {
  95.   gpio_set_level(OUTPUT_CONTROL_GPIO, 0);                                 // Desliga o controle do pcnt
  96. }
  97. //----------------------------------------------------------------------------------
  98. static void IRAM_ATTR pcnt_intr_handler(void *arg)                        // Overflow de contagem de pulsos
  99. {
  100.   PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);                                // Limpa indicador de interrupt
  101.   portENTER_CRITICAL_ISR(&timerMux);                                      // Bloqueia novo interrupt
  102.   multPulses++;                                                           // Incrementa contador de overflow
  103.   portEXIT_CRITICAL_ISR(&timerMux);                                       // Libera novo interrupt
  104. }
  105. //----------------------------------------------------------------------------------
  106. void IRAM_ATTR detectsCount()                                             // Interrupt de fim de tempo contagem
  107. {
  108.   pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);                       // Obtem o valor contado
  109.   flag = true;                                                            // Informa que ocorreu interrupt de controle
  110. }
  111. //----------------------------------------------------------------------------------
  112. void pcnt_init(void)                                                      // Rotina de inicializacao do pulse count
  113. {
  114.   pcnt_config_t pcnt_config = { };                                        // Instancia pulse config
  115.   pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;                         // Port de entrada dos pulsos
  116.   pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;                         // Controle da contagem
  117.   pcnt_config.unit = PCNT_COUNT_UNIT;                                     // Unidade de contagem
  118.   pcnt_config.channel = PCNT_COUNT_CHANNEL;                               // Canal de contagem
  119.   pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;                             // Limite maximo de contagem
  120.   pcnt_config.pos_mode = PCNT_COUNT_INC;                                  // Conta na subida do pulso
  121.   pcnt_config.neg_mode = PCNT_COUNT_INC;                                  // Conta na descida do pulso
  122.   pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;                             // Nao usado
  123.   pcnt_config.hctrl_mode = PCNT_MODE_KEEP;                                // Se HIGH conta incrementando
  124.   pcnt_unit_config(&pcnt_config);                                         // Inicializa PCNT
  125.  
  126.   pcnt_counter_pause(PCNT_COUNT_UNIT);                                    // Inicializa o contador PCNT
  127.   pcnt_counter_clear(PCNT_COUNT_UNIT);                                    // Zera o contador PCNT
  128.   pcnt_counter_resume(PCNT_COUNT_UNIT);                                   // inicia a contagem
  129.  
  130.   pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);                     // Limite superior de contagem
  131.   pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);                    // Rotina de Interrupt de pcnt
  132.   pcnt_intr_enable(PCNT_COUNT_UNIT);                                      // Habilita interrup de pcnt
  133. }
  134. //----------------------------------------------------------------------------------
  135. void setup()
  136. {
  137.   Serial.begin(115200);                                                   // Inicializa serial
  138. #ifdef LCD_ON                                                             // Se tem LCD
  139.   lcd.begin(16, 2);                                                       // Inicializa lcd
  140.   lcd.print("Frequencimetro");                                            // Print
  141. #endif
  142.   pcnt_init();                                                            // Inicializa o pulse count
  143.   gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);                              // Define o port decontrole
  144.   gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);              // Define como saida
  145.  
  146.   create_args.callback = tempo_controle;                                  // Instancia o tempo de controel
  147.   esp_timer_create(&create_args, &timer_handle);                          // Cria parametros do timer
  148.  
  149.   attachInterrupt(digitalPinToInterrupt(PCNT_INPUT_CTRL_IO), detectsCount, FALLING);  // Habilita interrupt de fim de contagem
  150. }
  151. //---------------------------------------------------------------------------------
  152. void loop()
  153. {
  154.   if (flag == true)                                                       // Se impressa estiver liberada
  155.   {
  156.     flag = false;                                                         // Impede nova impresao
  157.     float frequencia = 0;                                                 // Variavel para calculo de frequencia
  158.     frequencia = (pulses + (multPulses * overflow))  ;                    // Calcula qtos pulsos ocorram
  159.     Serial.print("  Frequencia: ");                                       // Print
  160.     Serial.print  (frequencia / 2 , 0 );                                  // Print
  161.     Serial.println("  Hz: ");                                             // Print
  162. #ifdef LCD_ON                                                             // Se tem LCD
  163.     lcd.setCursor(2, 1);                                                  //´Posicao 3 Linha 1
  164.     lcd.print(frequencia / 2, 0);                                         // Print
  165.     lcd.print("  Hz:        ");                                           // Print
  166. #endif
  167.     multPulses = 0;                                                       // Zera contador de overflow
  168.  
  169.     // Aqui pode rodar qq funcao                                          // Espaco para qualquer função
  170.     delay(50);                                                            // Espaco para qualquer função
  171.     // Aqui pode rodar qq funcao                                          // Espaco para qualquer função
  172.  
  173.     pcnt_counter_clear(PCNT_COUNT_UNIT);                                  // Zera o contador PCNT
  174.     esp_timer_start_once(timer_handle, janela);                           // Disparo unico de tempo de finido na variavel Janela
  175.     gpio_set_level(OUTPUT_CONTROL_GPIO, 1);                               // Libera port de contagem
  176.   }
  177. }
RAW Paste Data