旋转编码器奇怪的行为

如何解决旋转编码器奇怪的行为

我对旋转编码器的结果(在串行监视器上)有问题。

我正在使用 Arduino UNO 和 RotaryEncoder 库。 当我运行 example code 时,串行监视器在以任何速度旋转时都显示正确的值。 我想使用编码器来改变 Df-player 中的音量。 当我想将此代码与更复杂的 Mp3 播放器一起使用时,问题就开始了。 它实际上只有在我非常非常缓慢地旋转编码器时才有效


#include <SPI.h>
#include <MFRC522.h>
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <RotaryEncoder.h>

#define RST_PIN         9           // Configurable,see typical pin layout above
#define SS_PIN          10          // Configurable,see typical pin layout above

#define PIN_IN1 2
#define PIN_IN2 3

#define ROTARYSTEPS 1
#define ROTARYMIN 0
#define ROTARYMAX 30

const int playPauseButton = 4;
const int shuffleButton = 5;

boolean isPlaying = false;

MFRC522 mfrc522(SS_PIN,RST_PIN);   // Create MFRC522 instance

SoftwareSerial mySoftwareSerial(5,6); // RX,TX

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type,int value);

// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1,PIN_IN2,RotaryEncoder::LatchMode::TWO03);

// Last kNown rotary position.
int lastPos = -1;

//*****************************************************************************************//
void setup() {
  Serial.begin(9600);                                           // Initialize serial communications with the PC,COMMENT OUT IF IT FAILS TO PLAY WHEN disCONNECTED FROM PC
  mySoftwareSerial.begin(9600);
  SPI.begin();                                                  // Init SPI bus
  mfrc522.PCD_Init();                                              // Init MFRC522 card

  while (! Serial);
  encoder.setPosition(5 / ROTARYSTEPS); // start with the value of 5.

  pinMode(playPauseButton,INPUT_PULLUP);
  pinMode(shuffleButton,INPUT_PULLUP);




  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
  }
  Serial.println(F("DFPlayer Mini online. Place card on reader to play a spesific song"));

  //myDFPlayer.volume(15);  //Set volume value. From 0 to 30
  //volumeLevel = map(analogRead(volumePot),1023,30);   //scale the pot value and volume level
  myDFPlayer.volume(5);
  //prevVolume = volumeLevel;

  //----Set different EQ----
  myDFPlayer.EQ(DFPLAYER_EQ_norMAL);
  //  myDFPlayer.EQ(DFPLAYER_EQ_POP);
  //  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
  //  myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
  //  myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
  //  myDFPlayer.EQ(DFPLAYER_EQ_BASS);

}



//*****************************************************************************************//
void loop() {
  encoder.tick();

  // get the current physical position and calc the logical position
  int newPos = encoder.getPosition() * ROTARYSTEPS;
 
  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;

  } else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  } // if

  if (lastPos != newPos) {
    Serial.println(newPos);
    myDFPlayer.volume(newPos);
    lastPos = newPos;
  } // if


  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  MFRC522::mifare_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  //some variables we need
  byte block;
  byte len;
  MFRC522::StatusCode status;



  if (digitalRead(playPauseButton) == LOW) {
    if (isPlaying) {
      myDFPlayer.pause();
      isPlaying = false;
      Serial.println("Paused..");
    }
    else {
      isPlaying = true;
      myDFPlayer.start();
      Serial.println("Playing..");
    }
    delay(500);
  }


  if (digitalRead(shuffleButton) == LOW) {
    myDFPlayer.randomAll();
    Serial.println("Shuffle Play");
    isPlaying = true;
    delay(1000);
  }


  //-------------------------------------------

  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if ( mfrc522.PICC_IsNewCardPresent()) {



    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
      return;
    }

    Serial.println(F("**Card Detected:**"));

    //-------------------------------------------

    mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card

    //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex

    //-------------------------------------------

    Serial.print(F("Number: "));


    //---------------------------------------- GET NUMBER AND PLAY THE SONG

    byte buffer2[18];
    block = 1;
    len = 18;

    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A,1,&key,&(mfrc522.uid)); //line 834
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("Authentication Failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }

    status = mfrc522.mifare_Read(block,buffer2,&len);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("Reading Failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }


    //PRINT NUMBER
    String number = "";

    for (uint8_t i = 0; i < 16; i++)
    {
      number += (char)buffer2[i];
    }
    number.trim();
    Serial.print(number);

    //PLAY SONG

    myDFPlayer.play(number.toInt());
    isPlaying = true;



    //----------------------------------------

    Serial.println(F("\n**End Reading**\n"));

    delay(1000); //change value if you want to read cards faster

    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();
  }
}

知道有什么问题吗?

解决方法

您的主循环中有一个 delay(1000),并且由于您的 RotaryEncoder 对象似乎需要一个 tick() 函数,我假设它不是中断驱动的。这意味着如果它已经移动到下一步,它每秒只会检查一次。

如果一个旋转编码器被步进两次,中间的步进被MCU漏掉了,后者就无法知道编码器转了哪一圈。

所以在这种情况下,你每秒只能转动一步。

您需要的是:

  • 一个自由运行的主循环,每秒至少循环 100 次。 (不太好)
  • 一个由中断驱动的旋转编码器驱动程序。 (非常好)

我不知道这样的库是否存在,因为我倾向于不使用 arduino 库,但是使用 GPIO 中断编写自己的库是一个很好的练习。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?