Forum: Mikrocontroller und Digitale Elektronik Signal für Drehsignalgeber erzeugen


von Philipp G. (geiserp01)


Lesenswert?

Ich habe mal den umgekehrten Fall.

Ein Gerät ist mit einem Rotary Encoder ausgerüstet. Da dieser 'nicht in 
das Design passt', musst der Encoder mit zwei, resp. drei Tastern 
ersetzt werden (Einer für links, einer für rechts, der dritte ist der 
Druckknopf)

Es handelt sich um einen klassischen, 5-poligen Encoder mit Druckkontakt 
(GND, A, B, GND Taster, Taster).

Ich suche Beispiel Codes für Arduino. Used Cases. Bisher habe ich nur 
das gefunden:
1
#include <avr/interrupt.h>    //Include the Interrupt Library
2
3
#define T2Speed 50            // Setting the Interrupt Speed?
4
5
const int LED = 13;            // Setting the pin number for LED as 13?
6
const int channelA = 2;      // Setting the pin number for channel A as 2 (Since I have an Arduino Mega I assume this would pin 2 PWM?)
7
const int channelB = 3;      // Setting the pin number for channel A as 3
8
9
volatile byte tmrCount = 0; //Timer2 overflow interrupt vector handler
10
ISR(TIMER2_OVF_vect) {
11
  TCNT2 = T2Speed;          //reset timer
12
  digitalWrite(LED,HIGH);
13
  switch (tmrCount) {
14
  case 0:
15
    digitalWrite(channelA,HIGH);
16
    break;
17
  case 1:
18
    digitalWrite(channelB,HIGH);
19
    break;
20
  case 2:
21
    digitalWrite(channelA,LOW);
22
    break;
23
  case 3:
24
    digitalWrite(channelB,LOW);
25
  }
26
  tmrCount++;
27
  if (tmrCount >= 4) {
28
    tmrCount = 0;
29
  }
30
  digitalWrite(LED,LOW);
31
  TIFR2 = 0x00;
32
};  
33
34
void setup() {
35
  Serial.begin(115200);
36
  pinMode(LED,OUTPUT);   // UNO LED, just for show
37
  pinMode(channelA,OUTPUT); 
38
  pinMode(channelB,OUTPUT);
39
40
  TCCR2A = 0;           //Timer2 Settings: WGM mode 0
41
  TCCR2B = _BV(CS22);   //Timer2 Settings: Timer Prescaler /64
42
  TIMSK2 = _BV(TOIE2);  //Timer2 Overflow Interrupt Enable 
43
  TCNT2 = T2Speed;      //reset timer
44
}
45
46
void loop() {
47
}

Kennt jemand schönere Ansätze?

Funktion: Mit einem kurzen Tastendruck soll langsam durch das Menu 
gescrollt werden können. Bleibt man länger drauf, erhöht sich die 
Frequenz. Das Timing muss dann natürlich mit der bestehenden Schaltung 
angepasst werden.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Philipp G. schrieb:
> Kennt jemand schönere Ansätze?

Wie wäre es mit einem Ansatz, der wenigstens die 2 Taster auswertet (den 
mittleren Drucktaster kann man ja direkt weiterleiten) ? Mit entprellen 
und damit das Incrementsignal updated ? Oder fehlt es dir völlig an 
Programmiererfahrung ?
1
char pos,tl1,tl2,tr1,tr2;
2
3
loop()
4
{
5
   tl1=digitalRead(TAST_LINKS);
6
   if(tl1&&!tl2)
7
   {
8
      pos=(pos+1)%4;
9
   }
10
   tl2=tl1;
11
   tr1=digitalRead(TAST_LINKS);
12
   if(tr1&&!tr2)
13
   {
14
      pos=(pos+3)%4;
15
   }
16
   tr2=tr1;
17
   digitalWrite(CHAN_A,pos&1);
18
   digitalWrite(CHAN_B,((pos+1)&2)!=0);
19
   _delay_ms(5);
20
}

von Falk B. (falk)


Lesenswert?

@ Philipp G. (geiserp01)

>Ich habe mal den umgekehrten Fall.

Kann man machen, man muss halt nur die Tabelle mit Gray-Code 
durchlaufen.

>Ich suche Beispiel Codes für Arduino. Used Cases. Bisher habe ich nur
>das gefunden:
>#include <avr/interrupt.h>    //Include the Interrupt Library

Naja, da ist noch viel zu tun, vor allem die Eingabe fehlt!

