Forum: Mikrocontroller und Digitale Elektronik Encoder nach Peter


von Henry (Gast)


Lesenswert?

Hallo
In verschiedenen Projekten verwende ich Encoder (Drehgeber) mit RGB 
LEDs. Damit kann ich dann mit dem drehen verschiedene Farben anzeigen 
lassen.
Möchte jetz mal was ganz einfaches machen und das klappt nicht, miss...
Verwende den Code von Peter:
1
#define F_CPU 16000000UL        // Angabe der Frequenz, wichtig für die Zeit
2
#include "avr/io.h"            // Einbindung Datei Ausgänge
3
#include "avr/interrupt.h"        // Einbindung der interrupt.h
4
5
#define PHASE_A     (PINB & 1<<PB2)    // Eingang Encoder A  P172
6
#define PHASE_B     (PINA & 1<<PA0)    // Eingang Encoder B  P172  
7
8
#define LEDS_DDR    DDRA        // Ausgang LED
9
#define LEDS        PORTA        // 
10
11
volatile int8_t enc_delta;        // -128 ... 127
12
static int8_t last;
13
  
14
  void encode_init( void )
15
    {
16
    int8_t new;
17
    new = 0;
18
    if( PHASE_A ) new = 3;
19
    if( PHASE_B ) new ^= 1;      // Convertiert Gray Code in Binär Code
20
    last = new;            // power on state
21
    enc_delta = 0;
22
    }
23
  
24
  void timer_init()            // Timer2 1ms 16MHz
25
    {
26
    TCCR2A = (1<<WGM01);
27
    TCCR2B = (1<<CS01)|(1<<CS00);
28
    OCR2A = 249;
29
    TIMSK2 |=(1<<OCIE2A);
30
    }
31
32
  ISR( TIMER2_COMPA_vect )        // 1ms for manual movement
33
    {
34
    int8_t new, diff;
35
    new = 0;
36
    if( PHASE_A ) new = 3;
37
    if( PHASE_B ) new ^= 1;      // Konvertiert Gray Code in Binär Code
38
    diff = last - new;        // difference last - new
39
    if( diff & 1 ) 
40
      {                // bit 0 = value (1)
41
      last = new;          // store new as next last
42
      enc_delta += (diff & 2) - 1;  // bit 1 = direction (+/-)
43
      }
44
    }
45
46
  int8_t encode_read1( void )      // lesen einzel Schritt Encoder = schnell
47
    {
48
    int8_t val;
49
    cli();
50
    val = enc_delta;
51
    enc_delta = 0;
52
    sei();
53
    return val;            // counts since last call
54
    }
55
56
  int8_t encode_read2( void )      // lesen zwei Schritt Encoder = mittel
57
    {
58
    int8_t val;
59
    cli();
60
    val = enc_delta;
61
    enc_delta = val & 1;
62
    sei();
63
    return val >> 1;
64
    }
65
66
  int8_t encode_read4( void )      // lesen vier Schritt Encoder = langsam
67
    {
68
    int8_t val;
69
    cli();
70
    val = enc_delta;
71
    enc_delta = val & 3;
72
    sei();
73
    return val >> 2;
74
    }
75
76
  int main( void )            // Hauptschleife
77
    {
78
    int32_t val = 0;
79
    timer_init();
80
    DDRA |= 0b00100000;        // LED 5 auf Ausgang
81
    PORTA = 0b00100000;        // LED auf aus 
82
    encode_init();
83
  
84
    sei();
85
    for(;;)
86
      {
87
      val += encode_read2();    // lesen 1,2 oder 4 Schritt Encoder
88
      LEDS = val;
89
      }
90
    }
Die LED schaltet beim betätigen des Encoder leider etwas eigenartig. 
Muss ca. ein komplette Drehung machen wenn es schalten soll, noch eine 
Umdrehung geht sie wieder aus. Wollte igentlich das sie, egal ob links 
oder rechts drehe, kurz leuchtet und wieder aus geht. Es soll mir 
anzeigen ob ich drehe.
Jemand eine Idee dazu?

: Verschoben durch Moderator
von W.S. (Gast)


Lesenswert?

Henry schrieb:
> Jemand eine Idee dazu?

Ja. Und das ist immer wieder die gleiche: nicht einfach nur copy&paste, 
sondern verstehen.

Oder glaubst du, daß ein Forum ist wie ein Cola-Automat? Oben ne Frage 
reinstecken und unten kommt die fertige Lösung heraus?

W.S.

von Teo D. (teoderix)


Lesenswert?

