首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将此arduino instructable改编为ESP32

将此arduino instructable改编为ESP32
EN

Stack Overflow用户
提问于 2018-12-16 21:10:11
回答 2查看 1.8K关注 0票数 0

我正在尝试创建一个类似于这里找到的项目:

Easy Arduino Menus for Rotary Encoders

但是,我使用的是ESP32,而不是Arduino板。

要做到这一点,我需要让我的扶轮编码器使用他的代码:Improved Arduino Rotary Encoder Reading

但是,我不能编译代码并在"PIND“上得到一个错误。这一行:

代码语言:javascript
复制
reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values.

所以我的问题是:你有关于如何调整编码器代码以与ESP32一起工作的想法吗?

在此之前非常感谢。:)

他的完整代码如下:

代码语言:javascript
复制
/*******Interrupt-based Rotary Encoder Sketch*******
by Simon Merrett, based on insight from Oleg Mazurov, Nick Gammon, rt, Steve Spence
*/

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent

void setup() {
  pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
  attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
  attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
  Serial.begin(115200); // start the serial monitor link
}

void PinA(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
  if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    encoderPos --; //decrement the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void PinB(){
  cli(); //stop interrupts happening before we read pin values
  reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
  if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
    encoderPos ++; //increment the encoder's position count
    bFlag = 0; //reset flags for the next turn
    aFlag = 0; //reset flags for the next turn
  }
  else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
  sei(); //restart interrupts
}

void loop(){
  if(oldEncPos != encoderPos) {
    Serial.println(encoderPos);
    oldEncPos = encoderPos;
  }
}

EN

回答 2

Stack Overflow用户

发布于 2020-05-23 01:47:50

您推荐的库(https://github.com/igorantolic/ai-esp32-rotary-encoder)不太可靠。你会得到很多错误的读数。当我需要使用旋转编码器时,我坚持使用上面的例子。

我将其改编为ESP32:

幸运的是,GPIO34和GPIO35几乎是一样的。

GPIO34是二进制100

GPIO35是二进制1000

1100或0xC

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf

58页:

GPIO_IN_REG --> GPIO0...31

GPIO_IN1_REG --> GPIO32...39

请注意,GPIO 34、35、36和39需要上拉电阻。否则,您可以使用INPUT_PULLUP

代码语言:javascript
复制
#include <Arduino.h>

static int pinA = 35;
static int pinB = 34;
volatile byte aFlag = 0;
volatile byte bFlag = 0;
volatile byte encoderPos = 0;
volatile byte oldEncPos = 0;
volatile byte reading = 0;

void IRAM_ATTR PinA()
{
  cli();
  reading = GPIO_REG_READ(GPIO_IN1_REG) & 0xC;
  if (reading == B1100 && aFlag)
  {
    encoderPos--;
    bFlag = 0;
    aFlag = 0;
  }
  else if (reading == B1000)
    bFlag = 1;
  sei();
}

void IRAM_ATTR PinB()
{
  cli();
  reading = GPIO_REG_READ(GPIO_IN1_REG) & 0xC;
  if (reading == B1100 && bFlag)
  {
    encoderPos++;
    bFlag = 0;
    aFlag = 0;
  }
  else if (reading == B100)
    aFlag = 1;
  sei();
}

void setup()
{
  Serial.begin(115200);

  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  attachInterrupt(digitalPinToInterrupt(pinA), PinA, RISING);
  attachInterrupt(digitalPinToInterrupt(pinB), PinB, RISING);
}

void loop()
{
  if (oldEncPos != encoderPos)
  {
    Serial.print("encoderPos: ");
    Serial.println(encoderPos);
    oldEncPos = encoderPos;
  }
}
票数 2
EN

Stack Overflow用户

发布于 2018-12-17 01:24:21

PIND是仅用于兼容Arduino板的寄存器之一,可用于所谓的直接端口操作。

具体而言,引脚是端口D的输入寄存器(UNO上的引脚0至7)

例如,读取此寄存器将给出从PIN0到PIN7的每个gpio的输入状态。在旋转编码器中,它用于一次性读取PORTD值,然后屏蔽其他引脚,除了"pinA“和"pinB”,它们分别是引脚2和引脚3。

这不会在ESP32上工作,因为该平台没有这样的寄存器(请记住,您在这里进行的是直接硬件访问,而不是通过标准的Arduino API)您可以在ESP32中查看GPIO_IN_REG,您可以使用它以类似的方式读取GPIO引脚状态。GPIO_IN_REG将返回GPIO 0- 31的输入值。

你也可以尝试使用这个库:https://github.com/igorantolic/ai-esp32-rotary-encoder,如果你需要已经制作的东西,而不是重新发明轮子,除非它是为了你的学习目的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53802457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档