>Funktion: Mit einem kurzen Tastendruck soll langsam durch das Menu
>gescrollt werden können. Bleibt man länger drauf, erhöht sich die
>Frequenz. Das Timing muss dann natürlich mit der bestehenden Schaltung
>angepasst werden.

Du brauchst eine Tasteneingabe mit Entprellung und Erkennung eines 
langen Tastendrucks. Damit dir dann der Gray-Generator gesteuert. Klar 
geht das auch mit Switch(), aber eine einfache Tabelle ist hier deutlich 
einfacher und übersichtlicher.

Beitrag "Re: pulse direction signal zu encoder a b?"

Für die Entprellung bietet sich der uC Kalssiker von Peter D. an.

https://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

von Philipp G. (geiserp01)


Lesenswert?

Falk B. schrieb:
> Du brauchst eine Tasteneingabe mit Entprellung und Erkennung eines
> langen Tastendrucks. Damit dir dann der Gray-Generator gesteuert.

Danke, aber Unverständnis. Sinn und Zweck des Grey codes ist doch genau, 
dass keine Entprellung notwendig ist, oder?

von Falk B. (falk)


Lesenswert?

@ Philipp G. (geiserp01)

>> Du brauchst eine Tasteneingabe mit Entprellung und Erkennung eines
>> langen Tastendrucks. Damit dir dann der Gray-Generator gesteuert.

>Danke, aber Unverständnis.

Hmmm . . .

> Sinn und Zweck des Grey codes ist doch genau,
>dass keine Entprellung notwendig ist, oder?

Bei Drehgebereingängen!
Aber die Eingäng deines Emulators, hier der Arduino, sind normale 
Tasten!

P S Für so einen Emulator reicht ein kleiner ATtiny13, selbst den kann 
man spielend in C programmieren. Ist halt nicht als Arduino-Board 
verfügbar.

von HildeK (Gast)


Lesenswert?

Philipp G. schrieb:
> Danke, aber Unverständnis. Sinn und Zweck des Grey codes ist doch genau,
> dass keine Entprellung notwendig ist, oder?

Nicht ganz. Beim Grey-Code kann es natürlich auch zwischen Werten hin- 
und her schwanken, aber eben nur zwischen nebeneinander liegenden. Unter 
Umständen will man das auch nicht haben.

von Philipp G. (geiserp01)


Lesenswert?

MaWin schrieb:
> mittleren Drucktaster kann man ja direkt weiterleiten) ? Mit entprellen
> und damit das Incrementsignal updated ? Oder fehlt es dir völlig an
> Programmiererfahrung ?

Nein, gar nicht. Ich wollte nur wissen, ob es eine best practice für 
solche Fälle gibt, oder man sich sowas einfach selber zurechtstiefelt.

Ich schau' mir deine links gleich an.

Falk B. schrieb:
> Bei Drehgebereingängen!
> Aber die Eingäng deines Emulators, hier der Arduino, sind normale
> Tasten!

Ja, logisch, Notiz an mich selber, Gehirn einschalten.

Also entprellen, Länge des Drucks auswerten.

n = 800; //ms
If (Tasterpulse > n) then
   sendpulses;)
else
   sendsinglepulse

von georg (Gast)


Lesenswert?

HildeK schrieb:
> Beim Grey-Code kann es natürlich auch zwischen Werten hin-
> und her schwanken, aber eben nur zwischen nebeneinander liegenden

Einer Steuerung macht das nichts aus, wenn sie korrekt ausgelegt ist, 
aber eine Anzeige würde in der letzten Stelle hin und her springen, das 
sieht halt blöd aus. Dagegen hilft nicht unbedingt Entprellen, wenn der 
Encoder genau am Übergang steht, eher eine Hysterese.

Georg

von Falk B. (falk)


Lesenswert?

@Philipp G. (geiserp01)

>Nein, gar nicht. Ich wollte nur wissen, ob es eine best practice für
>solche Fälle gibt,

Nicht daß ich wüßte, zumal deine Anwendung SEHR exotisch ist. Einen 
Drehgeber durch 2 Tasten ersetzen macht man doch bestenfalls für 
Behinderte?!?

>Also entprellen, Länge des Drucks auswerten.

So in etwa.

>If (Tasterpulse > n) then
>   sendpulses;)
>else
>   sendsinglepulse

