问题描述
我对旋转编码器的结果(在串行监视器上)有问题。
我正在使用 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 中断编写自己的库是一个很好的练习。