KY-040 (Poti) Laut/Leise Start/Stop


#1

Hallo zusammen,

habe meinen ersten TonUINO zusammen gebaut und es hat auf anhieb funktioniert. Danke für großartige Arbeit. Hab auch ein paar Platinen gekauft…obwohl ich alles frei verdrahtet hab.

Ich möchte gerne die Lautstärke und Start/Stop über einen Drehimpulsgeber (KY 040) steuern. Dieser benötigt aber die Eingänge D2/D3 (Interupt-Eingänge). Wäre es ein Problem den Softserial auf die Eingänge D5/D6 zu verschieben?

Hat dies schon jemand realisiert? Möchte nicht das Rad neu erfinden…
Über hilfe würde ich mich sehr freuen, da mir das mit dem C schon recht schwer fällt.

Gruß
Thomas


#2

Prinzipiell kannst du die Serial für den DFPlayer auf jede zwei freie D Pins verlegen, da Du ja die Platine nicht verwendest. Das ist quasi eine Zeile code anpassen. Mit Platine geht das natürlich nicht. Drehimpulsgeber wurden hier und schon mal erwähnt. Musste mal suchen. Ob da fertiger code bei raus gekommen ist, weiss ich aber nicht mehr.


#3

Ich hab mit der Suchfunktion nichts fertiges finden können.

Der Hintergrund ist der, das meine Kinder (und meine Frau) Probleme hatten, die Lautstärke anzupassen. Entweder zu Leise, zu Laut oder der nächste Titel.

Ich hab mal selber was zusammen geklaut. Wäre nett, wenn da mal jemand drüber schaut. Ich habe die Angewohnheit, Programme etwas zu verkomplizieren. Was erschwerend hinzukommt, das ich nicht wirklich programmieren kann.

Die Lautstärke läßt sich über das Poti regeln, der Button des KY 040 ist jetzt ON/OFF. Ich hab den D5 frei gelassen falls mal ne LED mit PWM angesteuert werden soll…

Sketch

#include <DFMiniMp3.h>
#include <EEPROM.h>
#include <JC_Button.h>
#include <MFRC522.h>
#include <SPI.h>
#include <SoftwareSerial.h>

// DFPlayer Mini
SoftwareSerial mySoftwareSerial(6, 7); // RX, TX
uint16_t numTracksInFolder;
uint16_t currentTrack;

// this object stores nfc tag data
struct nfcTagObject {
uint32_t cookie;
uint8_t version;
uint8_t folder;
uint8_t mode;
uint8_t special;
};

nfcTagObject myCard;

static void nextTrack(uint16_t track);
int voiceMenu(int numberOfOptions, int startMessage, int messageOffset,
bool preview = false, int previewFromFolder = 0);

bool knownCard = false;

// implement a notification class,
// its member methods will get called
//
class Mp3Notify {
public:
static void OnError(uint16_t errorCode) {
// see DfMp3_Error for code meaning
Serial.println();
Serial.print("Com Error ");
Serial.println(errorCode);
}
static void OnPlayFinished(uint16_t track) {
Serial.print(“Track beendet”);
Serial.println(track);
delay(100);
nextTrack(track);
}
static void OnCardOnline(uint16_t code) {
Serial.println(F("SD Karte online "));
}
static void OnCardInserted(uint16_t code) {
Serial.println(F("SD Karte bereit "));
}
static void OnCardRemoved(uint16_t code) {
Serial.println(F("SD Karte entfernt "));
}
};

static DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(mySoftwareSerial);

