Pages: 1 [2]   Go Down
Author Topic: Verhalten Rotary Encoder  (Read 2929 times)
0 Members and 1 Guest are viewing this topic.
Forum Moderator
BZ (I)
Online Online
Brattain Member
*****
Karma: 271
Posts: 21881
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Einziges Manko: Wenn ich nur ein Raster weiterdrehe, löse ich jedesmal 2 bis 4 mal aus, also +1 +1 +1 +1
Der Encoder prellt; Du mußt ihn entprellen.
Grüße Uwe
Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
jetzt habe ich echt 2 STunden gelesen und gegoogelt, aber so ganz schlüssig isses mir noch nicht wie ich
a) den Button
b) den encoder
entprelle.

Wenn, dann möchte ich das auf jeden Fall Softwareseitig machen. Denke für meine Zwecke reicht das völligst aus.
Wenn mal jemand ein richtig gutes Tutorial kennt (auch für Einsteiger) würde mir das sehr helfen

Gruß
Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So,
der code von erni bernie/Nick Gammon funktioniert jetzt auch:
Code:
// Rotary encoder example.
// Author: Nick Gammon
// Date:   25th May 2011

// Thanks for jraskell for helpful suggestions.

// Wiring: Connect common pin of encoder to ground.
// Connect pin A (one of the outer ones) to a pin that can generate interrupts (eg. D2)
// Connect pin B (the other outer one) to another free pin (eg. D5)

volatile boolean fired;
volatile boolean up;
volatile boolean turned;

#define PINA 2
#define PINB 4
#define INTERRUPT 0  // that is, pin 2
#define PUSHP 3
#define INTERRUPTB 1  // that is, pin 3

void isrp ()
{
  if (!digitalRead (PUSHP))
    fired = true;
}  // end of isr
// Interrupt Service Routine for a change to encoder pin A
void isr ()
{
  if (digitalRead (PINA))
    up = digitalRead (PINB);
  else
    up = !digitalRead (PINB);
  turned = true;
}  // end of isr


void setup ()
{
  digitalWrite (PINA, HIGH);     // enable pull-ups
  digitalWrite (PINB, HIGH);
    digitalWrite (PUSHP, HIGH);
  attachInterrupt (INTERRUPT, isr, CHANGE);   // interrupt 0 is pin 2, interrupt 1 is pin 3
 attachInterrupt (INTERRUPTB, isrp, FALLING);  
  Serial.begin (115200);
}  // end of setup

void loop ()
{
static long rotaryCount = 0;

  if (turned)
    {
    if (up)
      rotaryCount++;
    else
      rotaryCount--;
    turned = false;
        
    Serial.print ("Count = ");  
    Serial.println (rotaryCount);
    }  // end if fired
else if (fired)
    {
    Serial.println ("Buttonpress");
    fired = false;
    }
}  // end of loop

Wenn ich das richtig verstehe, ist der schon softwareseitig entprellt??? Ging erst nicht.
Habe dann mal einen 0.1u Cap an den Button und zwischen A-C und B-C gelötet:
Der BUtton geht seit dem 100%ig
Der Encoder selbst leider nicht, wobei die Caps Verbesserung gebracht haben:
Ohne Caps war das Verhalten folgend:
es wurden IMMER 2 Clicks auslöst, zwischendrin dann auch mal 3.
Mit den Caps habe ich durchgängig 2 Clicks. (Click= 1 tacken weiter drehen, aber 2* den interrupt auslösen)

Tipps wären super - vielen DAnk



« Last Edit: January 13, 2012, 06:33:23 pm by currymuetze » Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So- denke ich habs gelöst:
aus
attachInterrupt (INTERRUPT, isr, CHANGE);
wird
attachInterrupt (INTERRUPT, isr, RISING);

und jetzt siehts gut aus.

Gibts noch Meinungen?Tipps?
Logged

Cologne
Offline Offline
God Member
*****
Karma: 11
Posts: 513
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo currymuetze,

mit dem Entprellen der Kontakte hab ich auch noch keine vernünftige Lösung gefunden.
Der Pushbutton ist mit 100nF wie bei dir hardwareseitig entprellt. Das funktioniert auch ganz gut.
Beim Encoder funktioniert das aber nicht.
Ich habe keine oder nur wenig Probleme, wenn ich den Encoder langsam drehe. Erst bei schnellen Drehungen verschluckt er sich.
Ich habe bei mir mal die Änderung RISING statt CHANGE in der Interruptsteuerung ausprobiert. Dann erkennt er aber erwartungsgemäß in eine Richtung nur jeden zweiten Schritt. Wahrscheinlich prellt dein Encoder mehr wie meiner und du hast durch das Prellen immer eine RISING Flanke.

Reinhard
Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
mal eine Frage noch:
ich habe den Encoder mal mit den PINs 1, 2, 3 verbunden. Das geht leider nicht, anders als mit 2,3,4.
Also Pin4 sollte an PIN1.
Ich vermute das liegt am TX (=Pin1). Der ist ja für die serielle Übertragung per USB zuständig.
Frag mich jetzt:
Beim Testen über serial klappt nix - wie wird das sein, wenn ich serial nicht mehr nutze, also während des programmablaufs kein USB benötige?

Gruß
Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo currymuetze,

