RuiViana

NovoTeste05

Jul 13th, 2020
1,143
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.   NovoTeste02  Compilou com a IDF do CEI
  3.   NovoTeste04   troca das rotinas de pontuação
  4.   NovoTeste05   limpeza de variaveis desnecessarias e organização
  5.  
  6.   Desenvolvedores: Rui Viana e Gustavo Murta   08/jul/2020
  7.  
  8.   Para desenvolver este projeto, foram aproveitadas partes de códigos dos desenvolvedores
  9.   abaixo referenciados.
  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 5 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.     5. Gerador de sinais programado para 10 KHz
  28.  
  29.   1. O contador de pulso usa o pcnt do ESP32.
  30.     O pcnt tem os seguintes parâmetros:
  31.       a. port de entrada;
  32.       b. canal de entrada;
  33.       c. port de controle;
  34.       d. contagem na subida do pulso;
  35.       e. contagem na descida do pulso;
  36.       f. contagem só com o controle em nível elevado;
  37.       g. limite máximo de contagem.
  38.  
  39.   2. O Controle de tempo de contagem usa o esp-timer.
  40.     O esp-timer tem o seguinte parâmetro:
  41.       a. controle do tempo;
  42.  
  43.   Funcionamento:
  44.     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.
  45.   Os pulsos são contado tanto na subida quanto na descida do pulso, para melhorar a media de contagem.
  46.   O tempo de contagem é definido pelo esp-timer, e esta' definido em 1 segundo, na variável janela.
  47.   Se a contagem for maior que 20000 pulsos durante o tempo de contagem, ocorra overflow e a cada overflow que ocorre
  48.   e' contabilizado na variável multPulses, e o contador de pulso retorna a zero continuando a contar.
  49.     Quando o tempo de leitura termina, uma rotina é chamada e o valor do no contador de pulsos e' lido e salvo,
  50.     um flag e' ligado indicando que terminou a leitura dos pulsos
  51.  
  52.     No loop, ao verificar que o flag indica que terminou a leitura dos pulsos, o valor é calculado multiplicando
  53.   o numero de overflow por 20000 e somando ao numero de pulsos restantes e dividindo por 2, pois contou 2 vezes.
  54.   Como o pulsos são contados na subida e na descida, a contagem e´ o dobro da frequência.
  55.     A frequência é impressa no serial monitor.
  56.   Os registradores são resetados e o port de controle de entrada é novamente elevado para nível alto e a contagem de
  57.   pulsos se inicia.
  58.  
  59.   Tem também um gerador de sinais que gera 10 KHz, e pode ser usado para testes.
  60.   Este gerador pode ser alterado para gerar frequencias até 40 MHz.
  61.   O Port de saida deste gerador é definido na linha #define LEDC_GPIO.
  62.   Atualmente está definido como GPIO 25.
  63.  
  64.   Para o uso da Serial e de um LCD, existem 2 definições que pode ser usadas juntas ou bloqueadas.
  65.   Este uso e bolqueio pode ser comitantemente ou individualmente.
  66.  
  67.   Referências:
  68.   author=krzychb https://github.com/espressif/esp-idf/tree/master/examples/peripherals/pcnt
  69.   resposta by Deouss » Thu May 17, 2018 3:07 pm no tópico https://esp32.com/viewtopic.php?t=5734
  70.   Gerador de sinais Gustavo https://github.com/Gustavomurta/ESP32_frequenceMeter/blob/master/ESP32OscilatorV03.ino
  71.   Formatação de numero https://arduino.stackexchange.com/questions/28603/the-most-effective-way-to-format-numbers-on-arduino
  72.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
  73.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
  74. */
  75.  
  76. #define IDF_ON                                                              // Seleciona IDF_ON = IDF  IDF_OFF = Arduino
  77. //#define LCD_ON                                                            // Se tem LCD defina LCD_ON, se não tem LCD, defina LCD_OFF
  78. //#define Ser_ON                                                            // Se quer imprimir resultados na serial defina Ser_ON, se não, defina  Ser_OFF
  79.  
  80. #include <stdio.h>
  81. #include "freertos/FreeRTOS.h"
  82. #include "freertos/portmacro.h"
  83. #include "freertos/task.h"
  84. #include "freertos/queue.h"
  85. #include "driver/periph_ctrl.h"
  86. #include "driver/ledc.h"
  87. #include "driver/gpio.h"
  88. #include "driver/pcnt.h"
  89. #include "driver/ledc.h"
  90. #include "esp_attr.h"
  91. #include "esp_log.h"
  92. #include "esp_timer.h"
  93. #include "sdkconfig.h"
  94.  
  95. #define PCNT_COUNT_UNIT       PCNT_UNIT_0                                 // Unidade 0 do pcnt
  96. #define PCNT_COUNT_CHANNEL    PCNT_CHANNEL_0                              // Canal 0 do pcnt
  97.  
  98. #define PCNT_INPUT_SIG_IO     GPIO_NUM_34                                          // Freq Meter Input GPIO 34
  99. #define LEDC_HS_CH0_GPIO      GPIO_NUM_25
  100.  
  101. #define PCNT_INPUT_CTRL_IO    GPIO_NUM_35                                          // Count Control GPIO HIGH=count up, LOW=count down GPIO 25
  102. #define OUTPUT_CONTROL_GPIO   GPIO_NUM_32                                  // Saida do timer GPIO 2
  103.  
  104. #define LEDC_HS_CH0_CHANNEL    LEDC_CHANNEL_0
  105. #define LEDC_HS_MODE           LEDC_HIGH_SPEED_MODE
  106. #define LEDC_HS_TIMER          LEDC_TIMER_0
  107.  
  108. unsigned long   overflow  =   20000;                                           // Valor maximo para overflow de pcnt
  109. #define PCNT_H_LIM_VAL        overflow                                    // Limite superior de contagem
  110.  
  111. esp_timer_create_args_t create_args;                                      // Argumentos do timer
  112. esp_timer_handle_t timer_handle;                                          // Instancia de timer
  113.  
  114. //  Calculo do ajustes para cada faixa de frequencia
  115. //  Resolucao = log2(Clock(80MHz)/f)   ex: 50.000 HZ = 80.0000/50.000 = 1.600 log2(1600) = 10
  116. //  Duty 50%  = (2**Resolucao)/2       ex: 2**10 = 1024   1024/2 = 512
  117.  
  118. bool            flag          = true;                                                         // Indicador de fim de contagem libera impressao
  119. int16_t         pulses        = 0;                                                       // Contador de pulsos de entrada
  120. unsigned long   multPulses    = 0;                                             // Contador de overflows de pcnt
  121. unsigned long   janela        = 1000000;                                          // Janela de 1 segundo para a contagem de pulsos
  122. uint32_t        oscilator     = 50000;                                                     // Frequencia em Hz
  123.  
  124. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  125. //----------------------------------------------------------------------------------------
  126. char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos)
  127. {
  128.   int c;
  129.   if (val >= radix)
  130.     s = ultos_recursive(val / radix, s, radix, pos + 1);
  131.   c = val % radix;
  132.   c += (c < 10 ? '0' : 'a' - 10);
  133.   *s++ = c;
  134.   if (pos % 3 == 0) *s++ = '.';
  135.   return s;
  136. }
  137. //----------------------------------------------------------------------------------------
  138. char *ltos(long val, char *s, int radix)
  139. {
  140.   if (radix < 2 || radix > 36) {
  141.     s[0] = 0;
  142.   } else {
  143.     char *p = s;
  144.     if (radix == 10 && val < 0) {
  145.       val = -val;
  146.       *p++ = '-';
  147.     }
  148.     p = ultos_recursive(val, p, radix, 0) - 1;
  149.     *p = 0;
  150.   }
  151.   return s;
  152. }
  153. //----------------------------------------------------------------------------
  154. void ledcInit ()
  155. {
  156.   ledc_timer_config_t ledc_timer = {};
  157.   ledc_timer.duty_resolution = LEDC_TIMER_10_BIT;      // resolution of PWM duty
  158.   ledc_timer.freq_hz = oscilator;                     // frequency of PWM signal
  159.   ledc_timer.speed_mode = LEDC_HS_MODE;               // timer mode
  160.   ledc_timer.timer_num = LEDC_HS_TIMER;               // timer index
  161.   ledc_timer_config(&ledc_timer);
  162.   //
  163.   ledc_channel_config_t ledc_channel = {};
  164.  
  165.   ledc_channel.channel    = LEDC_HS_CH0_CHANNEL;
  166.   ledc_channel.duty       = 512;
  167.   ledc_channel.gpio_num   = LEDC_HS_CH0_GPIO;
  168.   ledc_channel.speed_mode = LEDC_HS_MODE;
  169.   ledc_channel.hpoint     = 16;
  170.   ledc_channel.timer_sel  = LEDC_HS_TIMER;
  171.  
  172.   ledc_channel_config(&ledc_channel);
  173. }
  174. //----------------------------------------------------------------------------------
  175. void tempo_controle(void *p)                                              // Fim de tempo de leitura de pulsos
  176. {
  177.   gpio_set_level(OUTPUT_CONTROL_GPIO, 0);                               // Controle do PCount - stop count
  178.   pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);                       // Obtem o valor contado
  179.   flag = true;                                                            // Informa que ocorreu interrupt de controle
  180. }
  181. //----------------------------------------------------------------------------------
  182. static void IRAM_ATTR pcnt_intr_handler(void *arg)                        // Overflow de contagem de pulsos
  183. {
  184.   portENTER_CRITICAL_ISR(&timerMux);                                      // Desabilita interrupção ?
  185.   multPulses++;                                                           // Incrementa contador de overflow
  186.   PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);                                // Limpa indicador de interrupt
  187.   portEXIT_CRITICAL_ISR(&timerMux);                                       // Libera novo interrupt
  188. }
  189. //----------------------------------------------------------------------------------
  190. void pcnt_init(void)                                                      // Rotina de inicializacao do pulse count
  191. {
  192.   pcnt_config_t pcnt_config = { };                                        // Instancia pulse config
  193.   pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;                         // Port de entrada dos pulsos
  194.   pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;                         // Controle da contagem
  195.   pcnt_config.unit = PCNT_COUNT_UNIT;                                     // Unidade de contagem
  196.   pcnt_config.channel = PCNT_COUNT_CHANNEL;                               // Canal de contagem
  197.   pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;                             // Limite maximo de contagem
  198.   pcnt_config.pos_mode = PCNT_COUNT_INC;                                  // Conta na subida do pulso
  199.   pcnt_config.neg_mode = PCNT_COUNT_INC;                                  // Conta na descida do pulso
  200.   pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;                             // Nao usado
  201.   pcnt_config.hctrl_mode = PCNT_MODE_KEEP;                                // Se HIGH conta incrementando
  202.   pcnt_unit_config(&pcnt_config);                                         // Inicializa PCNT
  203.  
  204.   pcnt_counter_pause(PCNT_COUNT_UNIT);                                    // Inicializa o contador PCNT
  205.   pcnt_counter_clear(PCNT_COUNT_UNIT);                                    // Zera o contador PCNT
  206.  
  207.   pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);                     // Limite superior de contagem
  208.   pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);                    // Rotina de Interrupt de pcnt
  209.   pcnt_intr_enable(PCNT_COUNT_UNIT);                                      // Habilita interrup de pcnt
  210.  
  211.   pcnt_counter_resume(PCNT_COUNT_UNIT);                                   // inicia a contagem
  212. }
  213. //----------------------------------------------------------------------------------
  214. void myInit()
  215. {
  216.   ledcInit();
  217.   pcnt_init();                                                            // Inicializa o pulse count
  218.   gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);                              // Define o port decontrole
  219.   gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);              // Define o port de controle como saida
  220.  
  221.   create_args.callback = tempo_controle;                                  // Instancia o tempo de controle
  222.   esp_timer_create(&create_args, &timer_handle);                          // Cria parametros do timer
  223. }
  224. //---------------------------------------------------------------------------------
  225. void app_main(void)
  226. {
  227. #ifdef IDF_ON                                                             // IDF
  228.   myInit();                                                               // IDF
  229.   while (1)                                                               // IDF
  230.   {
  231. #endif
  232.     if (flag == true)                                                     // Se a contagem tiver terminado
  233.     {
  234.       flag = false;                                                       // Impede nova impresao
  235.       float frequencia = 0;                                               // Variavel para calculo de frequencia
  236.       frequencia = (pulses + (multPulses * overflow)) / 2  ;              // Calcula qtos pulsos ocorreram
  237.       char buf[32];
  238.       printf("frequencia: %s", (ltos(frequencia, buf, 10)));
  239.       printf(" Hz \n");
  240.  
  241.       multPulses = 0;                                                     // Zera contador de overflow
  242.  
  243.       // Aqui pode rodar qq funcao                                        // Espaco para qualquer função
  244.       //delay(50);                                                        // Espaco para qualquer função
  245.       vTaskDelay(1);
  246.       // Aqui pode rodar qq funcao                                        // Espaco para qualquer função
  247.  
  248.       pcnt_counter_clear(PCNT_COUNT_UNIT);                                // Zera o contador PCNT
  249.       esp_timer_start_once(timer_handle, janela);                         // Inicia contador de tempo de 1 segundo
  250.       gpio_set_level(OUTPUT_CONTROL_GPIO, 1);                             // Porta de controle habilita contagem dos pulsos
  251.     }
  252. #ifdef IDF_ON                                                             // IDF
  253.   }                                                                       // IDF
  254. #endif
  255. }
  256. //---------------------------------------------------------------------------------
  257. #ifdef IDF_OFF                                                            // Arduino
  258. void setup()
  259. {
  260.   Serial.begin(115200);                                                   // Inicializa a serial
  261.   myInit();                                                               // Chaama inicializacao
  262. }
  263. //---------------------------------------------------------------------------------
  264. void loop()
  265. {
  266.   app_main();                                                             // Chama rotina principal
  267. }
  268. #endif
RAW Paste Data