PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Arduino MEGA 2560 Pro Micro mit Rotary Encoder



Lord Integer
18.10.2020, 13:02
Moin,

ich habe mir einen Arduino MEGA 2560 Pro Micro angeschafft und versuche schon seit einigen Tagen einen Rotary Encoder zu benutzen.

Arduino: https://www.amazon.de/ARCELI-Arduino-Mega-ATmega2560-CH340G-Elektronik/dp/B07MQ1J9MR/ref=sr_1_9?__mk_de_DE=ÅMÅŽÕÑ&dchild=1&keywords=arduino+mega&qid=1603022275&quartzVehicle=1480-1518&replacementKeywords=arduino&sr=8-9

Encoder: https://www.amazon.de/WayinTop-Encoder-Drehgeber-Drehwinkelgeber-Druckknopf/dp/B07T3672VK/ref=sr_1_3?__mk_de_DE=ÅMÅŽÕÑ&dchild=1&keywords=Rotary+encoder&qid=1603022349&sr=8-3

Habe schon endliche Beispiele mit irgendwelchen Libs ausprobiert.
Aber, um es besser zu verstehen , habe ich mir einen Sketch gebastelt der 2 Interrups nimmt. Dieser Sketch funktioniert einwandfrei auf einem Arduino Nano mit Pin 2,3.
Laut Recherche sind die digitalen Interrupt Pins von einem Mega, Mega2560, MegaADK = 2, 3, 18, 19, 20, 21 gültig.

Ich hoffe mir kann jemand weiterhelfen.
Beste Grüße




/************************************************** ************************************************** ************************************/
#define EcButtonPin_SW 8
#define EcPin_CLK 2//A
#define EcPin_DT 3//B
/***********************/
#define MinEncoderPos 0
#define MaxEncoderPos 30
/***********************/
volatile unsigned int encoderPos = 0;
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
/***********************/
// interrupt service routine variables
boolean A_set = false;
boolean B_set = false;
/************************************************** ************************************************** ************************************/

void setup()
{
Serial.begin(9600);
pinMode (EcButtonPin_SW, INPUT);
pinMode (EcPin_CLK,INPUT);//A
pinMode (EcPin_DT,INPUT);//B

digitalWrite(EcPin_CLK, HIGH); // turn on pullup resistors
digitalWrite(EcPin_DT, 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)
}

void loop()
{
CheckAndSetEncoderPos();
}

void CheckAndSetEncoderPos()
{
rotating = true; // reset the debouncer
if (lastReportedPos != encoderPos)
{
Serial.print("lastPosition: => ");
Serial.print(lastReportedPos);
Serial.print(" ------------------- ");
lastReportedPos = encoderPos;

Serial.print("newPosition: => ");
Serial.println(lastReportedPos);
}
}

// ------------- Interrupt Service Routines ------------------------------
// ISR Interrupt on A changing state (Increment position counter)
void doEncoderA()
{
if ( rotating ) delay(1); // wait a little until the bouncing is done
if( digitalRead(EcPin_CLK) != A_set ) // debounce once more
{
A_set = !A_set;
if (A_set && !B_set)
if(encoderPos <=(MaxEncoderPos -1))
{
encoderPos += 1; // adjust counter +1 if A leads B
}
rotating = false; // no more debouncing until loop() hits again
}
}// ------------------- doEncoderA ----------------------------------------
// ISR Interrupt on B changing state, same as A above
void doEncoderB()
{
if ( rotating ) delay(1);
if( digitalRead(EcPin_DT) != B_set )
{
B_set = !B_set;
if( B_set && !A_set )
if(encoderPos >=(MinEncoderPos +1) )
{
encoderPos -= 1; //adjust counter -1 if B leads A
}
rotating = false;
}
}// -------------------- doEncoderB --------------------------------------

Searcher
18.10.2020, 14:55
attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)


Moin moin,

ich bin jetzt nicht der Arduino Spezialist aber beim Versuch Deinen Code zu verstehen, bin ich auf obige zwei Zeilen gestoßen.

Die Seite hier; https://www.arduino.cc/reference/de/language/functions/external-interrupts/attachinterrupt/ sagt:


Syntax

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) (Empfohlen)
attachInterrupt(interrupt, ISR, mode) (Nicht empfohlen)
attachInterrupt(pin, ISR, mode) (Nicht empfohlen; Funktioniert nur auf Arduino SAMD-, Uno WiFi Rev2-, Due- und 101-Boards.)