mit dem Entprellen der Kontakte hab ich auch noch keine vernünftige Lösung gefunden.
Der Pushbutton ist mit 100nF wie bei dir hardwareseitig entprellt. Das funktioniert auch ganz gut.
Beim Encoder funktioniert das aber nicht.
Ich habe keine oder nur wenig Probleme, wenn ich den Encoder langsam drehe. Erst bei schnellen Drehungen verschluckt er sich.
Ich habe bei mir mal die Änderung RISING statt CHANGE in der Interruptsteuerung ausprobiert. Dann erkennt er aber erwartungsgemäß in eine Richtung nur jeden zweiten Schritt. Wahrscheinlich prellt dein Encoder mehr wie meiner und du hast durch das Prellen immer eine RISING Flanke.

Reinhard

Also was ich grad gemerkt habe:
Am interrupt 0 (PIN 2) funktioniert die entprellung des Encoders beim drehen wunderbar.
Am interrupt 5 (PIN 18) habe ich bei gleichem Code wieder ne Prellung drin. Irgendwie doch alles merkwürdig...
Code:
volatile boolean fired1;
volatile boolean up1;
volatile boolean turned1;
volatile boolean fired2;
volatile boolean up2;
volatile boolean turned2;

#define PINA 4
#define PINB 2
#define PUSH1 3
#define INTERRUPT1 0  // that is, pin 2
#define INTERRUPT2 1  // that is, pin 3
#define PINC 17
#define PIND 18
#define PUSH2 19
#define INTERRUPT3 5  // that is, pin 2
#define INTERRUPT4 4  // that is, pin 3

void isrp1 ()
{
  if (!digitalRead (PUSH1))
    fired1 = true;


void isr1 ()
{
  if (digitalRead (PINA))
    up1 = digitalRead (PINB);
  else
    up1 = !digitalRead (PINB);
  turned1 = true;


void isrp2 ()
{
  if (!digitalRead (PUSH2))
    fired2 = true;
}

void isr2 ()
{
  if (digitalRead (PINC))
    up2 = digitalRead (PIND);
  else
    up2 = !digitalRead (PIND);
  turned2 = true;
}   

void setup ()
{
  digitalWrite (PINA, HIGH); 
  digitalWrite (PINB, HIGH);
  digitalWrite (PUSH1, HIGH);
  attachInterrupt (INTERRUPT1, isr1, RISING);   
  attachInterrupt (INTERRUPT2, isrp1, FALLING); 
  digitalWrite (PINC, HIGH); 
  digitalWrite (PIND, HIGH);
  digitalWrite (PUSH2, HIGH);
  attachInterrupt (INTERRUPT3, isr2, RISING);   
  attachInterrupt (INTERRUPT4, isrp2, FALLING); 
 
  Serial.begin (115200);


void loop ()
{
  static long rotaryCount = 0;
  static long rotaryCount2 = 0;
  if (turned1) {
    if (up1) {
      if (rotaryCount>=55 && rotaryCount<4040) rotaryCount=rotaryCount+50;
      if ((rotaryCount>=4040 && rotaryCount<=4089) || rotaryCount<55) rotaryCount=rotaryCount+5;
      if (rotaryCount>4089 && rotaryCount<=4094) rotaryCount++;
    }
    else {
      if (rotaryCount>=55 && rotaryCount<4040) rotaryCount=rotaryCount-50;
      if ((rotaryCount>5 && rotaryCount<55) || rotaryCount>=4040) rotaryCount=rotaryCount-5;
      if (rotaryCount<=5 && rotaryCount>=1) rotaryCount=rotaryCount--;
    }
    turned1 = false;
    Serial.print ("Count1 = "); 
    Serial.println (rotaryCount);
  }
  if (fired1) {
    Serial.println ("Buttonpress1");
    fired1 = false;
  }
  if (turned2) {
    if (up2) {
      if (rotaryCount2>=55 && rotaryCount2<4040) rotaryCount2=rotaryCount2+50;
      if ((rotaryCount2>=4040 && rotaryCount2<=4089) || rotaryCount2<55) rotaryCount2=rotaryCount2+5;
      if (rotaryCount2>4089 && rotaryCount2<=4094) rotaryCount2++;
    }
    else {
      if (rotaryCount2>=55 && rotaryCount2<4040) rotaryCount2=rotaryCount2-50;
      if ((rotaryCount2>5 && rotaryCount2<55) || rotaryCount2>=4040) rotaryCount2=rotaryCount2-5;
      if (rotaryCount2<=5 && rotaryCount2>=1) rotaryCount2=rotaryCount2--;
    }
    turned2 = false;
    Serial.print ("Count2 = "); 
    Serial.println (rotaryCount2);
  }
  if (fired2) {
    Serial.println ("Buttonpress2");
    fired2 = false;
  }
 
 
}
Logged

Offline Offline
God Member
*****
Karma: 6
Posts: 717
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

möchte den Thread noch mal aufmachen, da ich den von mir genutzten Encoder irgendwie als zu unzuverlässig empfinde und er anscheinend eh falsch ist (2 bit bei 20 pulses):
Kann mir jemand einen Encoder empfehlen, bzw. die relevanten Daten, auf die ich achten muss, mit dem ich folgendes umsetzen kann:
- Per Button schalte ich den Modus um
- Rechts und links drehen ändert jeweils die Helligkeit meiner LEDs
- Der Encoder wird an 2 Interrupts angeschlossen: Einmal der Button selbst sowie das Auslesen einer Drehrichtung
- Der Encoder sollte ein 12mm Schaft mit Gewinde haben

Bestenfalls bei Reichelt
VG
Thorsten

Logged

Pages: 1 [2]   Go Up
Jump to: