2018年11月27日 星期二

DIY - ESP32:ESP32 PCNT 脈衝計數器程式(三十九)

DIY - ESP32:ESP32 PCNT 脈衝計數器程式(三十九):

ESP32 的 IDF 內已經有 PCNT(Pulse Counter / 脈衝計數器)範例程式,可以直接編譯使用,首先是設置 PCNT 的輸入和輸出引腳,將輸入和輸出引腳連接一起,輸出引腳會輸出 1Hz 10%佔空比(Duty Cycle)的訊號,觸發 PCNT 中斷處理程序傳遞到主程序,主程序處理 PCNT 接收的訊號,通過串口輸出結果資料。

ESP32 PCNT脈衝計數器電路製作
測試範例:
  • 編譯並加載示例。
  • 打開串口監視器以查看屏幕上打印的消息。
  • 將 GPIO17 連接到 GPIO18
  • GPIO5 是控制信號,您可以通過內部上拉使其懸空,或將其連接到地。 如果懸空,脈衝計數值將增加。 如果將 GPIO5 連接到 GND,則計數將減少。

脈衝計數器值時將觸發中斷:
  • 達到 thresh1 或 thresh0 值
  • 達到 l_lim 值或 h_lim 值
  • 將重置為零。
  • 檢查範例是否打印出當前計數器值和事件。

ESP32 PCNT 脈衝計數器程式 IO 設定:
#define PCNT_TEST_UNIT          PCNT_UNIT_0
#define PCNT_H_LIM_VAL         10
#define PCNT_L_LIM_VAL        -10
#define PCNT_THRESH1_VAL    5
#define PCNT_THRESH0_VAL   -5
#define PCNT_INPUT_SIG_IO     17     // Pulse Input GPIO
#define PCNT_INPUT_CTRL_IO  5     // Control GPIO HIGH=count up, LOW=count down
#define LEDC_OUTPUT_IO          18  // Output 1 Hz pulse generator

ESP32 PCNT 脈衝計數器程式 Output 1Hz 設定:
static void ledc_init(void)
{
    // Prepare and then apply the LEDC PWM timer configuration
    ledc_timer_config_t ledc_timer;
    ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_timer.timer_num = LEDC_TIMER_1;
    ledc_timer.duty_resolution = LEDC_TIMER_10_BIT;
    ledc_timer.freq_hz = 1;  // set output frequency at 1 Hz
    ledc_timer_config(&ledc_timer);

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel;
    ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_channel.channel = LEDC_CHANNEL_1;
    ledc_channel.timer_sel = LEDC_TIMER_1;
    ledc_channel.intr_type = LEDC_INTR_DISABLE;
    ledc_channel.gpio_num = LEDC_OUTPUT_IO;
    ledc_channel.duty = 100; // set duty at about 10%
    ledc_channel_config(&ledc_channel);
}

ESP32 PCNT 脈衝計數器程式 Input 設定:
static void pcnt_example_init(void)
{
    /* Prepare configuration for the PCNT unit */
    pcnt_config_t pcnt_config = {
        // Set PCNT input signal and control GPIOs
        .pulse_gpio_num = PCNT_INPUT_SIG_IO,
        .ctrl_gpio_num = PCNT_INPUT_CTRL_IO,
        .channel = PCNT_CHANNEL_0,
        .unit = PCNT_TEST_UNIT,

        // What to do on the positive / negative edge of pulse input?
        .pos_mode = PCNT_COUNT_INC,   // Count up on the positive edge
        .neg_mode = PCNT_COUNT_DIS,   // Keep the counter value on the negative edge

        // What to do when control input is low or high?
        .lctrl_mode = PCNT_MODE_REVERSE, // Reverse counting direction if low
        .hctrl_mode = PCNT_MODE_KEEP,    // Keep the primary counter mode if high

        // Set the maximum and minimum limit values to watch
        .counter_h_lim = PCNT_H_LIM_VAL,
        .counter_l_lim = PCNT_L_LIM_VAL,
    };

    /* Initialize PCNT unit */
    pcnt_unit_config(&pcnt_config);

    /* Configure and enable the input filter */
    pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
    pcnt_filter_enable(PCNT_TEST_UNIT);

    /* Set threshold 0 and 1 values and enable events to watch */
    pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_1);
    pcnt_set_event_value(PCNT_TEST_UNIT, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_THRES_0);

    /* Enable events on zero, maximum and minimum limit values */
    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_ZERO);
    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_H_LIM);
    pcnt_event_enable(PCNT_TEST_UNIT, PCNT_EVT_L_LIM);

    /* Initialize PCNT's counter */
    pcnt_counter_pause(PCNT_TEST_UNIT);
    pcnt_counter_clear(PCNT_TEST_UNIT);

    /* Register ISR handler and enable interrupts for PCNT unit */
    pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, NULL);
    pcnt_intr_enable(PCNT_TEST_UNIT);

    /* Everything is set up, now go to counting */
    pcnt_counter_resume(PCNT_TEST_UNIT);
}

ESP32 PCNT 脈衝計數器程式:
void app_main()
{
    /* Initialize LEDC to generate sample pulse signal */
    ledc_init();

    /* Initialize PCNT event queue and PCNT functions */
    pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));
    pcnt_example_init();

    int16_t count = 0;
    pcnt_evt_t evt;
    portBASE_TYPE res;
    while (1) {
        /* Wait for the event information passed from PCNT's interrupt handler.
         * Once received, decode the event type and print it on the serial monitor.
         */
        res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_PERIOD_MS);
        if (res == pdTRUE) {
            pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
            printf("Event PCNT unit[%d]; cnt: %d\n", evt.unit, count);
            if (evt.status & PCNT_STATUS_THRES1_M) {
                printf("THRES1 EVT\n");
            }
            if (evt.status & PCNT_STATUS_THRES0_M) {
                printf("THRES0 EVT\n");
            }
            if (evt.status & PCNT_STATUS_L_LIM_M) {
                printf("L_LIM EVT\n");
            }
            if (evt.status & PCNT_STATUS_H_LIM_M) {
                printf("H_LIM EVT\n");
            }
            if (evt.status & PCNT_STATUS_ZERO_M) {
                printf("ZERO EVT\n");
            }
        } else {
            pcnt_get_counter_value(PCNT_TEST_UNIT, &count);
            printf("Current counter value :%d\n", count);
        }
    }
}
 

操作系統:Windows 7 64-bit 版本
開發環境:AiThinker05 版本
原程碼: ESP32 ESP-IDF V3.0rc1
程式:DIY-ESP32-029-PCNT_01_IDF-20181124

ESP32 PCNT 脈衝計數器電路製作運行中
ESP32 PCNT 脈衝計數器電路製作顯示
ESP32 PCNT 脈衝計數器電路輸出 1Hz
ESP32 PCNT 脈衝計數器電路串行監視器上的示例輸出
相關網址:
※ DIY - ESP32:ESP32 PCNT 脈衝計數器電路(三十八)
※ DIY - ESP32:ESP32 PCNT API 函數模塊介紹(四十)
※ DIY - ESP32:ESP32 PCNT API 函數(四十一)
※ DIY - ESP32:ESP32 PCNT API 函數結構件及其它(四十二)

2018年 11月 27日 天氣報告
氣溫:19.2@ 19:20
相對濕度:百分之 92%
天氣:雨

沒有留言:

張貼留言