// Leider kann das Modul keine Queue abspielen.
static uint16_t _lastTrackFinished;
static void nextTrack(uint16_t track) {
if (track == _lastTrackFinished) {
return;
}
_lastTrackFinished = track;

if (knownCard == false)
// Wenn eine neue Karte angelernt wird soll das Ende eines Tracks nicht
// verarbeitet werden
return;

if (myCard.mode == 1) {
Serial.println(F(“Hörspielmodus ist aktiv -> keinen neuen Track spielen”));
// mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
}
if (myCard.mode == 2) {
if (currentTrack != numTracksInFolder) {
currentTrack = currentTrack + 1;
mp3.playFolderTrack(myCard.folder, currentTrack);
Serial.print(F("Albummodus ist aktiv -> nächster Track: "));
Serial.print(currentTrack);
} else
// mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
{ }
}
if (myCard.mode == 3) {
uint16_t oldTrack = currentTrack;
currentTrack = random(1, numTracksInFolder + 1);
if (currentTrack == oldTrack)
currentTrack = currentTrack == numTracksInFolder ? 1 : currentTrack+1;
Serial.print(F("Party Modus ist aktiv -> zufälligen Track spielen: "));
Serial.println(currentTrack);
mp3.playFolderTrack(myCard.folder, currentTrack);
}
if (myCard.mode == 4) {
Serial.println(F(“Einzel Modus aktiv -> Strom sparen”));
// mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
}
if (myCard.mode == 5) {
if (currentTrack != numTracksInFolder) {
currentTrack = currentTrack + 1;
Serial.print(F("Hörbuch Modus ist aktiv -> nächster Track und "
“Fortschritt speichern”));
Serial.println(currentTrack);
mp3.playFolderTrack(myCard.folder, currentTrack);
// Fortschritt im EEPROM abspeichern
EEPROM.write(myCard.folder, currentTrack);
} else {
// mp3.sleep(); // Je nach Modul kommt es nicht mehr zurück aus dem Sleep!
// Fortschritt zurück setzen
EEPROM.write(myCard.folder, 1);
}
}
}

static void previousTrack() {
if (myCard.mode == 1) {
Serial.println(F(“Hörspielmodus ist aktiv -> Track von vorne spielen”));
mp3.playFolderTrack(myCard.folder, currentTrack);
}
if (myCard.mode == 2) {
Serial.println(F(“Albummodus ist aktiv -> vorheriger Track”));
if (currentTrack != 1) {
currentTrack = currentTrack - 1;
}
mp3.playFolderTrack(myCard.folder, currentTrack);
}
if (myCard.mode == 3) {
Serial.println(F(“Party Modus ist aktiv -> Track von vorne spielen”));
mp3.playFolderTrack(myCard.folder, currentTrack);
}
if (myCard.mode == 4) {
Serial.println(F(“Einzel Modus aktiv -> Track von vorne spielen”));
mp3.playFolderTrack(myCard.folder, currentTrack);
}
if (myCard.mode == 5) {
Serial.println(F("Hörbuch Modus ist aktiv -> vorheriger Track und "
“Fortschritt speichern”));
if (currentTrack != 1) {
currentTrack = currentTrack - 1;
}
mp3.playFolderTrack(myCard.folder, currentTrack);
// Fortschritt im EEPROM abspeichern
EEPROM.write(myCard.folder, currentTrack);
}
}

// MFRC522
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522
MFRC522::MIFARE_Key key;
bool successRead;
byte sector = 1;
byte blockAddr = 4;
byte trailerBlock = 7;
MFRC522::StatusCode status;

#define buttonPause 4 //original A0 (KY 040)
#define buttonUp A1
#define buttonDown A2
#define busyPin 8 // original 4 (KY 040)
#define CLK 2 // KY 040 A
#define DT 3 // KY 040 B

#define LONG_PRESS 1000

Button pauseButton(buttonPause);
Button upButton(buttonUp);
Button downButton(buttonDown);
bool ignorePauseButton = false;
bool ignoreUpButton = false;
bool ignoreDownButton = false;

int old_Volume = 1, Volume = 0, max_Volume = 30;
bool A, B, drehen = 0;

uint8_t numberOfCards = 0;

bool isPlaying() { return !digitalRead(busyPin); }

void setup() {

Serial.begin(115200); // Es gibt ein paar Debug Ausgaben über die serielle
// Schnittstelle
randomSeed(analogRead(A0)); // Zufallsgenerator initialisieren

Serial.println(F(“TonUINO Version 2.0”));
Serial.println(F(“© Thorsten Voß”));

// Knöpfe mit PullUp
pinMode(buttonPause, INPUT_PULLUP);
pinMode(buttonUp, INPUT_PULLUP);
pinMode(buttonDown, INPUT_PULLUP);

// KY 040
pinMode(CLK, INPUT_PULLUP); attachInterrupt(0, Lauter, CHANGE);
pinMode(DT, INPUT_PULLUP); attachInterrupt(1, Leiser, CHANGE);

// Busy Pin
pinMode(busyPin, INPUT);

// DFPlayer Mini initialisieren
mp3.begin();
mp3.setVolume(15);

// NFC Leser initialisieren
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
mfrc522
.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}

