RuiViana

NovoTeste02

Jul 10th, 2020
2,518
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.   Compilou com a IDF do CEI
  3.   ESP32 Frequence_Meter_0.0.21
  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.   Gerador de sinais Gustavo https://github.com/Gustavomurta/ESP32_frequenceMeter/blob/master/ESP32OscilatorV03.ino
  11.  
  12.   O Projeto:
  13.   Um frequencímetro usando ESP32, sem necessidade de escalas e mostrando até 7 dígitos,
  14.   atingindo com precisão até 20MHz ou mais.
  15.  
  16.   Definições:
  17.   PORT de entrada do frequencímetro PCNT_INPUT_SIG_IO (GPIO 34)
  18.   PORT de entrada de controle PCNT_INPUT_CTRL_IO (GPIO 35)
  19.   PORT de saída do timer OUTPUT_CONTROL_GPIO (GPIO 32)
  20.   O PORT de entrada de controle (GPIO 35) deve ser ligado ao PORT de saída do timer (GPIO 32).
  21.   Estes são os ports usados no projeto, mas podem ser modificados para sua melhor conveniência.
  22.  
  23.   O frequencímetro é dividido em 5 partes:
  24.     1. Contador de pulsos;
  25.     2. Controle de tempo de contagem;
  26.     3. Impressão do resultado;
  27.     4. Espaço para outras funções.
  28.     5. Gerador de sinais programado para 10 KHz
  29.  
  30.   1. O contador de pulso usa o pcnt do ESP32.
  31.     O pcnt tem os seguintes parâmetros:
  32.       a. port de entrada;
  33.       b. canal de entrada;
  34.       c. port de controle;
  35.       d. contagem na subida do pulso;
  36.       e. contagem na descida do pulso;
  37.       f. contagem só com o controle em nível elevado;
  38.       g. limite máximo de contagem.
  39.  
  40.   2. O Controle de tempo de contagem usa o esp-timer.
  41.     O esp-timer tem o seguinte parâmetro:
  42.       a. controle do tempo;
  43.  
  44.   Funcionamento:
  45.     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.
  46.   Os pulsos são contado tanto na subida quanto na descida do pulso, para melhorar a media de contagem.
  47.   O tempo de contagem é definido pelo esp-timer, e esta' definido em 1 segundo, na variável janela.
  48.   Se a contagem for maior que 20000 pulsos durante o tempo de contagem, ocorra overflow e a cada overflow que ocorre
  49.   e' contabilizado na variável multPulses, e o contador de pulso retorna a zero continuando a contar.
  50.     Quando o tempo de leitura termina, uma rotina é chamada e o valor do no contador de pulsos e' lido e salvo,
  51.     um flag e' ligado indicando que terminou a leitura dos pulsos
  52.  
  53.     No loop, ao verificar que o flag indica que terminou a leitura dos pulsos, o valor é calculado multiplicando
  54.   o numero de overflow por 20000 e somando ao numero de pulsos restantes e dividindo por 2, pois contou 2 vezes.
  55.   Como o pulsos são contados na subida e na descida, a contagem e´ o dobro da frequência.
  56.     A frequência é impressa no serial monitor.
  57.   Os registradores são resetados e o port de controle de entrada é novamente elevado para nível alto e a contagem de
  58.   pulsos se inicia.
  59.  
  60.   Tem também um gerador de sinais que gera 10 KHz, e pode ser usado para testes.
  61.   Este gerador pode ser alterado para gerar frequencias até 40 MHz.
  62.   O Port de saida deste gerador é definido na linha #define LEDC_GPIO.
  63.   Atualmente está definido como GPIO 25.
  64.  
  65.   Para o uso da Serial e de um LCD, existem 2 definições que pode ser usadas juntas ou bloqueadas.
  66.   Este uso e bolqueio pode ser comitantemente ou individualmente.
  67.  
  68.   Referências:
  69.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
  70.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
  71.  
  72. */
  73.  
  74. #include <stdio.h>
  75. #include "freertos/FreeRTOS.h"
  76. #include "freertos/portmacro.h"
  77. #include "freertos/task.h"
  78. #include "freertos/queue.h"
  79. #include "driver/periph_ctrl.h"
  80. #include "driver/ledc.h"
  81. #include "driver/gpio.h"
  82. #include "driver/pcnt.h"
  83. #include "driver/ledc.h"
  84. #include "esp_attr.h"
  85. #include "esp_log.h"
  86. #include "esp_timer.h"
  87. #include "sdkconfig.h"
  88.  
  89. #define PCNT_COUNT_UNIT       PCNT_UNIT_0                                 // Unidade 0 do pcnt
  90. #define PCNT_COUNT_CHANNEL    PCNT_CHANNEL_0                              // Canal 0 do pcnt
  91. #define PCNT_INPUT_SIG_IO     34                                          // Freq Meter Input GPIO 34
  92. #define PCNT_INPUT_CTRL_IO    35                                          // Count Control GPIO HIGH=count up, LOW=count down GPIO 25
  93. #define OUTPUT_CONTROL_GPIO   GPIO_NUM_32                                  // Saida do timer GPIO 2
  94.  
  95. #define PCNT_H_LIM_VAL        overflow                                    // Limite superior de contagem
  96.  
  97. esp_timer_create_args_t create_args;                                      // Argumentos do timer
  98. esp_timer_handle_t timer_handle;                                          // Instancia de timer
  99.  
  100. unsigned long overflow = 20000;                                           // Valor maximo para overflow de pcnt
  101. bool flag = true;                                                         // Indicador de fim de contagem libera impressao
  102. int16_t pulses = 0;                                                       // Contador de pulsos de entrada
  103. unsigned long multPulses = 0;                                             // Contador de overflows de pcnt
  104. unsigned long  janela = 1000000;                                          // Janela de 1 segundo para a contagem de pulsos
  105.  
  106. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  107.  
  108. #define LEDC_HS_CH0_CHANNEL    LEDC_CHANNEL_0
  109. #define LEDC_HS_CH0_GPIO       (25)
  110. #define LEDC_HS_MODE           LEDC_HIGH_SPEED_MODE
  111. #define LEDC_HS_TIMER          LEDC_TIMER_0
  112.  
  113. uint32_t  freque = 50000;                                                     // Frequencia em Hz
  114. uint32_t dig[8];
  115. //----------------------------------------------------------------------------
  116. void ledcInit ()
  117. {
  118.   ledc_timer_config_t ledc_timer = {};
  119.   ledc_timer.duty_resolution = LEDC_TIMER_6_BIT;      // resolution of PWM duty
  120.   ledc_timer.freq_hz = freque;                        // frequency of PWM signal
  121.   ledc_timer.speed_mode = LEDC_HS_MODE;               // timer mode
  122.   ledc_timer.timer_num = LEDC_HS_TIMER;               // timer index
  123.   ledc_timer_config(&ledc_timer);
  124.   //
  125.   ledc_channel_config_t ledc_channel = {};
  126.  
  127.   ledc_channel.channel    = LEDC_HS_CH0_CHANNEL;
  128.   ledc_channel.duty       = 50;
  129.   ledc_channel.gpio_num   = LEDC_HS_CH0_GPIO;
  130.   ledc_channel.speed_mode = LEDC_HS_MODE;
  131.   ledc_channel.hpoint     = 16;
  132.   ledc_channel.timer_sel  = LEDC_HS_TIMER;
  133.  
  134.   ledc_channel_config(&ledc_channel);
  135. }
  136. //---------------------------------------------------------------------------------
  137. void inserePt(uint32_t frequencia)                                        // Separação da frequencia em digitos
  138. {
  139.   uint32_t cTemp;                                                         // Temporaria para calculo
  140.   cTemp = (uint32_t)(frequencia / 2);                                     // Obtem o valor da frequencia
  141.   for (int i = 0 ; i < 8; i++)                                            // Separa 8 digitos
  142.   {
  143.     dig[i] = (cTemp % 10);                                                // Salva digito separado na mattriz
  144.     cTemp /= 10;                                                          // Divide por 10 para separar o proximo digito
  145.   }
  146. }
  147. //---------------------------------------------------------------------------------
  148. void rotinaSerial()                                                       // Imprime na serial com ponto milhar
  149. { // Se está definido para imprimir na serial
  150.   bool nTemp = false;                                                     // Temporario para limpeza de zeros a esquerda
  151.   for (int i = 7 ; i > -1 ; i--)                                          // Identifica o digito
  152.   {
  153.     if (nTemp == false)                                                   // Se não encontrou digito significativo ainda
  154.     {
  155.       //if (dig[i] == 0)                                                    // Testa se o digito é zero
  156.       //{
  157.       //  printf("");
  158.         //Serial.print  ("" );                                              // Se for Print nullo
  159.       //}
  160.       if (dig[i] != 0)                                                                  // Se não for
  161.       {
  162.         //Serial.print  (dig[i]);                                           // Print o digito
  163.         printf("frequencia :%d", (dig[i]));
  164.         if (i == 6)                                                       // Se for a 6a posição
  165.           printf(".");
  166.         //Serial.print  (".");                                            // Print imprime ponto
  167.         if (i == 3)                                                       // Se for a 3a posição
  168.           printf(".");
  169.         //Serial.print  (".");                                            // Imprime ponto
  170.         nTemp = true;                                                     // Informa que tem numero significativo
  171.       }
  172.     }
  173.     else                                                                  // Se tem numero significativo
  174.     {
  175.       printf("%d", (dig[i]));
  176.       ///Serial.print  (dig[i] );                                            // Imprime o digito
  177.       if (i == 6)                                                         // Se for a 6a posição
  178.         printf(".");
  179.       //Serial.print  (".");                                              // Print imprime ponto
  180.       if (i == 3)                                                         // Se for a 3a posição
  181.         printf(".");
  182.       //Serial.print  (".");                                              // Imprime ponto
  183.     }
  184.   }
  185.   printf(" HZ \n");
  186.   //Serial.println  (" Hz" );                                               // Print
  187. }
  188. //----------------------------------------------------------------------------------
  189. void tempo_controle(void *p)                                              // Fim de tempo de leitura de pulsos
  190. {
  191.   gpio_set_level(OUTPUT_CONTROL_GPIO, 0);                               // Controle do PCount - stop count
  192.   pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);                       // Obtem o valor contado
  193.   flag = true;                                                            // Informa que ocorreu interrupt de controle
  194. }
  195.  
  196. //----------------------------------------------------------------------------------
  197. static void IRAM_ATTR pcnt_intr_handler(void *arg)                        // Overflow de contagem de pulsos
  198. {
  199.   portENTER_CRITICAL_ISR(&timerMux);                                      // Desabilita interrupção ?
  200.   multPulses++;                                                           // Incrementa contador de overflow
  201.   PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);                                // Limpa indicador de interrupt
  202.   portEXIT_CRITICAL_ISR(&timerMux);                                       // Libera novo interrupt
  203. }
  204.  
  205. //----------------------------------------------------------------------------------
  206. void pcnt_init(void)                                                      // Rotina de inicializacao do pulse count
  207. {
  208.   pcnt_config_t pcnt_config = { };                                        // Instancia pulse config
  209.   pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;                         // Port de entrada dos pulsos
  210.   pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;                         // Controle da contagem
  211.   pcnt_config.unit = PCNT_COUNT_UNIT;                                     // Unidade de contagem
  212.   pcnt_config.channel = PCNT_COUNT_CHANNEL;                               // Canal de contagem
  213.   pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;                             // Limite maximo de contagem
  214.   pcnt_config.pos_mode = PCNT_COUNT_INC;                                  // Conta na subida do pulso
  215.   pcnt_config.neg_mode = PCNT_COUNT_INC;                                  // Conta na descida do pulso
  216.   pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;                             // Nao usado
  217.   pcnt_config.hctrl_mode = PCNT_MODE_KEEP;                                // Se HIGH conta incrementando
  218.   pcnt_unit_config(&pcnt_config);                                         // Inicializa PCNT
  219.  
  220.   pcnt_counter_pause(PCNT_COUNT_UNIT);                                    // Inicializa o contador PCNT
  221.   pcnt_counter_clear(PCNT_COUNT_UNIT);                                    // Zera o contador PCNT
  222.  
  223.   pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);                     // Limite superior de contagem
  224.   pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);                    // Rotina de Interrupt de pcnt
  225.   pcnt_intr_enable(PCNT_COUNT_UNIT);                                      // Habilita interrup de pcnt
  226.  
  227.   pcnt_counter_resume(PCNT_COUNT_UNIT);                                   // inicia a contagem
  228. }
  229. //----------------------------------------------------------------------------------
  230. void myInit()
  231. {
  232.   ledcInit();
  233.   pcnt_init();                                                            // Inicializa o pulse count
  234.   gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);                              // Define o port decontrole
  235.   gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);              // Define o port de controle como saida
  236.  
  237.   create_args.callback = tempo_controle;                                  // Instancia o tempo de controle
  238.   esp_timer_create(&create_args, &timer_handle);                          // Cria parametros do timer
  239. }
  240. //---------------------------------------------------------------------------------
  241. void app_main(void)
  242. {
  243.   myInit();
  244.   while (1)
  245.   {
  246.     if (flag == true)                                                       // Se a contagem tiver terminado
  247.     {
  248.       flag = false;                                                         // Impede nova impresao
  249.       float frequencia = 0;                                                 // Variavel para calculo de frequencia
  250.       frequencia = (pulses + (multPulses * overflow))  ;                    // Calcula qtos pulsos ocorreram
  251.       inserePt((uint32_t) frequencia);
  252.       rotinaSerial();
  253.       //    Serial.print("  Frequencia: ");                                       // Print
  254.       //    Serial.println ((frequencia / 2 ), 0);                                // Print
  255.       //printf("frequencia :%.1f\n", frequencia / 2);                             // Print
  256.  
  257.       multPulses = 0;                                                       // Zera contador de overflow
  258.  
  259.       // Aqui pode rodar qq funcao                                          // Espaco para qualquer função
  260.       //delay(50);                                                            // Espaco para qualquer função
  261.       vTaskDelay(1);
  262.       // Aqui pode rodar qq funcao                                          // Espaco para qualquer função
  263.  
  264.       pcnt_counter_clear(PCNT_COUNT_UNIT);                                  // Zera o contador PCNT
  265.       esp_timer_start_once(timer_handle, janela);                           // Inicia contador de tempo de 1 segundo
  266.       gpio_set_level(OUTPUT_CONTROL_GPIO, 1);                            // Porta de controle habilita contagem dos pulsos
  267.     }
  268.   }
  269. }
RAW Paste Data