RuiViana

NovoTeste06

Jul 13th, 2020
1,223
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.   NovoTeste06   Nova Diretiva de compilação  ARDUINO
  6.  
  7.   Desenvolvedores: Rui Viana e Gustavo Murta   08/jul/2020
  8.  
  9.   Para desenvolver este projeto, foram aproveitadas partes de códigos dos desenvolvedores
  10.   abaixo referenciados.
  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.   author=krzychb https://github.com/espressif/esp-idf/tree/master/examples/peripherals/pcnt
  70.   resposta by Deouss » Thu May 17, 2018 3:07 pm no tópico https://esp32.com/viewtopic.php?t=5734
  71.   Gerador de sinais Gustavo https://github.com/Gustavomurta/ESP32_frequenceMeter/blob/master/ESP32OscilatorV03.ino
  72.   Formatação de numero https://arduino.stackexchange.com/questions/28603/the-most-effective-way-to-format-numbers-on-arduino
  73.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
  74.   https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
  75. */
  76.  
  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. uint32_t        mDuty         = 512;
  124.  
  125. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
  126. //----------------------------------------------------------------------------------------
  127. char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos)
  128. {
  129.   int c;
  130.   if (val >= radix)
  131.     s = ultos_recursive(val / radix, s, radix, pos + 1);
  132.   c = val % radix;
  133.   c += (c < 10 ? '0' : 'a' - 10);
  134.   *s++ = c;
  135.   if (pos % 3 == 0) *s++ = '.';
  136.   return s;
  137. }
  138. //----------------------------------------------------------------------------------------
  139. char *ltos(long val, char *s, int radix)
  140. {
  141.   if (radix < 2 || radix > 36) {
  142.     s[0] = 0;
  143.   } else {
  144.     char *p = s;
  145.     if (radix == 10 && val < 0) {
  146.       val = -val;
  147.       *p++ = '-';
  148.     }
  149.     p = ultos_recursive(val, p, radix, 0) - 1;
  150.     *p = 0;
  151.   }
  152.   return s;
  153. }
  154. //----------------------------------------------------------------------------
  155. void ledcInit ()
  156. {
  157.   ledc_timer_config_t ledc_timer = {};
  158.   ledc_timer.duty_resolution = LEDC_TIMER_10_BIT;      // resolution of PWM duty
  159.   ledc_timer.freq_hz    = oscilator;                     // frequency of PWM signal
  160.   ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
  161.   ledc_timer.timer_num = LEDC_TIMER_0;
  162.   ledc_timer_config(&ledc_timer);
  163.  
  164.   ledc_channel_config_t ledc_channel = {};
  165.  
  166.   ledc_channel.channel    = LEDC_HS_CH0_CHANNEL;
  167.   ledc_channel.duty       = mDuty;
  168.   ledc_channel.gpio_num   = LEDC_HS_CH0_GPIO;
  169.   ledc_channel.intr_type  = LEDC_INTR_DISABLE;
  170.   ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  171.   ledc_channel.timer_sel  = LEDC_TIMER_0;
  172.  
  173.   ledc_channel_config(&ledc_channel);
  174. }
  175. //----------------------------------------------------------------------------------
  176. void tempo_controle(void *p)                                              // Fim de tempo de leitura de pulsos
  177. {
  178.   gpio_set_level(OUTPUT_CONTROL_GPIO, 0);                               // Controle do PCount - stop count
  179.   pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);                       // Obtem o valor contado
  180.   flag = true;                                                            // Informa que ocorreu interrupt de controle
  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. void pcnt_init(void)                                                      // Rotina de inicializacao do pulse count
  192. {
  193.   pcnt_config_t pcnt_config = { };                                        // Instancia pulse config
  194.   pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;                         // Port de entrada dos pulsos
  195.   pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;                         // Controle da contagem
  196.   pcnt_config.unit = PCNT_COUNT_UNIT;                                     // Unidade de contagem
  197.   pcnt_config.channel = PCNT_COUNT_CHANNEL;                               // Canal de contagem
  198.   pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;                             // Limite maximo de contagem
  199.   pcnt_config.pos_mode = PCNT_COUNT_INC;                                  // Conta na subida do pulso
  200.   pcnt_config.neg_mode = PCNT_COUNT_INC;                                  // Conta na descida do pulso
  201.   pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;                             // Nao usado
  202.   pcnt_config.hctrl_mode = PCNT_MODE_KEEP;                                // Se HIGH conta incrementando
  203.   pcnt_unit_config(&pcnt_config);                                         // Inicializa PCNT
  204.  
  205.   pcnt_counter_pause(PCNT_COUNT_UNIT);                                    // Inicializa o contador PCNT
  206.   pcnt_counter_clear(PCNT_COUNT_UNIT);                                    // Zera o contador PCNT
  207.  
  208.   pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);                     // Limite superior de contagem
  209.   pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);                    // Rotina de Interrupt de pcnt
  210.   pcnt_intr_enable(PCNT_COUNT_UNIT);                                      // Habilita interrup de pcnt
  211.  
  212.   pcnt_counter_resume(PCNT_COUNT_UNIT);                                   // inicia a contagem
  213. }
  214. //----------------------------------------------------------------------------------
  215. void myInit()
  216. {
  217.   ledcInit();
  218.   pcnt_init();                                                            // Inicializa o pulse count
  219.   gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);                              // Define o port decontrole
  220.   gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);              // Define o port de controle como saida
  221.  
  222.   create_args.callback = tempo_controle;                                  // Instancia o tempo de controle
  223.   esp_timer_create(&create_args, &timer_handle);                          // Cria parametros do timer
  224. }
  225. //---------------------------------------------------------------------------------
  226. void app_main(void)
  227. {
  228. //#ifdef IDF_ON                                                             // IDF
  229. #ifndef ARDUINO
  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. #ifndef ARDUINO
  255.   }                                                                       // IDF
  256. #endif
  257. }
  258. //---------------------------------------------------------------------------------
  259. //#ifdef IDF_OFF                                                            // Arduino
  260. #ifdef ARDUINO
  261. void setup()
  262. {
  263.   Serial.begin(115200);                                                   // Inicializa a serial
  264.   myInit();                                                               // Chaama inicializacao
  265. }
  266. //---------------------------------------------------------------------------------
  267. void loop()
  268. {
  269.   app_main();                                                             // Chama rotina principal
  270. }
  271. #endif
RAW Paste Data