ESP32 PULSE CNT脉冲计数器使用

ESP32 电子创客营 2396次浏览 已收录 0个评论 扫描二维码

ESP32 PULSE CNT脉冲计数器使用

基于esp32 IDF进行开发,实现对直流有刷电机的控制,同时要对转速通过霍尔传感器进行计数。esp32内部的外设还是挺多,所以一个功能也可以用不同的思路来实现。

ESP32内部有个专门驱动电机的mcpwm,该模块可以产生直驱动电机需要的PWM信号,同时还带的有捕获功能,可以对引脚上的脉冲记性计数,脉宽测量。本来是想用MCPWM的捕获功能来实现霍尔计数的的。但是之后看esp32的参考手册发现还有个PULSE CNT功能是专门进行脉冲个数计数的,这个更贴合于霍尔计数的使用。mcpwm内的捕获确实也可以实现,只是他获取到的是发生跳边沿之后之前的脉宽长度。所以假如要根据脉宽做软件滤波的话这个功能会更合适。

PULSE CNT功能它是可以直接硬件滤波,把变化过快的脉冲直接滤掉,避免进行对干扰信号计数。所以这个对于容易受电机干扰的霍尔传感器计数再适合不过。

下面就对PULSE CNT(下面就简称pcnt)功能做个大概介绍:他的功能很简单就是实现脉冲个数的计数。如果说要和STM32内部的一个功能类比的话,更像stm32定时器中的ENCODER编码器功能,我用stm32会比较多,所以自然而然的就会把他们进行对比。

pcnt内部一共有8组单元,每个单元有两个通道,每个通道都有一个脉冲输入脚和控制脚。这个脉冲输入脚很好理解,那么这个控制脚有什么用呢?这个脚也不难,通过软件配置可以用这个脚控制计数器是向上还是向下计数,当然软件里面也可以配置不使用。当然还有个地方需要注意,就是每个单元两个通道是连接在一个计数器上面的,所以通过这两个通道就可以实现对编码器的计数功能。但是假如我要对两路霍尔进行计数就必须要用两个单元。

pcnt的中断源呢一共有五个:

  • L_LIM            最小计数值中断,意思就是达到最小计数值的时候就会触发该中断,最小计数值在初始化的时候有配置
  • H_LIM           最大计数值中断,意思是达到最大计数值的时候回触发该中断
  • THRES_0       阈值0 中断,也就是自己设定一个值,当计数到达该值的时候就会触发中断
  • THRES_1       阈值1中断,和阈值0功能一样,只是可以设定两个阈值
  • ZERO            计数为0 中断,当计数器值记到0时产生该中断

因为我本次没有用到中断,所以中断使用的例子请参考官方IDF中的examples。

在深入进去看ESP官方资料的时候发现一个问题,pcnt在SDK寄存器列表里面有status_unit寄存器但是在参考手册上是没有的。所以吐槽一下使用国产的IC,这些资料的完整一致性有时候还真是经不起排查推敲。之前还发现sdk的一个使用的bug,反馈给官方,说回复我一个多星期现在也没回复,所以有的bug只能自己趟过然后记录下来。

下面就列下我自己基于esp-idf写的hall计数函数:

 

pcnt_unit_t hallPcntUint[2]={HALL_PCNT_UINT_L,HALL_PCNT_UINT_R};
void hallInit()
{
    pcnt_config_t pcnt_config = {
        // Set PCNT input signal and control GPIOs
        .pulse_gpio_num = HALL_GPIO_L,
        .ctrl_gpio_num = -1,
        .channel = PCNT_CHANNEL_0,
        .unit = HALL_PCNT_UINT_L,
        // 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_KEEP, // 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 = 30000,
        .counter_l_lim = 0,
    };
    /* Initialize PCNT unit */
    pcnt_unit_config(&pcnt_config);

    pcnt_config.pulse_gpio_num=HALL_GPIO_R;
    pcnt_config.unit=HALL_PCNT_UINT_R;
    pcnt_unit_config(&pcnt_config);         //初始化pcnt uint1

    /* Configure and enable the input filter */
    pcnt_set_filter_value(HALL_PCNT_UINT_L, 1000);
    pcnt_filter_enable(HALL_PCNT_UINT_L);
    pcnt_set_filter_value(HALL_PCNT_UINT_R, 1000);
    pcnt_filter_enable(HALL_PCNT_UINT_R);

    /* Initialize PCNT's counter */
    pcnt_counter_pause(HALL_PCNT_UINT_L);
    pcnt_counter_clear(HALL_PCNT_UINT_L);
    pcnt_counter_pause(HALL_PCNT_UINT_R);
    pcnt_counter_clear(HALL_PCNT_UINT_R);
    /* Everything is set up, now go to counting */
    
}

void hallStartCounter(uint8_t hall)
{
    pcnt_counter_pause(hallPcntUint[hall]);
    pcnt_counter_clear(hallPcntUint[hall]);
    pcnt_counter_resume(hallPcntUint[hall]);  
}
void hallStopCounter(uint8_t hall)
{

    pcnt_counter_pause(hallPcntUint[hall]);
    pcnt_counter_clear(hallPcntUint[hall]);          
}
void hallClearCounter(uint8_t hall)
{
    pcnt_counter_clear(hallPcntUint[hall]);     
}
int16_t hallGetCounter(uint8_t hall)
{
    int16_t count;
    pcnt_get_counter_value(hallPcntUint[hall],&count);
    return  count;       
}

转载请注明转自电子创客营:ESP32 PULSE CNT脉冲计数器使用! 了解我们点击这里

微信扫一扫关注我们的公众号:eemaker

ESP32 PULSE CNT脉冲计数器使用


喜欢 (0)or分享 (0)
电子创客营
关于作者:

您必须 登录 才能发表评论!