Du zählst den PortA rauf und runter.... Wie ist den DIE LED 
angeschlossen o. sinds mehrer oder oder......? Zeig mal was Du das hat!

von mIstA (Gast)


Lesenswert?

Henry schrieb:
> Wollte igentlich das sie, egal ob links
> oder rechts drehe, kurz leuchtet und wieder aus geht.

Und welcher Teil Deines Programms sollte das - Deiner Meinung nach - wie 
bewerkstelligen?

von Hugo H. (hugo_hu)


Lesenswert?

Hallo Henry aka Helmut aka Achim,

Deine Erfahrungen

Henry schrieb:
> In verschiedenen Projekten verwende ich Encoder (Drehgeber) mit RGB
> LEDs. Damit kann ich dann mit dem drehen verschiedene Farben anzeigen
> lassen.

kann man "Deinem" Programm nicht entnehmen.

Du hättest den Programm-Kopf auch stehen lassen können, da das Entfernen 
dieses Teils wohl Deine einzige Eigenleistung war:
1
/************************************************************************/
2
/*                                                                      */
3
/*                      Reading rotary encoder                     */
4
/*                      one, two and four step encoders supported  */
5
/*                                                                      */
6
/*              Author: Peter Dannegger                                 */
7
/*                                                                      */
8
/************************************************************************/

Beitrag "Drehgeber/Encoder 1-, 2- oder 4-schrittig"

: Bearbeitet durch User
von Al. K. (alterknacker)


Lesenswert?

Dann ist es doch alles o.k.
Betreff:   "Encoder nach Peter"

von Egonwalter M. (heiner1234)


Lesenswert?

Hugo H. schrieb:
> Hallo Henry aka Helmut aka Achim,
>
> Deine Erfahrungen
>
> Henry schrieb:
>> In verschiedenen Projekten verwende ich Encoder (Drehgeber) mit RGB
>> LEDs. Damit kann ich dann mit dem drehen verschiedene Farben anzeigen
>> lassen.
>
> kann man "Deinem" Programm nicht entnehmen.

Nun, es ist doch bekannt, dass Henry aka Helmut aka Achim immer wieder 
per  copy & paste Programmteile zusammenkopiert, diese Schnipsel aber 
nicht versteht und dann hier um Hilfe bittet. Ok soweit, es wird immer 
irgendwie irgendjemand helfen.
Wenn er aber dann mithilfe Anderer das Programm zu Laufen gebracht und 
dann ein "Tut" erstellt und dieses ins Netz stellt OHNE Angabe von 
Originalquellen - das ist frech.

von Henry (Gast)


Lesenswert?

Kann mich nicht erinnern das Peter die Nutzung seiner Programme 
untersagt hat. Im Gegenteil. Ein Encoder mit RGB ist in dieser Frage 
zwar erwähnt aber nicht nach gefragt, habe es nur erwähnt das es geht.
Die LED ist am Pin PA5 angeschlossen.
Hoffe das ihr nicht von mir erwartet, das ich ein Programm schreibe was 
besser ist als das von Peter.
Wer das denkt leidet wohl unter Grössenwahn.

von Henry (Gast)


Lesenswert?

Steht sogar im Titel von wem es ist

von Stefan F. (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Wenn er aber dann mithilfe Anderer das Programm zu Laufen gebracht und
> dann ein "Tut" erstellt und dieses ins Netz stellt OHNE Angabe von
> Originalquellen - das ist frech.

Henry schrieb:
> Kann mich nicht erinnern das Peter die Nutzung seiner Programme
> untersagt hat.

Derartige Kritik habe ich schon ein paar mal zu Recht einstecken müssen. 
Was verboten ist, und was sich nicht gehört, sind zweierlei.

Solange du dich noch so schwer tust, fremde Codes zu benutzen, 
beschränke dich auf die C Bibliothek und schreibe alles selber, was du 
kannst. Aber bilde dir nicht zu früh ein, dass deine mühsam erarbeiteten 
Codes für Tutorials gut genug sind. Das ist ein häufiger Anfängerfehler, 
den auch ich einige male gemacht habe.

Wenn du etwas funktionierendes zusammen geklöppelt hast, kannst du es 
hier immer noch zu Kontrolle Posten. Ziehe dir dazu ein dickes Fell an, 
schlafe vor jeder Antwort eine Nacht, und verzichte in deinem Tutorial 
nicht auf Quellangaben. Dann wird das schon.

Wir sind alte Meckersäcke, aber das heißt nicht, dass wir nicht gerne 
helfen.

von Heiner (Gast)


Lesenswert?

Henry schrieb:
> Kann mich nicht erinnern das Peter die Nutzung seiner Programme
> untersagt hat.

Hat auch niemand angezweifelt, Henry

> Im Gegenteil. Ein Encoder mit RGB ist in dieser Frage
> zwar erwähnt aber nicht nach gefragt, habe es nur erwähnt das es geht.

Was ist dann Dein Problem?

> Die LED ist am Pin PA5 angeschlossen.
> Hoffe das ihr nicht von mir erwartet, das ich ein Programm schreibe was
> besser ist als das von Peter.

Auf keinen Fall nach Deinen bisherigen Leistungen 😉
> Wer das denkt leidet wohl unter Grössenwahn.

Keiner denkt das!

von Uwe K. (ukhl)


Lesenswert?

Henry schrieb:
> Die LED ist am Pin PA5 angeschlossen.

Versuche doch mal PA2...

von Stefan F. (Gast)


Lesenswert?

Val ist eine 32 Bit Variable, die gibst du auf einem 8 Bit Port aus, von 
dem du wiederum nur ein Bit mitten drin verwendest. Kommt dir das nicht 
seltsam vor?

Da es das Bit 5 ist, ändert es nur alle 32 Impulse seinen Zustand.

von Hugo H. (hugo_hu)


Lesenswert?

Henry schrieb:
> Möchte jetz mal was ganz einfaches machen und das klappt nicht, miss...
> Verwende den Code von Peter:

Schau doch mal im Tutorial nach:

https://playground.boxtec.ch/lib/exe/fetch.php/tutorials/encoder.pdf

von Heiner (Gast)


Lesenswert?

😂👍

von Henry (Gast)


Lesenswert?

Uwe K. schrieb:
> Versuche doch mal PA2...

Wieso PA2?

Hugo H. schrieb:
> Schau doch mal im Tutorial nach:

Das mit RGB im Encoder klappt hier.

Stefan ⛄ F. schrieb:
> Val ist eine 32 Bit Variable, die gibst du auf einem 8 Bit Port aus, von
> dem du wiederum nur ein Bit mitten drin verwendest. Kommt dir das nicht
> seltsam vor?
>
> Da es das Bit 5 ist, ändert es nur alle 32 Impulse seinen Zustand.

Das hatte ich auch bereits geändert und verwende jetzt val

Stefan ⛄ F. schrieb:
> Wenn du etwas funktionierendes zusammen geklöppelt hast, kannst du es
> hier immer noch zu Kontrolle Posten.

Das klingt gut und würde ich sehr gern machen. Doch leider geht es 
einigen hier darum anderen zu zeigen das sie Nieten und schlimmer sind.

Leider haben einige Menschen in den Sozialen Netzwerken mehr damit zu 
tun andere zu beleidigen und mit dem Tot zu bedrohen. Die Auswirkungen 
hat man ja bereits gesehen.

Stefan ⛄ F. schrieb:
> Wir sind alte Meckersäcke, aber das heißt nicht, dass wir nicht gerne
> helfen.

Leider habe ich den Eindruck das das meckern vorgeht. Einige meckern 
lieber als zu helfen

von Hugo H. (hugo_hu)


Lesenswert?

Henry schrieb:
> Das mit RGB im Encoder klappt hier.

Da vermutlich auch - ganz nah ...

https://www.mikrocontroller.net/articles/Modulares_Board#Encoder_/_Drehgeber

Henry schrieb:
> Doch leider geht es
> einigen hier darum anderen zu zeigen das sie Nieten und schlimmer sind.

Nein - nur auf Deine Masche hinweisen, Dir alles von Anderen "vorbeten 
zu lassen" um es danach in ein "Tuturial von HJS" zu packen. Wenn ich 
mich richtig erinnere machst Du das seit ca. 10 Jahren so.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Henry schrieb:
> Muss ca. ein komplette Drehung machen
Um deine eigene Längsachse? So eine Art Pirouette?
Warum schreibst du nicht einfach, WAS du da drehst und WIE du das an den 
µC angeschlossen hast.

> Möchte jetz mal was ganz einfaches machen und das klappt nicht
Hilft alles nix. Dann musst du noch was einfacheres machen und Schritt 
für Schritt vorwärts gehen.

> Die LED schaltet beim betätigen des Encoder leider etwas eigenartig.
Du selber hast das doch programmiert. Was hast du dir dabei gedacht, als 
du die Zeilen hingeschrieben hast? Welche Reaktion der LED hast du bei 
diesem, deinem Programm erwartet?

> Es soll mir anzeigen ob ich drehe. Jemand eine Idee dazu?
Ja, du brauchst dafür ein anderes Programm (und lustigerweise brauchst 
du für die Lösung dieser Aufgabe nicht mal eine Encoderauswertung). Du 
musst nur erkennen, ob sich an den Pins was ändert und dann jeweils 
einen Timer hochsetzen. Dieser Timer wird ständig herunter gezählt, und 
so lange er ungleich 0 ist, wird die LED angeschaltet.

Ich würde das etwa so machen:
1
volatile int8_t enc_delta;        // -128 ... 127
2
static int8_t last;
3
volatile int8_t timeout_led = 0;
4
:
5
:
6
  ISR( TIMER2_COMPA_vect )        // 1ms for manual movement
7
  {
8
    int8_t new, diff;
9
    new = 0;
10
    if( PHASE_A ) new = 3;
11
    if( PHASE_B ) new ^= 1;          // Konvertiert Gray Code in Binär Code
12
    diff = last - new;               // difference last - new
13
    if( diff & 1 ) 
14
    {                                // bit 0 = value (1)
15
        last = new;                   // store new as next last
16
        enc_delta += (diff & 2) - 1;  // bit 1 = direction (+/-)
17
18
        timeout_led=255;              // Zeitzähler hochsetzen
19
    }
20
    if (timeout_led>0) timeout_led--; // Zeit runterzählen
21
  }
22
:
23
:
24
    for(;;)
25
    {
26
      // Zeit abfragen und LED ansteuern
27
      if (timeout_led>0) LEDS |=   (1<<5); // ein
28
      else               LEDS &=  ~(1<<5); // aus
29
30
      val += encode_read2();    // lesen 1,2 oder 4 Schritt Encoder
31
    }
32
:
Ergebnis: die LED leuchtet so lange du drehst und noch etwa eine viertel 
Sekunde länger.

BTW: tolles Ding, das Eiweißgewölle da zwischen den Ohren. Die Benutzung 
ist ausdrücklich nicht verboten.

EDIT:
Henry schrieb:
> Einige meckern lieber als zu helfen
Da hat nach meiner Erfahrung der TO schon auch ein gewichtig Wort 
mitzureden. Wenn der sich helfen lässt und MITDENKT, dann flutscht das 
viel besser.

Henry schrieb:
> Das hatte ich auch bereits geändert und verwende jetzt val
Und wie sollte sich die LED durch diese "Änderung" verhalten? Bringt es 
irgendwas, die Aufgabe mit "val" anzugehen? Warum meinst du, dass das 
der richtige Weg ist?

: Bearbeitet durch Moderator
von Henry (Gast)


Lesenswert?

Lothar M. schrieb:
> Um deine eigene Längsachse? So eine Art Pirouette?
> Warum schreibst du nicht einfach, WAS du da drehst und WIE du das an den
> µC angeschlossen hast.

Meine den Encoder damit. Der Anschluss steht im Programm mit drin. B=PA0 
und A=PB2.

Lothar M. schrieb:
> Und wie sollte sich die LED durch diese "Änderung" verhalten? Bringt es
> irgendwas, die Aufgabe mit "val" anzugehen? Warum meinst du, dass das
> der richtige Weg ist?

Die Auswertung von val bringt eine Reaktion der LED, ein kurzes 
aufleuchten bei der Drehung des Encoders. Es ist mir klar das es nicht 
die beste Lösung ist, hatte aber erst mal die Funktin.
Auf deine Lösung bin ich nicht gekommen. Danke. Werde sie jetzt 
auseinander nehmen und mir genau ansehen

von Stefan F. (Gast)


Lesenswert?

Henry schrieb:
> Leider habe ich den Eindruck das das meckern vorgeht. Einige meckern
> lieber als zu helfen

Nein, meckern fällt ihnen (mir) nur sehr viel leichter als höflich zu 
sein.

von Henry (Gast)


Lesenswert?

Lothar M. schrieb:
> ISR( TIMER2_COMPA_vect )        // 1ms for manual movement
>   {
>     int8_t new, diff;
>     new = 0;
>     if( PHASE_A ) new = 3;
>     if( PHASE_B ) new ^= 1;          // Konvertiert Gray Code in Binär
> Code
>     diff = last - new;               // difference last - new
>     if( diff & 1 )
>     {                                // bit 0 = value (1)
>         last = new;                   // store new as next last
>         enc_delta += (diff & 2) - 1;  // bit 1 = direction (+/-)
>         timeout_led=255;              // Zeitzähler hochsetzen
>     }
>     if (timeout_led>0) timeout_led--; // Zeit runterzählen
>   }

In diesem Teil funktioniert was nicht.
Die Auswertung des Encoders erfolgt mit Phase A und Phase B. Es kann 
sich nur 0, 1, -1, 3 oder -3 ergben (nach Peter). Dabei ist (diff & 1) 
die Änderung. Damit müsste sich bei einer Änderung timeout_led bei 
Bedienung auf 255 stellen. Sobald keine Drehbewegung am Encoder erfolgt 
müsste timeout_led durch timeout_led-- auf 0 gezählt werden. Da der 
Timer mit 1ms läuft und es 255 gemacht wird, ergibt sich eine 
Nachlaufzeit von ca 250ms und die LED muss schalten. Das macht sie 
leider nicht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Henry schrieb:
> Das macht sie leider nicht.
Sondern? Was macht sie stattdessen?

Und zeig auch mal deinen Code (als Dateianhang namens *.c), der zu dem 
Verhalten führt.

Beitrag #7060520 wurde von einem Moderator gelöscht.
von Egonwalter M. (heiner1234)


Lesenswert?

Stefan ⛄ F. schrieb:
> Henry schrieb:
>> Leider habe ich den Eindruck das das meckern vorgeht. Einige meckern
>> lieber als zu helfen
>
> Nein, meckern fällt ihnen (mir) nur sehr viel leichter als höflich zu
> sein.

Es geht nicht um "das meckern", sondern vielmehr um die zumeist 
unqualifizierten Aussagen "... es geht nicht".
Wenn man Hilfe erwartet, dann
- schildert man genau, was man zur Fehlersuche bislang getan hat
- schildert man genau den Fehler (wann tritt er auf, welche 
Schaltzustände usw)
- hängt sein komplettes Programm an und nicht irgendwelche Codeschnipsel

das ist das Mindeste - siehe:

Lothar M. schrieb:
> Henry schrieb:
>> Das macht sie leider nicht.
> Sondern? Was macht sie stattdessen?
>
> Und zeig auch mal deinen Code (als Dateianhang namens *.c), der zu dem
> Verhalten führt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Egonwalter M. schrieb:
> was man zur Fehlersuche bislang getan hat
Das Motto heißt hier "teile und herrsche", und da ist die erste Frage:
funktioniert die Ansteuerung der LED?

Ganz offenbar offenbar ist deine LED low-aktiv, denn
Henry schrieb:
> PORTA = 0b00100000;        // LED auf aus
Da passt also meine Polarität schon mal nicht, und die LED müsste 
während des Drehens ausgehen.

Wenn das mit der LED dann geht, kannst du ja einfach mal einen Taster 
afragen und damit den Zähler auf 255 setzen.

Und wenn die LWD dann auf den Taster reagiert, dann siehst du zu, dass 
das Hochsetzen des Zählers furch eine Drehgeberänderung geschieht.

Und wenn du das hast, dann bist du fertig.

von W.S. (Gast)


Lesenswert?

Henry schrieb:
> In verschiedenen Projekten verwende ich Encoder (Drehgeber) mit RGB
> LEDs.

Das ist ein bissel weit hergeholt. Genauso könnte man auch sagen "in der 
Spargelzeit verwende ich Spargel und zerlassene Butter mit dem Klo". Das 
ist genauso richtig - unter Weglassung einer Zwischenstufe (genannt 
Mensch, der das zu Mittag ißt).

Also: Sinnvollerweise hält man die verschiedenen Dinge in einer Firmware 
auseinander. Etwa so: Drehgeber - Treiber dafür - Events (ist nach links 
gedreht worden oder so) - Logik (was tun, wenn 1 Schritt nach rechts 
gedreht wurde) - Auswertung (LED leuchten lassen oder nicht).

Wenn du dich in deiner Herangehensweise an so ein Konzept hältst, dann 
kanst du jeden einzelnen Teil separat austesten und kommst so viel eher 
zu deinem Resultat.

Wenn du alles in einen Topf schmeißt, dann kommt da keine Ordnung rein 
und wenn du obendrein sowas postest (oder eine nicht verstandene Routine 
von jemand anderem), dann kann dir keiner helfen, denn durch so ein 
Durcheinander und/oder aus dem Kontext gerissenes Zeug will sich keiner 
freiwillig durchwühlen.

W.S.

von Henry (Gast)


Lesenswert?

Konnte den Fehler weiter eingrenzen. Die LED schaltet korrekt. Nach 
Programm start ist die LED ausgeschaltet, beim ersten drehen des 
Encoders schaltet die LED ein und dann nicht wieder aus.
Mit
Lothar M. schrieb:
> if (timeout_led>0)
macht sie leider gar nichts. Der Code:
1
//***********************************************************************                                                                   
2
//                      Reading rotary encoder                      
3
//                      one, two and four step encoders supported   
4
//              Author: Peter Dannegger     und Lohtar M                                
5
//************************************************************************
6
7
#define F_CPU 16000000UL        // Angabe der Frequenz, wichtig für die Zeit
8
#include "avr/io.h"            // Einbindung Datei Ausgänge
9
#include "avr/interrupt.h"        // Einbindung der interrupt.h
10
11
#define PHASE_A     (PINB & 1<<PB2)    // Eingang Encoder A  
12
#define PHASE_B     (PINA & 1<<PA0)    // Eingang Encoder B    
13
14
int8_t val=0;
15
volatile int8_t enc_delta;        // -128 ... 127
16
static int8_t last;
17
volatile int8_t timeout_led = 0;    // neu
18
  
19
  void encode_init( void )
20
    {
21
    int8_t new;
22
    new = 0;
23
    if( PHASE_A ) new = 3;
24
    if( PHASE_B ) new ^= 1;      // Convertiert Gray Code in Binär Code
25
    last = new;            // power on state
26
    enc_delta = 0;
27
    }
28
  
29
  void timer_init()            // Timer2 1ms 16MHz
30
    {
31
    TCCR2A = (1<<WGM01);
32
    TCCR2B = (1<<CS01)|(1<<CS00);
33
    OCR2A = 249;
34
    TIMSK2 |=(1<<OCIE2A);
35
    }
36
  
37
    ISR( TIMER2_COMPA_vect )        // 1ms for manual movement
38
      {
39
      int8_t new, diff;
40
      new = 0;
41
      if( PHASE_A ) new = 3;
42
      if( PHASE_B ) new ^= 1;          // Konvertiert Gray Code in Binär Code
43
      diff = last - new;               // difference last - new
44
      if( diff & 1 )
45
        {                                // bit 0 = value (1)
46
        last = new;                   // store new as next last
47
        enc_delta += (diff & 2) - 1;  // bit 1 = direction (+/-)
48
        timeout_led=255;              // Zeitzähler hochsetzen
49
        }
50
      if (timeout_led>0) 
51
      {
52
      timeout_led--;        // Zeit runterzählen
53
      }
54
      }
55
56
  int8_t encode_read1( void )      // lesen einzel Schritt Encoder = schnell
57
    {
58
    int8_t val;
59
    cli();
60
    val = enc_delta;
61
    enc_delta = 0;
62
    sei();
63
    return val;            // counts since last call
64
    }
65
66
  int8_t encode_read2( void )      // lesen zwei Schritt Encoder = mittel
67
    {
68
    int8_t val;
69
    cli();
70
    val = enc_delta;
71
    enc_delta = val & 1;
72
    sei();
73
    return val >> 1;
74
    }
75
76
  int8_t encode_read4( void )      // lesen vier Schritt Encoder = langsam
77
    {
78
    int8_t val;
79
    cli();
80
    val = enc_delta;
81
    enc_delta = val & 3;
82
    sei();
83
    return val >> 2;
84
    }
85
86
  int main( void )            // Hauptschleife
87
    {
88
    timer_init();
89
    DDRA |= 0b00100000;        // LED 5 auf Ausgang
90
    PORTA = 0b00100000;        // LED auf aus 
91
    sei();
92
    for(;;)
93
      {
94
      val += encode_read1();    // lesen 1,2 oder 4 Schritt Encoder
95
      // LED ansteuern
96
      if (timeout_led==0)
97
        {
98
        PORTA |=(1<<PINA5);
99
        }
100
      else
101
        {
102
        PORTA &=~(1<<PINA5);
103
        }  
104
      }
105
    }
Das funktioniert:
1
if( diff & 1 )
2
        {                                // bit 0 = value (1)
3
        last = new;                   // store new as next last
4
        enc_delta += (diff & 2) - 1;  // bit 1 = direction (+/-)
5
        timeout_led=255;              // Zeitzähler hochsetzen
6
        }
7
      if (timeout_led>0) 
8
      {
9
      timeout_led--;        // Zeit runterzählen
10
      }
Wird timeout_led nicht wieder auf 255 gesetzt?

von Egonwalter M. (heiner1234)


Lesenswert?

W.S. schrieb:
> Henry schrieb:
>> In verschiedenen Projekten verwende ich Encoder (Drehgeber) mit RGB
>> LEDs.
>
> Also: Sinnvollerweise hält man die verschiedenen Dinge in einer Firmware
> auseinander. Etwa so: Drehgeber - Treiber dafür - Events (ist nach links
> gedreht worden oder so) - Logik (was tun, wenn 1 Schritt nach rechts
> gedreht wurde) - Auswertung (LED leuchten lassen oder nicht).
>
> Wenn du dich in deiner Herangehensweise an so ein Konzept hältst, dann
> kanst du jeden einzelnen Teil separat austesten und kommst so viel eher
> zu deinem Resultat.
>
In einem seiner "Tuts" verweist Achim S. aka Henry ja sogar auf diese 
Vorgehensweise:
- Eingabe
- Verarbeitung
- Ausgabe

Deshalb verstehe ich nicht, warum er sich selbst nicht an sein "Tut" 
hält...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Henry schrieb:
> Wird timeout_led nicht wieder auf 255 gesetzt?
Natürlich nicht, weil ein int8_t maximal den Wert 127 annehmen kann. 
Mach da mal ein u mit rein. Sagt der Compiler dazu nichts?

von Henry (Gast)


Lesenswert?

Wie lange wollt ihr mir noch das vergangene vorwerfen? Habe Fehler 
gemacht uns stehe dazu.

Egonwalter M. schrieb:
> Wenn du dich in deiner Herangehensweise an so ein Konzept hältst, dann
>> kanst du jeden einzelnen Teil separat austesten und kommst so viel eher
>> zu deinem Resultat.

Wenn du so gut bist dann kannst du mir vielleicht sagen wie man in 
diesem Programm einzelne Teile separat austesten kann. Die LED 
funktioniert, habe ich getestet, Encoder funktioniert, habe ich 
getestet. Was kann ich noch tun?

Lothar M. schrieb:
> Mach da mal ein u mit rein. Sagt der Compiler dazu nichts?

Es kam keine Fehlermeldung. Habe ein u reingesetzt und jetzt 
funktioniert es.
Danke für deine Hilfe.

von Heiner (Gast)


Lesenswert?

Naja, da war der Code von Lothar M. (Moderator) leider schon falsch, da 
er bei seinem Codeschnipsel
volatile int8_t timeout_led geschrieben hat und den Wert timeout_led = 
255 in der ISR gesetzt hat.

Int8_t reicht aber nur von - … bis + …

Deshalb das “u”

von Heiner (Gast)


Lesenswert?

Und nebenbei - das ist ein Paradebeispiel für hirnloses Abschreiben von 
Code OHNE nachzudenken.

Gratuliere Henry 👍

von Egonwalter M. (heiner1234)


Lesenswert?

Heiner schrieb:
> Naja, da war der Code von Lothar M. (Moderator) leider schon falsch, da
> er bei seinem Codeschnipsel
> volatile int8_t timeout_led geschrieben hat und den Wert timeout_led =
> 255 in der ISR gesetzt hat.
>
> Int8_t reicht aber nur von - … bis + …
>
> Deshalb das “u”


wenn beim Compiler die Flags fuer Warnungen / Errors richtig gesetzt 
wären, würde er warnen:

"warning: overflow in implicit constant conversion"

(macht er jedenfalls bei mir - AVR Studio4.18 Build 716, WINAVR 2010...)

von Stefan F. (Gast)


Lesenswert?

Benutze die Compiler Option -Wall (das kann auch die Arduino IDE)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Heiner schrieb:
> da war der Code von Lothar M. (Moderator) leider schon falsch
Ich sehe sowas als kleine Aufgabe zum Mitdenken an. Hat leider offenbar 
nicht funktioniert. Ich hoffe bloß, dass dieser Hinweis auf das 'u' 
einen gewissen Lerneffekt angestoßen hat. Und die Hoffnung stirbt 
bekanntlich zuletzt...  ;-)

von W.S. (Gast)


Lesenswert?

Lothar M. schrieb:
> Ich sehe sowas als kleine Aufgabe zum Mitdenken an.

Das war dreist.

W.S.

von S. Landolt (Gast)


Lesenswert?

> Das war dreist.
Ja, und wenn ich dann noch an die "Eiweißmasse" denke (wer es 
rechtzeitig sah) ...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> wenn ich dann noch an die "Eiweißmasse" denke
Ja nun, das Gehirn besteht nun mal zum größten Teil aus Eiweiß (aka 
Proteine)...

Immerhin hat Henry die Idee meines Codes verstanden und das mit dem uint 
auch noch gelernt.


Dass man natürlich das Programm noch wesentlich besser entkoppeln könnte 
und im Idealfall der Task "LED ansteuern" nichts mitten im Code 
"Drehgeber" zu suchen hat, steht ausser Frage. Da würde ich im echten 
Leben einen Zeitstempel nehmen und dann mit einem fortlaufenden ms-Timer 
arbeiten. und diese ganze Aufgabe in die Hauptschleife verlegen:
1
:
2
:
3
volatile int32_t millis;
4
:
5
:
6
  ISR( TIMER2_COMPA_vect )        // 1ms for manual movement
7
    {
8
    millis++;
9
    :
10
    :
11
12
  int main( void )            // Hauptschleife
13
    {
14
    static int32_t lastchg = 0;
15
    int32_t tiakt;
16
    int8_t d;
17
18
    timer_init();
19
    DDRA |= 0b00100000;        // LED 5 auf Ausgang
20
    PORTA = 0b00100000;        // LED auf aus 
21
    encode_init();
22
  
23
    for(;;)
24
      {
25
      cli();          // beim lesen von millis: Interrupts blockieren!!
26
      tiakt = millis; // millis werden pro Durchlauf nur 1x gelesen, 
27
      sei();          // im Rest der Schleife ändert sich die Zeit nicht.
28
29
      d = encode_read2();
30
      position += d;
31
32
      if (d!=0) lastchg = tiakt; // Position geändert, Zeitpunkt merken
33
      if (tiakt-lastchg < 333) PORTA |=(1<<PINA5);  // Timeout läuft
34
      else                     PORTA &=~(1<<PINA5); // Timeout abgelaufen
35
36
      }
37
    }

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Lesenswert?

an Lothar Miller:
Es war, zumal für einen Moderator, völlig unangebracht - es hieß bei 
Ihnen "Eiweißgewölle", und da zitiere ich den Duden: 'Gewölle': "von 
Greifvögeln herausgewürgter Klumpen unverdaulicher Nahrungsreste"; und 
das, als Moderator, gegenüber einem Forumsmitglied (mag sich dieses auch 
noch so ungeschickt anstellen).

von W.S. (Gast)


Lesenswert?

S. Landolt schrieb:
> an Lothar Miller:
> Es war, zumal für einen Moderator, völlig unangebracht...

Laß mal, gelegentlich hat auch ein Moderator mal den Drang, sich etwas 
'starkdeutsch' auszudrücken. Was mich hingegen mehr ärgert, sind 
Ausreden wenn einer sich mal vertut. Letzteres ist aud Dauer 
unvermeidlich und da wäre ein simples 'sorry, hab mich mal vertan' 
weitaus besser.

W.S.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Es war, zumal für einen Moderator, völlig unangebracht
Es ist nun mal ganz einfach so, dass es ein Eiweißgewölle ist und man es 
zum Denken verwenden kann und auch sollte. Punkt.

> gegenüber einem Forumsmitglied (mag sich dieses auch noch so ungeschickt
> anstellen).
Wer hat denn dem Henry geholfen obwohl er sich ungeschickt angestellt 
hat?


W.S. schrieb:
> sind Ausreden wenn einer sich mal vertut.
Also gut: ich gebe es hiermit öffentlich jedem zur Kenntnis, dass ich da 
oben mangels Compiler und Testumgebung einen Fehler reingebracht habe. 
Wer sowas noch nie geschafft hat, kann jetzt gern auf mir herumhacken.

: Bearbeitet durch Moderator
von Egonwalter M. (heiner1234)


Lesenswert?

Lothar M. schrieb:
> S. Landolt schrieb:
>> Es war, zumal für einen Moderator, völlig unangebracht
> Es ist nun mal ganz einfach so, dass es ein Eiweißgewölle ist und man es
> zum Denken verwenden kann und auch sollte. Punkt.
>
>> gegenüber einem Forumsmitglied (mag sich dieses auch noch so ungeschickt
>> anstellen).
> Wer hat denn dem Henry geholfen obwohl er sich ungeschickt angestellt
> hat?
>
>
> W.S. schrieb:
>> sind Ausreden wenn einer sich mal vertut.
> Also gut: ich gebe es hiermit öffentlich jedem zur Kenntnis, dass ich da
> oben mangels Compiler und Testumgebung einen Fehler reingebracht habe.
> Wer sowas noch nie geschafft hat, kann jetzt gern auf mir herumhacken.

Ok, kann man nichts dagegen einwenden.
Akzeptiert.

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.