Naja, ich würde es anders machen. Man nehme eine statemachine, 
welche zyklisch im Zeitraster X aufgerufen wird, wobei X die 
Puslfrequenz der schnellen Puse bestimmt. Diese FSM bekommt von der 
Entprellroutine 2 Eingangssignale. Und zwar Taste wurde gedrückt (Flanke 
inaktiv/aktiv) und Taste ist schon lange gedrückt. Bei beiden Signalen 
geht die FSM je einen Schritt in die jeweilige Richtung. Das 
Flankensignal löscht sich selber in der Entprellroutine, die FSM kann so 
oder so nur einen Schritt machen. Das Signal Taste schon länger gedrückt 
bleibt aber stehen, bis man losläßt.

Praktisch kann man das alles locker in eine Timer-ISR packen, wobei die 
Entprellung bei djedem Aufruf arbeitet (um die 1kHz), die Signalausgabe
aber nur jede X-te ISR, vielleicht Faktor 100 langsamer (macht immer 
noch 10 Schritte/s).

von Philipp G. (geiserp01)


Lesenswert?

Falk B. schrieb:
> Nicht daß ich wüßte, zumal deine Anwendung SEHR exotisch ist. Einen
> Drehgeber durch 2 Tasten ersetzen macht man doch bestenfalls für
> Behinderte?!?

Wüsste ich nicht dass du es bist hätte ich das glatt als Beleidigung 
aufgefasst :)

Scherz beiseite. Es handelt sich um eine Konsole mit drei eingebauten 
Displays dreier unterschiedlicher Geräte, allesamt mittig und 
untereinander angeordnet. Um die Displays herum befinden sich Taster, 
links und rechts symmetrisch angeordnet.

Ein Gerät wird nun ersetzt durch ein anderes, welches von Haus aus mit 
einem Drehgeber bedient wird. Das stört das Auge; die Symmetrie der 
Konsole ginge verloren, man könnte höchstens rechts und links zwei 
Drehgeber einbauen, und dies so beschalten dass beide dieselbe Funktion 
ausführen, was wohl noch beh... wäre.

Der 'Kunde' will die Bedienung mit den Tastern erhalten.

Falk B. schrieb:
> Naja, ich würde es anders machen. Man nehme eine statemachine,
> welche zyklisch im Zeitraster X aufgerufen wird, wobei X die
> Puslfrequenz der

ok, schaue mir an, danke.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Ich hab mal ein wenig zusammenkopiert. Siehe Anhang.

von Peter (Gast)


Lesenswert?

Du brauchst also einen Drehgeberemulator?

Also einen Zähler den man mit den Tasten auf und ab steuern kann und der 
vorwärts von wückwarts unterscheiden kann und sich die Drehgeberposition 
merkt, also 4 Zustände hat. Beim linksdrehen wird vorwärts geschoben, 
beim REchtsdrehen rückwärts.

Ergibt das Muster

0110
1100

0011
0110

1001
0011

1100
1001

von Philipp G. (geiserp01)


Lesenswert?

Falk B. schrieb:
> Ich hab mal ein wenig zusammenkopiert. Siehe Anhang.

bist ein Schatz, danke dir

von Philipp G. (geiserp)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Mittlerweile habe ich das Gerät zum Umbau zu Hause. Noch mal von vorne, 
damit man sich nicht den gesamten Thread durchlesen muss:

Ausgangslage

Der Rotary Encoder soll durch zwei (drei) Taster ersetzt werden. Für 
mich von Relevanz sind nur die zwei Taster welche den 2bit greycode 
erzeugen.

@Falk Brunner war so nett und hat obigen Code erstellt, den probiere ich 
abends mal aus, nochmals danke an dieser Stelle!

Beim Drehsignalgeber handelt es sich um diesen hier:

https://www.alps.com/prod/info/E/HTML/Encoder/Incremental/EC12E/EC12D1524403.html

Von Relevanz:
Number of pulse  15
Ratings  1mA 5V DC
Output signal  Two phase A and B
Max./min. operating current(Resistive load)  10mA/1mA

[Bild pcb01_front_enc01.jpg]
-> Der Encoder der ersetzt werden soll

[Bild pcb01_back_enc02.jpg]
- Die 5 Pins des Encoders, man sieht auch schön die beiden R gegen Masse 
und Versorgungsspannung

[Bild pcb02_back_enc.jpg]

- Die Rückseite des zweiten Boards

[Bild pcb02_front_enc.jpg]

- Die Front des zweiten Board mit dem Spannungsregulator.

Fragen

