首页 > 解决方案 > 如何读取带有 ESP32 中断和全局标志的旋转编码器

问题描述

使用中断时,任何类型的 digitalRead 都应该过时,或者我认为。让我解释一下我对此的理解以显示我的问题:

比如说,正交增量旋转编码器 (RE) 在两个信号引脚上都被拉高,因此处于空闲状态。如果我在两个引脚的下降沿配置中断服务例程 (ISR) 并让引脚 B 的 ISR 仅将标志“flag_B”设置为 false(表示引脚的逻辑状态)和引脚的 ISR A 在 A 的 ISR 期间根据 flag_B 的状态设置或重置标志“flag_顺时针”,那么我应该为每个转弯步骤获得正确的方向,对吗?我唯一的任务是在 ISR 之后再次将引脚 B 的状态设置为高电平,并且我的代码应该为下一次中断做好准备。但这不起作用,当您感觉到一点“颠簸”时,在转动步骤的前半部分显示错误方向或逆时针显示的许多随机情况 在转动旋钮的同时,在下半部分顺时针方向转动,当轴完成一步时,基本上只转动一步就做了两个相反的动作。我的逻辑有问题吗?所有信号都在硬件中去抖动,并且在示波器上看起来像预期的那样。

ISR:

//re-CLK signal
void IRAM_ATTR reCLK_ISR(void){
  if(myFlags->pinBstate){
    //this means the first interrupt of a turning step comes from the clock, not data
    myFlags->direction = CCW;
  }
  else{
    //this means the interrupt of a turning step occured from data first
    myFlags->direction = CW;
  }
}

//re-DATA signal
void IRAM_ATTR reDATA_ISR(void){
  myFlags->pinDATAstate = false;
}

进一步处理:

//some function 

//scroll = CW / CCW
    if((myFlags->direction) != STOP){

      if(myFlags->direction == CW){ 

        //DEBUG
        digitalWrite(PIN_LED_DEBUG, LOW);

        }
      }
      if(myFlags->direction == CCW){

        //DEBUG
        digitalWrite(PIN_LED_DEBUG, HIGH);

      }
      myFlags->pinDATAstate = true;
      myFlags->direction = STOP;   //direction has 3 states: CW, CCW and STOP
    }

最后两条语句应该将所有受影响的标志恢复到编码器被触摸之前的状态,这意味着为下一回合做好准备。LED 只是替代应根据转向方向执行的不同计算。

标签: c++interruptstate-machineesp32encoder

解决方案


即使该引脚被分配为中断,您仍然可以使用它digitalRead()来确定方向。例如:

const uint8_t pinA = 25;
const uint8_t pinB = 26;
volatile int counter;

void IRAM_ATTR isr(){
  if(digitalRead(pinA) == digitalRead(pinB)) {
    //Clockwise
    counter++;
  } else {
    //Counter Clockwise
    counter--;
  }
}

您甚至不需要另一个 ISR 来确定方向。我用这种方法来确定速度和方向;


推荐阅读