RuiViana

NovoTeste04

Jul 13th, 2020
804
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.  
  5.   Desenvolvedores: Rui Viana e Gustavo Murta   08/jul/2020
  6.  
  7.   Para desenvolver este projeto, foram aproveitadas partes de códigos dos desenvolvedores
  8.   abaixo referenciados.
  9.  
  10.   O Projeto:
  11.   Um frequencímetro usando ESP32, sem necessidade de escalas e mostrando até 7 dígitos,
  12.   atingindo com precisão até 20MHz ou mais.
  13.  
  14.   Definições:
  15.   PORT de entrada do frequencímetro PCNT_INPUT_SIG_IO (GPIO 34)
  16.   PORT de entrada de controle PCNT_INPUT_CTRL_IO (GPIO 35)
  17.   PORT de saída do timer OUTPUT_CONTROL_GPIO (GPIO 32)
  18.   O PORT de entrada de controle (GPIO 35) deve ser ligado ao PORT de saída do timer (GPIO 32).
  19.   Estes são os ports usados no projeto, mas podem ser modificados para sua melhor conveniência.
  20.  
  21.   O frequencímetro é dividido em 5 partes:
  22.     1. Contador de pulsos;
  23.     2. Controle de tempo de contagem;
  24.     3. Impressão do resultado;
  25.     4. Espaço para outras funções.
  26.     5. Gerador de sinais programado para 10 KHz
  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 tempo de leitura termina, uma rotina é chamada e o valor do no contador de pulsos e' lido e salvo,
  49.     um flag e' ligado indicando que terminou a leitura dos pulsos
  50.  
  51.     No loop, ao verificar que o 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.   Tem também um gerador de sinais que gera 10 KHz, e pode ser usado para testes.
  59.   Este gerador pode ser alterado para gerar frequencias até 40 MHz.
  60.   O Port de saida deste gerador é definido na linha #define LEDC_GPIO.
  61.   Atualmente está definido como GPIO 25.
  62.  
  63.   Para o uso da Serial e de um LCD, existem 2 definições que pode ser usadas juntas ou bloqueadas.
  64.   Este uso e bolqueio pode ser comitantemente ou individualmente.
  65.  
  66.   Referências:
  67.   author=krzychb https://github.com/espressif/esp-idf/tree/master/examples/peripherals/pcnt
  68.   resposta by Deouss » Thu May 17, 2018 3:07 pm no tópico https://esp32.com/viewtopic.php?t=5734
  69.   Gerador de sinais Gustavo https://github.com/Gustavomurta/ESP32_frequenceMeter/blob/master/ESP32OscilatorV03.ino
  70.   Formatação de numero https://arduino.stackexchange.com/questions/28603/the-most-effective-way-to-format-numbers-on-arduino
  71.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
  72.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
  73.  
  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. #define PCNT_INPUT_SIG_IO     34                                          // Freq Meter Input GPIO 34
  98. #define PCNT_INPUT_CTRL_IO    35                                          // Count Control GPIO HIGH=count up, LOW=count down GPIO 25
  99. #define OUTPUT_CONTROL_GPIO   GPIO_NUM_32                                  // Saida do timer GPIO 2
  100.  
  101. #define PCNT_H_LIM_VAL        overflow                                    // Limite superior de contagem
  102.  
  103. esp_timer_create_args_t create_args;                                      // Argumentos do timer
  104. esp_timer_handle_t timer_handle;                                          // Instancia de timer
  105.  
  106. unsigned long overflow = 20000;                                           // Valor maximo para overflow de pcnt
  107. bool flag = true;                                                         // Indicador de fim de contagem libera impressao
  108. int16_t pulses = 0;                                                       // Contador de pulsos de entrada
  109. unsigned long multPulses = 0;                                             // Contador de overflows de pcnt
  110. unsigned long  janela = 1000000;                                          // Janela de 1 segundo para a contagem de pulsos
  111.  
  112. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  113.  
  114. #define LEDC_HS_CH0_CHANNEL    LEDC_CHANNEL_0
  115. #define LEDC_HS_CH0_GPIO       (25)
  116. #define LEDC_HS_MODE           LEDC_HIGH_SPEED_MODE
  117. #define LEDC_HS_TIMER          LEDC_TIMER_0
  118.  
  119. uint32_t  freque = 50000;                                                     // Frequencia em Hz
  120. uint32_t dig[8];
  121.  
  122.  
  123. //----------------------------------------------------------------------------------------
  124. char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos)
  125. {
  126.   int c;
  127.  
  128.   if (val >= radix)
  129.     s = ultos_recursive(val / radix, s, radix, pos + 1);
  130.   c = val % radix;
  131.   c += (c < 10 ? '0' : 'a' - 10);
  132.   *s++ = c;
  133.   if (pos % 3 == 0) *s++ = '.';
  134.   return s;
  135. }
  136. //----------------------------------------------------------------------------------------
  137. char *ltos(long val, char *s, int radix)
  138. {
  139.   if (radix < 2 || radix > 36) {
  140.     s[0] = 0;
  141.   } else {
  142.     char *p = s;
  143.     if (radix == 10 && val < 0) {
  144.       val = -val;
  145.       *p++ = '-';
  146.     }
  147.     p = ultos_recursive(val, p, radix, 0) - 1;
  148.     *p = 0;
  149.   }
  150.   return s;
  151. }
  152.  
  153. //----------------------------------------------------------------------------
  154. void ledcInit ()
  155. {
  156.   ledc_timer_config_t ledc_timer = {};
  157.   ledc_timer.duty_resolution = LEDC_TIMER_6_BIT;      // resolution of PWM duty
  158.   ledc_timer.freq_hz = freque;                        // 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       = 50;
  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. //----------------------------------------------------------------------------------
  183. static void IRAM_ATTR pcnt_intr_handler(void *arg)                        // Overflow de contagem de pulsos
  184. {
  185.   portENTER_CRITICAL_ISR(&timerMux);                                      // Desabilita interrupção ?
  186.   multPulses++;                                                           // Incrementa contador de overflow
  187.   PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);                                // Limpa indicador de interrupt
  188.   portEXIT_CRITICAL_ISR(&timerMux);                                       // Libera novo interrupt
  189. }
  190.  
  191. //----------------------------------------------------------------------------------
  192. void pcnt_init(void)                                                      // Rotina de inicializacao do pulse count
  193. {
  194.   pcnt_config_t pcnt_config = { };                                        // Instancia pulse config
  195.   pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;                         // Port de entrada dos pulsos
  196.   pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;                         // Controle da contagem
  197.   pcnt_config.unit = PCNT_COUNT_UNIT;                                     // Unidade de contagem
  198.   pcnt_config.channel = PCNT_COUNT_CHANNEL;                               // Canal de contagem
  199.   pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;                             // Limite maximo de contagem
  200.   pcnt_config.pos_mode = PCNT_COUNT_INC;                                  // Conta na subida do pulso
  201.   pcnt_config.neg_mode = PCNT_COUNT_INC;                                  // Conta na descida do pulso
  202.   pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;                             // Nao usado
  203.   pcnt_config.hctrl_mode = PCNT_MODE_KEEP;                                // Se HIGH conta incrementando
  204.   pcnt_unit_config(&pcnt_config);                                         // Inicializa PCNT
  205.  
  206.   pcnt_counter_pause(PCNT_COUNT_UNIT);                                    // Inicializa o contador PCNT
  207.   pcnt_counter_clear(PCNT_COUNT_UNIT);                                    // Zera o contador PCNT
  208.  
  209.   pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);                     // Limite superior de contagem
  210.   pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);                    // Rotina de Interrupt de pcnt
  211.   pcnt_intr_enable(PCNT_COUNT_UNIT);                                      // Habilita interrup de pcnt
  212.  
  213.   pcnt_counter_resume(PCNT_COUNT_UNIT);                                   // inicia a contagem
  214. }
  215. //----------------------------------------------------------------------------------
  216. void myInit()
  217. {
  218.   ledcInit();
  219.   pcnt_init();                                                            // Inicializa o pulse count
  220.   gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);                              // Define o port decontrole
  221.   gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);              // Define o port de controle como saida
  222.  
  223.   create_args.callback = tempo_controle;                                  // Instancia o tempo de controle
  224.   esp_timer_create(&create_args, &timer_handle);                          // Cria parametros do timer
  225. }
  226. //---------------------------------------------------------------------------------
  227. void app_main(void)
  228. {
  229. #ifdef IDF_ON                                                             // IDF
  230.   myInit();                                                               // IDF
  231.   while (1)                                                               // IDF
  232.   {
  233. #endif
  234.     if (flag == true)                                                       // Se a contagem tiver terminado
  235.     {
  236.       flag = false;                                                         // Impede nova impresao
  237.       float frequencia = 0;                                                 // Variavel para calculo de frequencia
  238.       frequencia = (pulses + (multPulses * overflow)) / 2  ;                  // Calcula qtos pulsos ocorreram
  239.       char buf[32];
  240.       printf("frequencia: %s", (ltos(frequencia, buf, 10)));
  241.       printf(" Hz \n");
  242.  
  243.       multPulses = 0;                                                       // Zera contador de overflow
  244.  
  245.       // Aqui pode rodar qq funcao                                          // Espaco para qualquer função
  246.       //delay(50);                                                            // Espaco para qualquer função
  247.       vTaskDelay(1);
  248.       // Aqui pode rodar qq funcao                                          // Espaco para qualquer função
  249.  
  250.       pcnt_counter_clear(PCNT_COUNT_UNIT);                                  // Zera o contador PCNT
  251.       esp_timer_start_once(timer_handle, janela);                           // Inicia contador de tempo de 1 segundo
  252.       gpio_set_level(OUTPUT_CONTROL_GPIO, 1);                            // Porta de controle habilita contagem dos pulsos
  253.     }
  254. #ifdef IDF_ON                                                             // IDF
  255.   }                                                                       // IDF
  256. #endif
  257. }
  258. //---------------------------------------------------------------------------------
  259. #ifdef IDF_OFF                                                            // Arduino
  260. void setup()
  261. {
  262.   Serial.begin(115200);                                                   // Inicializa a serial
  263.   myInit();                                                               // Chaama inicializacao
  264. }
  265. //---------------------------------------------------------------------------------
  266. void loop()
  267. {
  268.   app_main();                                                             // Chama rotina principal
  269. }
  270. #endif
RAW Paste Data