Der 2bit Greycode soll von einem Arduino Nano erzeugt werden, weil ich 
von diesen 20 Stück zu Hause liegen habe. Versorgungsspannung vom Nano 
bei 5V.

[Bild pcb02_front_enc.jpg]

zeigt den Eingang mit 5VDC, danach der Spannungsregler zwischen den 
beiden Cs auf 3.3V. Das bedeutet die ganze Platine werkelt mit 3.3V.

Soll/darf/kann ich mit einem 340R Widerstand zwischen Arduino Nano Out 
direkt auf die Encoder Pins A und B gehen? ((5 - 3.3) \ 0.005 = 340)? 
Ich würde dann die Versorgung von Nano direkt vom Board nehmen (+5V).

Weitere Alternativen:
Spannungsteiler am Ausgang auf 3.3V
Logic Level Shifter

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Den Nano kann man auch mit 3,3V laufen lassen. Aber dann muss man den 
Takt runter drehen, 16 MHz sind dann nicht mehr erlaubt. Aber 
Längswiderstände sind wahrscheinlich einfacher 1K ist OK. Genaugenommen 
kann man auch die Ausgänge vom Arduino als Open Drain Treiber nutzen, 
dann ist die Drehgeberemulation perfekt, denn die Pull-Ups auf 3,3V sind 
schon auf der Platine.

Das erreicht man, indem man auf DDRB anstatt PORTB den invertierten 
Gray-Code ausgibt.

    // update outputs

    DDRB = ( DDRB & ~0x03 ) | (~gray & 0x03);

D.h. die IOs werden zwischen Ausgang mit Wert 0 (PORTB) oder Eingang 
umgeschaltet.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

>pcb01_back_enc02.jpg

Wenn der LM358 da schon auf 3,3 oder 5V läuft, kann man auch huckepack 
einen Tiny13/25/45/85 in SO-8 auflöten, wenn man ihn vorher programmiert 
hat. Spart das ganze Nano Dings ein und liegt auch schon nahe am 
Drehgeber.

: Bearbeitet durch User
von Philipp G. (geiserp)


Angehängte Dateien:

Lesenswert?

Ich versuche das mal mit opendrain @Falk, wäre sowieso die beste Lösung. 
Der Encoder macht ja auch nix anderes.

Ich habe gestern Messungen gemacht (Bild). Ich hoffe der Versatz passt 
einigermassen. Die Messungen habe ich direkt am PCB gemacht (Kanal 1 = 
A, Kanal 2 = B, GND vom PCB.

Vorgehen: 'Von Hand' möglichst schnell und gleichmässig drehen.

Ich muss gestehen das ist die erste Berührung mit Encodern in meinem 
Leben, habe null praktische Erfahrung damit.

: Bearbeitet durch User
von Philipp G. (geiserp01)


Lesenswert?

Der code funktioniert leider nicht wie erwartet.



PB0, Pin 8 Nano
PB1, Pin 9 Nano

Nach den booten sind beide auf low, dann geht einer der beiden auf high 
- unabhängig was ich an den Tastereingängen PB3/4 mache.

von Falk B. (falk)


Lesenswert?

@ Philipp G. (geiserp01)

>Der code funktioniert leider nicht wie erwartet.

Der Code ist auch für einen nackten Attiny13 geschrieben, nicht Arduino 
Nano. Schau dir an, wo die entpsprechenden Pins liegen.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Also ich hab das Programm jetzt mal real auf dem ATtiny13 getestet, es 
läuft wie es soll. Der einzige Fehler war, daß ich die ISR mit 1kHz 
anstatt 100Hz hab laufen lassen, da sind die Signale im Automatikmodus 
halt um Faktor 10 zu schnell ;-)

Siehe Anhang, jetzt mit 100Hz ISR und Screenshot.

Die Taster sind normale Schließer, welche gegen GNG schalten. Man 
braucht keine externen Pull-Up Widerstände, die internen im AVR reichen 
hier.

von Philipp G. (geiserp01)


Lesenswert?

Danke Falk. Hätte früher berichten sollen, es funktioniert alles. Dass 
das Timing nicht stimmt, habe ich schnell gemerkt.

Ich habe mir hinter '2bit greycode' viel zu viel vorgestellt, eigentlich 
ist das simple - zumindest mit 2 bit.

Interessant wäre das jetzt rein analog zu lösen, evtl. mit zwei NE555 
oder dem 556.

Gruss, Philipp

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.