Also besser mit Variante "attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)" versuchen :confused:

Gruß
Searcher

Lord Integer
18.10.2020, 16:05
Hi Searcher,

danke für den Tipp.
Bekomme es aber irgendwie immer noch nicht hin.
Habe jetzt mit deiner vorgeschlagenen Syntax mit digitalPinToInterrupt(pin) beim AttachInterrupt die
INT.0 INT.1 | INT.2 INT.3 | INT.4 INT.5
Pin2 Pin3 | Pin21 Pin20 | Pin19 Pin18

getestet.

Irgendwas ist noch nicht richtig.
Die Interruptnummern und die digitalenPins des Arduino MEGA 2560 Pro Micro.stimmen anscheinend nicht.

Habe das mit den digitalPinToInterrupt(pin) bei einem Arduino Nano und Uno getestet. Dort geht alles.

Moppi
18.10.2020, 16:08
Hallo,

da war aber einer schnell (ich zu langsam) :)

Ok, vielleicht hilft es trotzdem noch.

Vorschlag (Searchers mit eingearbeitet):


Diesen Programmteil


void setup()
{
Serial.begin(9600);
pinMode (EcButtonPin_SW, INPUT);
pinMode (EcPin_CLK,INPUT);//A
pinMode (EcPin_DT,INPUT);//B

digitalWrite(EcPin_CLK, HIGH); // turn on pullup resistors
digitalWrite(EcPin_DT, 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)
}


ändern zu


void setup()
{
Serial.begin(9600);
pinMode (EcButtonPin_SW, INPUT);
pinMode (EcPin_CLK,INPUT_PULLUP);//A
pinMode (EcPin_DT,INPUT_PULLUP);//B

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

Natürlich am besten zuerst auf dem Nano probieren, wo es schon funktionierte.

Vielleicht auch mal ohne "PULLUP" versuchen?

MfG

Lord Integer
18.10.2020, 16:36
Hi, auch Dir vielen Dank für die Hilfe.

Leider auch mit deiner Hilfe ohne Erfolg. Auf dem Nano und Uno gehts super.

Laut den Angaben benutze ich die richtigen Pins. Auf folgender Ansicht sind die Interrups gelb markiert.
https://protosupplies.com/product/mega-2560-pro-with-ch340-usb/

Gruß

Searcher
18.10.2020, 17:50
Laut den Angaben benutze ich die richtigen Pins. Auf folgender Ansicht sind die Interrups gelb markiert.
https://protosupplies.com/product/mega-2560-pro-with-ch340-usb/


Da sehe ich jetzt keine Übersicht. Zum "Mega 2560 Pro Mini" habe ich folgende Pinzuordnungen gefunden:
https://robotdyn.com/pub/media/0G-00005642==MEGA-PROMINI-ATmega2560/DOCS/PINOUT==0G-00005642==MEGA-PROMINI-ATmega2560.pdf

Das sind auf Arduino Pin 2, 3 (D2, D3) die Interrupts 4, 5.

Gruß
Searcher

Moppi
18.10.2020, 17:58
Also wenn er mit digitalPinToInterrupt() die Pins an die ISR bindet, ist es da nicht egal welcher Interrupt es am Ende wäre? Hauptsache ist doch, dass ein Interrupt ausgelöst wird, der zur ISR führt.
Hauptsache die Pins 2 und 3 (müsste D2 und D3 sein), sind an der Platine richtig abgegriffen.

Gruß

Lord Integer
18.10.2020, 18:29
Da gebe ich dir recht Moppi. digitalPinToInterrupt() bindet die Pins an die ISR. Von daher sollte es funktionieren. Es geht ja beim Uno und Nano auch mit digitalPinToInterrupt() und den Board Pins 2 und 3.
Jedoch auf dem Mega 2560 Pro Mini nicht. Auch mit attachInterrupt(0, doEncoderA, CHANGE); und den von Searcher genannten Interrupts 4, 5 sollte es funktionieren.
Eventuell ist das Board defekt. Habe leider nur 1 Board davon. Deswegen muss ich es anscheinend reklamieren. Beim nächsten Board habe ich eventuell mehr Glück oder ich übersehe irgendetwas. Hm

Lord Integer
20.11.2020, 14:21
Hi,
ich wollte euch nur mitteilen, dass das Board defekt ist. Mit meinem neuen MEGA 2560 Pro Micro funktioniert alles ohne Probleme.