// RESET — ALLE DREI KNÖPFE BEIM STARTEN GEDRÜCKT HALTEN -> alle bekannten
// Karten werden gelöscht
if (digitalRead(buttonPause) == LOW && digitalRead(buttonUp) == LOW &&
digitalRead(buttonDown) == LOW) {
Serial.println(F(“Reset -> EEPROM wird gelöscht”));
for (int i = 0; i < EEPROM.length(); i++) {
EEPROM.write(i, 0);
}
}

}

void loop() {
do {
mp3.loop();
// Buttons werden nun über JS_Button gehandelt, dadurch kann jede Taste
// doppelt belegt werden
pauseButton.read();
upButton.read();
downButton.read();

// #######################################################

  drehen = true;  // zurücksetzen entprellvariable

if (old_Volume != Volume)
{ Serial.print(“Volume:”);
Serial.println(Volume);
mp3.setVolume(Volume);
old_Volume = Volume; }

// #######################################################

if (pauseButton.wasReleased()) {
  if (ignorePauseButton == false)
    if (isPlaying())
      mp3.pause();
    else
      mp3.start();
  ignorePauseButton = false;
} else if (pauseButton.pressedFor(LONG_PRESS) &&
           ignorePauseButton == false) {
  if (isPlaying())
    mp3.playAdvertisement(currentTrack);
  else {
    knownCard = false;
    mp3.playMp3FolderTrack(800);
    Serial.println(F("Karte resetten..."));
    resetCard();
    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();
  }
  ignorePauseButton = true;
}

// ******************* alte Lautstärkeregelung **************************
if (upButton.wasReleased()) {
if (!ignoreUpButton)
nextTrack(random(65536));
else
ignoreUpButton = false;
}

if (downButton.wasReleased()) {
  if (!ignoreDownButton)
    previousTrack();
  else
    ignoreDownButton = false;
}

// *******************************************************************

// Ende der Buttons

} while (!mfrc522.PICC_IsNewCardPresent());

// RFID Karte wurde aufgelegt

if (!mfrc522.PICC_ReadCardSerial())
return;

if (readCard(&myCard) == true) {
if (myCard.cookie == 322417479 && myCard.folder != 0 && myCard.mode != 0) {

  knownCard = true;
  _lastTrackFinished = 0;
  numTracksInFolder = mp3.getFolderTrackCount(myCard.folder);
  Serial.print(numTracksInFolder);
  Serial.print(F(" Dateien in Ordner "));
  Serial.println(myCard.folder);

  // Hörspielmodus: eine zufällige Datei aus dem Ordner
  if (myCard.mode == 1) {
    Serial.println(F("Hörspielmodus -> zufälligen Track wiedergeben"));
    currentTrack = random(1, numTracksInFolder + 1);
    Serial.println(currentTrack);
    mp3.playFolderTrack(myCard.folder, currentTrack);
  }
  // Album Modus: kompletten Ordner spielen
  if (myCard.mode == 2) {
    Serial.println(F("Album Modus -> kompletten Ordner wiedergeben"));
    currentTrack = 1;
    mp3.playFolderTrack(myCard.folder, currentTrack);
  }
  // Party Modus: Ordner in zufälliger Reihenfolge
  if (myCard.mode == 3) {
    Serial.println(
        F("Party Modus -> Ordner in zufälliger Reihenfolge wiedergeben"));
    currentTrack = random(1, numTracksInFolder + 1);
    mp3.playFolderTrack(myCard.folder, currentTrack);
  }
  // Einzel Modus: eine Datei aus dem Ordner abspielen
  if (myCard.mode == 4) {
    Serial.println(
        F("Einzel Modus -> eine Datei aus dem Odrdner abspielen"));
    currentTrack = myCard.special;
    mp3.playFolderTrack(myCard.folder, currentTrack);
  }
  // Hörbuch Modus: kompletten Ordner spielen und Fortschritt merken
  if (myCard.mode == 5) {
    Serial.println(F("Hörbuch Modus -> kompletten Ordner spielen und "
                     "Fortschritt merken"));
    currentTrack = EEPROM.read(myCard.folder);
    mp3.playFolderTrack(myCard.folder, currentTrack);
  }
}

// Neue Karte konfigurieren
else {
  knownCard = false;
  setupCard();
}

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

int voiceMenu(int numberOfOptions, int startMessage, int messageOffset,
bool preview = false, int previewFromFolder = 0) {
int returnValue = 0;
if (startMessage != 0)
mp3.playMp3FolderTrack(startMessage);
do {
pauseButton.read();
upButton.read();
downButton.read();
mp3.loop();
if (pauseButton.wasPressed()) {
if (returnValue != 0)
return returnValue;
delay(1000);
}

if (upButton.pressedFor(LONG_PRESS)) {
  returnValue = min(returnValue + 10, numberOfOptions);
  mp3.playMp3FolderTrack(messageOffset + returnValue);
  delay(1000);
  if (preview) {
    do {
      delay(10);
    } while (isPlaying());
    if (previewFromFolder == 0)
      mp3.playFolderTrack(returnValue, 1);
    else
      mp3.playFolderTrack(previewFromFolder, returnValue);
  }
  ignoreUpButton = true;
} else if (upButton.wasReleased()) {
  if (!ignoreUpButton) {
    returnValue = min(returnValue + 1, numberOfOptions);
    mp3.playMp3FolderTrack(messageOffset + returnValue);
    delay(1000);
    if (preview) {
      do {
        delay(10);
      } while (isPlaying());
      if (previewFromFolder == 0)
        mp3.playFolderTrack(returnValue, 1);
      else
        mp3.playFolderTrack(previewFromFolder, returnValue);
    }
  } else
    ignoreUpButton = false;
}

if (downButton.pressedFor(LONG_PRESS)) {
  returnValue = max(returnValue - 10, 1);
  mp3.playMp3FolderTrack(messageOffset + returnValue);
  delay(1000);
  if (preview) {
    do {
      delay(10);
    } while (isPlaying());
    if (previewFromFolder == 0)
      mp3.playFolderTrack(returnValue, 1);
    else
      mp3.playFolderTrack(previewFromFolder, returnValue);
  }
  ignoreDownButton = true;
} else if (downButton.wasReleased()) {
  if (!ignoreDownButton) {
    returnValue = max(returnValue - 1, 1);
    mp3.playMp3FolderTrack(messageOffset + returnValue);
    delay(1000);
    if (preview) {
      do {
        delay(10);
      } while (isPlaying());
      if (previewFromFolder == 0)
        mp3.playFolderTrack(returnValue, 1);
      else
        mp3.playFolderTrack(previewFromFolder, returnValue);
    }
  } else
    ignoreDownButton = false;
}

} while (true);
}

void resetCard() {
do {
pauseButton.read();
upButton.read();
downButton.read();

if (upButton.wasReleased() || downButton.wasReleased()) {
  Serial.print(F("Abgebrochen!"));
  mp3.playMp3FolderTrack(802);
  return;
}

} while (!mfrc522.PICC_IsNewCardPresent());

if (!mfrc522.PICC_ReadCardSerial())
return;

Serial.print(F(“Karte wird neu Konfiguriert!”));
setupCard();
}

void setupCard() {
mp3.pause();
Serial.print(F(“Neue Karte konfigurieren”));

// Ordner abfragen
myCard.folder = voiceMenu(99, 300, 0, true);

// Wiedergabemodus abfragen
myCard.mode = voiceMenu(6, 310, 310);

// Hörbuchmodus -> Fortschritt im EEPROM auf 1 setzen
EEPROM.write(myCard.folder,1);

// Einzelmodus -> Datei abfragen
if (myCard.mode == 4)
myCard.special = voiceMenu(mp3.getFolderTrackCount(myCard.folder), 320, 0,
true, myCard.folder);

// Admin Funktionen
if (myCard.mode == 6)
myCard.special = voiceMenu(3, 320, 320);

// Karte ist konfiguriert -> speichern
mp3.pause();
writeCard(myCard);
}

bool readCard(nfcTagObject *nfcTag) {
bool returnValue = true;
// Show some details of the PICC (that is: the tag/card)
Serial.print(F(“Card UID:”));
dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
Serial.println();
Serial.print(F("PICC type: "));
MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
Serial.println(mfrc522.PICC_GetTypeName(piccType));

byte buffer[18];
byte size = sizeof(buffer);

// Authenticate using key A
Serial.println(F(“Authenticating using key A…”));
status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(
MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
returnValue = false;
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}

// Show the whole sector as it currently is
Serial.println(F(“Current data in sector:”));
mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
Serial.println();

// Read data from the block
Serial.print(F(“Reading data from block “));
Serial.print(blockAddr);
Serial.println(F(” …”));
status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(blockAddr, buffer, &size);
if (status != MFRC522::STATUS_OK) {
returnValue = false;
Serial.print(F("MIFARE_Read() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
}
Serial.print(F(“Data in block “));
Serial.print(blockAddr);
Serial.println(F(”:”));
dump_byte_array(buffer, 16);
Serial.println();
Serial.println();

uint32_t tempCookie;
tempCookie = (uint32_t)buffer[0] << 24;
tempCookie += (uint32_t)buffer[1] << 16;
tempCookie += (uint32_t)buffer[2] << 8;
tempCookie += (uint32_t)buffer[3];

nfcTag->cookie = tempCookie;
nfcTag->version = buffer[4];
nfcTag->folder = buffer[5];
nfcTag->mode = buffer[6];
nfcTag->special = buffer[7];

return returnValue;
}

void writeCard(nfcTagObject nfcTag) {
MFRC522::PICC_Type mifareType;
byte buffer[16] = {0x13, 0x37, 0xb3, 0x47, // 0x1337 0xb347 magic cookie to
// identify our nfc tags
0x01, // version 1
nfcTag.folder, // the folder picked by the user
nfcTag.mode, // the playback mode picked by the user
nfcTag.special, // track or function for admin cards
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

byte size = sizeof(buffer);

mifareType = mfrc522.PICC_GetType(mfrc522.uid.sak);

// Authenticate using key B
Serial.println(F(“Authenticating again using key B…”));
status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(
MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print(F("PCD_Authenticate() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
mp3.playMp3FolderTrack(401);
return;
}

// Write data to the block
Serial.print(F(“Writing data into block “));
Serial.print(blockAddr);
Serial.println(F(” …”));
dump_byte_array(buffer, 16);
Serial.println();
status = (MFRC522::StatusCode)mfrc522.MIFARE_Write(blockAddr, buffer, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Write() failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
mp3.playMp3FolderTrack(401);
}
else
mp3.playMp3FolderTrack(400);
Serial.println();
delay(100);
}

/**

  • Helper routine to dump a byte array as hex values to Serial.
    */
    void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
    }
    }

//*************** Lautstärkeregelung über Poti ***************

void Lauter(){
if (drehen) delay (1); // entprellen
if(digitalRead(CLK) != A) {A = !A;
if ( A && !B && Volume != max_Volume)
Volume ++;
drehen = false; // entprellen
}}

void Leiser(){
if (drehen) delay (1);
if(digitalRead(DT) != B) {B = !B;
if(B && !A && Volume !=0)
Volume --;
drehen = false;
}}

//***************************************************************


#4

Hast du was programmiert?
Ich habe da gestern auch nachgeschaut und auch was gefunden.
Ich bin aber nicht fit im programmieren.

Hier mal eine lib

Wenn ich den Code und die Beispiele richtig verstehe müsste man da immer nur ein Wert rauskommt also eine endposition immer Zwischenspeichern und dann beim verdrehen immer wieder prüfen um wieviel der Wert sichveränder hat und das dann auf die entsprechenden Pins rausgeben mit Volumen Up oder down.

Mit einem Poti gibt es hier eine Lösung.
Max Lautstärke immer fest einstellen und den poti in Reihe zwischen dem Lautsprecher + Kanal z.b.

Beim pi war das einfacher da man in den Skript direkt die entsprechenden Pin einträgt und auch die verschiedenen Befehle.

Beispiel


#5

Hi,

Ist alles schon fertig programmiert. Es wird keine zusätzliche Libery benötigt.
Einfach den Drehimpulsgeber an die Pins 2,3,4, 5V, und GND anschließen. (Die Serielle Kommunikation des DF PLayers verschiebt sich auf Pin 6 und 7. Den Pin 5 hab ich für eine evtl. Status LED frei gelassen, da dieser Pin PulsWeitenModulation beherscht.

Mit dem Drehimpulsgeber wird einfach hoch und runter gezählt und bei einer änderung der Wert an den DFPlayer übergeben. (Außerdem wird noch entprellt)

Der einzigste Nachteil ist meiner Meinung nach, das die Platine von @Thorsten nicht benutzt werden kann.

Der Code ist sicherlich noch zu kompliziert geschrieben, funktioniert aber. UND es sind nach wie vor nur 3 Bedienknöpfe.

Gruß
Thomas


#6

Kannst du den Code hier mal veröffentlichen? Interessiert mich sehr.


#7

Ist doch. Im 3. Artikel unter den Bildern. Einfach Sketch aufklappen :wink:


#8

Ah
Nicht gesehen und ich schreibe so viel.
Danke


#9

Hallo Samoht, (beim Schreiben deines Names ist mir aufgefallen dass da wohl was verdreht ist :slight_smile:)
danke für den Sketch.
Die Lautstärke so verstellen finde ich sehr elegant.
Heute sind meine KY-040 gekommen und hab gleich den Sketch probiert.
Zählen tut dein Programm, leider prellen die Drehgeber. Hab auch 2 andere Programme probiert.
Wie ist es bei dir? Hast du Kondensatoren oder ähnliches zum Entprellen drin?
Oder liegt es an meinen Breadboardaufbau? Ich gehe aber davon aus dass die Verbindungen gut sind.
Gruß Uli


#10

Hi Uli,

ich hab diese Dreh-Impuls-Geber verwendet:
KY-040
Soweit ich erkennen kann, haben die keine Kondensatoren nur Widerstände an board.

Hast du den Sketch komplett kopiert? Wenn ich das richtig zusammen geklaut hab, wird in der Software entprellt. Evtl. hilft es, die Verzögerung zu erhöhen.

//*************** Lautstärkeregelung über Poti ***************

void Lauter(){
if (drehen) delay (1); // entprellen
if(digitalRead(CLK) != A) {A = !A;
if ( A && !B && Volume != max_Volume)
Volume ++;
drehen = false; // entprellen
}}

void Leiser(){
if (drehen) delay (1);
if(digitalRead(DT) != B) {B = !B;
if(B && !A && Volume !=0)
Volume --;
drehen = false;
}}

//***************************************************************

Ich hab ein paar variablen angepasst, bei mir machte es keinen Unterschied:

Volume:
volatile unsigned int --> int

drehen:
static boolean rotating --> bool

Evtl. ist das eine Hilfe für dich? Ich bin kein auch kein richtig guter c++ programmer…

Gruß
Thomas


#11

Hallo Thomas,
ja ich habe den aufgeführten Sketch von dir komplett kopiert. Bei dir funktioniert er so?
Ich habe noch die Gänsefüßchen abänder müssen, da sonst der Sketch Fehler hatte.
Ich habe die selben Drehgeber wie du gekauft.
Testweise habe ich jetzt schon 3 andere Sketche probiert. Die Drehgeber prellen immer.
Komisch.
Gruß Uli


#12

ich weiß nicht ob man das so darf. den Sketch hab ich mir hier geklaut und angepasst:
https://www.nikolaus-lueneburg.de/2016/02/rotary-encoder/

Original

#define encoderPinA 2
#define encoderPinB 3

volatile unsigned int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating=false; // debounce management

// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;

void setup() {

pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);

digitalWrite(encoderPinA, HIGH); // turn on pullup resistors
digitalWrite(encoderPinB, HIGH); // turn on pullup resistors

attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)

Serial.begin(9600); // output
}

void loop()
{
rotating = true; // reset the debouncer

if (lastReportedPos != encoderPos)
{
Serial.print(“Index:”);
Serial.println(encoderPos, DEC);
lastReportedPos = encoderPos;
}
}

// Interrupt on A changing state
void doEncoderA()
{
if ( rotating ) delay (1); // wait a little until the bouncing is done
if( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
encoderPos += 1;
rotating = false; // no more debouncing until loop() hits again
}
}

// Interrupt on B changing state, same as A above
void doEncoderB(){
if ( rotating ) delay (1);
if( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if( B_set && !A_set )
encoderPos -= 1;
rotating = false;
}
}

hat eigentlich auf anhieb funktioniert. Ich muss aber auch sagen, dass ich nur einen KY-040 getestet habe…alle anderen sind noch original verpackt.


#13

Hallo Thomas,
danke erstmal noch für deine schnelle Antworten.
Ich habe den Sketch jetzt probiert und es funktioniert ohne zu prellen.
Keine Ahnung warum deiner bei mir nicht geht. (Hat vlt. mit dem rauskopieren von der Webseite hier zu tun. Er ist ja mal eingerückt und mal wieder nicht)
Dann mach ich mal mit dem jetzt weiter und versuche es in die aktuelle Version einzubinden.
Gruß Uli


#14

Hmm, ich weiß auch nicht, wie ich eine Datei hier Hochladen kann, dann würde ich die .ino zur verfügung stellen. Bei Github bin ich nicht angemeldet…

Gruß