Decoderschaltung für Drehimpulsgeber

So, ich melde mich nochmal, nachdem ich jetzt endlich Zeit gefunden hatte das ganze auch in die Praxis umzusetzen.
Es funktioniert mit 20ms wunderbar.!!!
Es handelt sich um einen handbedienten Drehencoder, so dass ich die 40 St/s nicht erreichen werde.

Jetzt habe ich aber noch ein anderes Projekt vor, bei dem ich ich da nun wieder eine 0 Logik Ausgabe benötige.
Wenn es dir, lieber Pirx, möglich wäre mir den ASM Code zu geben, würde ich mich dort gerne reinfuchsen und sowohl mit der Zeit als auch mit der 0 oder 1 Ausgabe etwas rumprobieren.
Ich will ja auch was lernen und nicht nur fertige HEX Files brennen....
Das wäre super nett !
Gruß
July
 
Wo liegt denn nun eigentlich Dein Problem?
Ich will ja auch was lernen und nicht nur fertige HEX Files brennen....

Ich werde weiterhin Bascom lernen

Beim Auswerten des Drehencoders hilft Bascom Dir weitgehend. (Encoder)
Zum Setzen/Löschen von Bits benutzt Bascom Set/Reset
Und für Zeitvernichtungsschleifen gibts wait/waitms/waitus
...
Hast Du Dir den Link zur Encoder-Funktion mal angesehen?
Im Code-Beispiel am Ende wird der Drehgeber alle 10ms abgefragt, und bei erkannter Änderung in die Subroutinen "Links" bzw "Rechts" gesprungen. Diese 10ms kannst Du entsprechend des tatsächlichen Prellens Deines Encoders variieren, in den Subroutinen läßt Du dann anstelle des Print die Ausgabebeine zappeln (set/reset, und zwischendurch wait/waitms/waitus).
 
... mich dort gerne reinfuchsen ... Ich will ja auch was lernen
Hallo july69,

also die Routine ist recht übersichtlich. Hinsichtlich Assembler ist da nichts dran, was man nicht auch aus der Befehlsreferenz bzw. dem Datenblatt des Prozessors entnehmen könnte. Der Rest wird dir ohne weitergehende Erklärung vermutlich nicht viel bringen.

Frage : Was genau möchtest du denn daran lernen bzw. wo möchtest du dich reinfuchsen ?


Was mich jetzt doch mal interessiert, sind deine Projekte damit. Möchtest du uns nicht auch mal etwas über die erzählen oder sie hier im Forum vorstellen ?

Gruß
Pirx
 
in meinem Fall war der Hauptprozessor ein ATMega8. Der war allerdings schon mit anderen Aufgaben gut beschäftigt und auch etliche Prozessorbaugruppen waren schon anderweitig in Benutzung. Den Drehencoder wirklich zuverlässig zu decodieren habe ich nicht mehr hinbekommen.

Es gibt eine sehr gute Lösung mit einer Tabelle.
Die ist wirklich ziemlich schnell und sollte somit den Mega kein bisschen belasten...
 
Die Tabelle löst lediglich die "Drehrichtungsauswertung", und ein Tabellenzugriff ist auch zumindest ein indirektes Load aus dem SRAM...
Mit dem Drehencoder direkt hätte ich vier Impulse pro Drehschritt und müßte noch die Richtung auswerten. So habe ich nur einen Impuls und brauche keine Zeit zur Auswertung. Und den Impuls gibt es auch nur, wenn es wirklich einen kompletten Drehschritt gab. Und falls der Drehencoder mal Zicken macht, wird der Hauptprozessor nicht sinnlos mit Impulsen beschäftigt.
Pirx hatte ja angemerkt, daß der ursprüngliche Mega8-Hauptprozessor bereits ohne den Encoder gut ausgelastet war, und er es deswegen ausgelagert hat.
 
Das Hauptproblem seinerzeit waren die bereits komplett anderweitig belegten Timer und keiner davon hatte die passende Timerfrequenz für die Encoderabfrage.
Und die mit etlichen Nachteilen behaftete Interruptabfrage war (und ist) einfach nicht nach meinem Gusto.
 
Hey Pirx

habe nach sehr lange Suchen im Netz, dein .hex File gefunden, exakt das, was ich schon seit langer Zeit gesucht habe !

Das File mit 200ms ist perfekt !

Ich würde aber gerne einen Attiny 45 oder andere CPU´s Verwenden, und daher währe es toll, wenn du das Assambler File hier reinstellen könntest.

LG
Tom
 
  • Pirx hat das ganze damals als seperaten Controller gemacht, weil der eigentliche Controller hardware- und zeittechnisch recht ausgelastet war.
  • der seperate Drehencoder-auswerte-Controller hat keine weiteren Aufgaben - er muß also nicht effizient oder sparsam implementiert werden. Wichtig ist nur die sichere Funktion.
  • Für die eigentliche Funktion werden (neben der Stromversorgung) nur vier Pins gebraucht. Es empfiehlt sich also die Verwendung eines acht- oder sechsbein-Tinies (beim Tiny4/5/9/10 müßte man den Reset zum I/O machen, die Modus-Auswahl (seperate Richtungsimpulse vs. Richtung+Clock) könnte man mittels Pull-Widerständen an den Ausgängen realisieren, die einmalig beim PowerUp ausgewertet werden.
  • Pirx hat dem Forum seinen Lösungsansatz (die Idee), und auch das ASM-Programm bereitgestellt - es bleibt jedem frei, das für eigene Bedürfnisse anzupassen.
Du bist jetzt bereits der zweite, der von Pirx 'ne Anpassung an Deine Bedürfnisse erbittet.
Ok, ein ASMler sollte Pirx' ASM-Datei selbst anpassen können, ein BASCOMler sollte das alles mit dem von mir mehrfach geposteten Link auf die Encoder-Routine selbst schaffen (da ist das gefühlt nur ein fünfzehnzeiler oder so).
Inwiefern es bei C fertige Routinen gibt, kann ich(!) nicht sagen - Dirk hatte meiner Erinnerung nach mehrfach Lösungen dazu.

Mein Vorschlag für Dich wäre (trotzdem), daß Du(!) das mal in Bascom angehst - die Lösung wäre vom letztlich verwendeten Controller unabhängig (der wird am Anfang inkludiert und kann ausgetauscht werden), die Abtastfrequenz (Entprellung) der Encoderpins und die Pulslängen der Ausgänge wird durch waitms-Instruktionen realisiert - wäre also auch anpaßbar.

Die wesentliche Funktion ist mit der verlinkten Encoder-Routine bereits als Code-Beispiel vorhanden, da fehlt nur noch die Ausgabe.
Wenn Du dabei an irgendeiner Stelle nicht mehr weiterkommst, schau ich gern rein, vielleicht auch einer der Bascom-Profis hier?!

P.S.: Bascoms Encoder-Instruktion nutzt (abgesehen von den Pins) keine Controller-Hardware, ist also unabhängig von weiterer Controller-Hardware.
Die Eingangspins müssen am selben Port hängen (bei den meisten kleinen Tinies gibts eh nur einen).
Die Encoder-Instruktion besitzt einen Parameter, die das Programm auf den nächsten Schritt warten läßt.

P.P.S.: Willkommen im Forum
 
Danke für die Infos

Ich bräuchte nur das Original File, damit ich mir den CPU selber nach bedarf ändern kann.
Das Hex File dazu ist ja bereits gepostet worden, nur halt nicht die zugehörige .asm Datei.
( DIG_HW3_ATT13 mit Delay zum Test.hex ) ... von Dino03 am 27.10.2008

Thanks
Tom
 
Hallo Tom,

ich denke der Assembler-Sourcecode ist im Startbeitrag angehängt (im Beitrag unten Box Anhänge).

(27.10.08 ist das Registrierungsdatum von Dino03)

Dirk :ciao:
 
Genau. Das war die ursprüngliche Version.
Auf Wunsch von July hat Pirx dann nochmal 'ne zweite Version mit anderen Timings rausgegeben, diesmal nur als HEXfile.
Wie gesagt, wahrscheinlich mittels NOPs in definierten Schleifen. Das sollte ein ASMler problemlos hinbekommen.
Flexibler bist Du, wenn Du das Encoder-Beispiel aus der Bascom Hilfe anpaßt - da nimmt Bascom Dir nämlich das berechnen der Warteschleifen usw ab.
Aber ich rede im Kreis...
(Ok, man braucht statt/neben dem AtmelStudio auch noch Bascom, wäre vielleicht ein Argument...)
 
Hallo Tom,
Das File mit 200ms ist perfekt !

Wofür brauchst du das mit 200 Millisekunden Ausgabe ? Wo dreht man denn in der Praxis derart langsam ?

Ich würde aber gerne einen Attiny 45 oder andere CPU´s Verwenden, und daher währe es toll, wenn du das Assembler File hier reinstellen könntest.

Das auf andere Prozessoren umzusetzen, ist grundsätzlich nicht ganz trivial. Ich habe mir das für den Tiny13 und der 45er kurz angesehen. Die beiden sind sehr ähnlich, da sind nur 2 Änderungen nötig, die ich dir schnell machen kann. Ich muss nur wissen mit welchem Delay und ob H- oder L-aktiv.

Wenn du da wirklich selbst Hand anlegen willst, wird es nicht ohne Erklärung des Ganzen gehen. Aber nicht mehr heute. Das Wetter ist einfach zu schön.

Gruß
Pirx
 
Eben deswegen hatte ich ja auch vorgeschlagen, das eine Hochsprache machen zu lassen die eine entsprechende Software-Funktion anbietet, und problemlos die Anpassung an einen anderen Controller selbst übernimmt.
BASCOM bietet eine Encoder-Funktion, in der Hilfe findet sich dazu folgendes Beispiel:

CodeBox BascomAVR
'-----------------------------------------------------------------------------------------
'name                     : encoder.bas
'copyright                : (c) 1995-2005, MCS Electronics
'purpose                  : demonstration of encoder function
'micro                    : Mega128
'suited for demo          : yes
'commercial addon needed  : no
'An encoder has 2 outputs and a ground
'We connect the outputs to pinb.0 and pinb.1
'You may choose different pins as long as they are at the same PORT
'The pins must be configured to work as input pins
'This function works for all PIN registers
'-----------------------------------------------------------------------------------------

$regfile = "m128def.dat"                                    ' specify the used micro
$crystal = 4000000                                          ' used crystal frequency
$baud = 19200                                               ' use baud rate
$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

Print "Encoder test"
Dim B As Byte
'we have dimmed a byte because we need to maintain the state of the encoder

Portb = &B11                                                ' activate pull up registers

Do
  B = Encoder(pinb.0 , Pinb.1 , Links , Rechts , 1)
  '                                               ^--- 1 means wait for change which blocks programflow
  '                               ^--------^---------- labels which are called
  '              ^-------^---------------------------- port PINs
  Print B
Waitms 10
Loop
End

'so while you can choose PINB0 and PINB7,they must be both member of PINB
'this works on all PIN registers

Links:
Print "left rotation"
Return

Rechts:
Print "right rotation"
Return
End

ok, bereinigen wir das mal auf den wesentlichen Teil:

CodeBox BascomAVR
$regfile = "m128def.dat"                                    ' specify the used micro
$crystal = 4000000                                          ' used crystal frequency (von wait-Instruktionen benötigt)

Dim B As Byte
'we have dimmed a byte because we need to maintain the state of the encoder

Portb = &B11                                                ' activate pull up registers

Do
  B = Encoder(pinb.0 , Pinb.1 , Links , Rechts , 1)
  '                                               ^--- 1 means wait for change which blocks programflow
  '                               ^--------^---------- labels which are called
  '              ^-------^---------------------------- port PINs
Waitms 10                                                   'Entprellung
Loop
End

Links:
'Code für erkannten Links-Schritt
Return

Rechts:
'Code für erkannten Rechts-Schritt
Return
End

Ok, für den zu wählenden Controller ist einfach dessen Definitionsdatei in Zeile 1 anzugeben, ich habe hier grad den Tiny2312A zur Hand.
Die tatsächliche Taktfrequenz (Zeile 2) benötigt BASCOM hier für die Berechnung der Warteschleifen, mein Tiny taktet mit 8MHz internem Oszillator.

Die zu verwendenden Pins wollen wir einfach austauschbar haben, also definieren wir uns dafür Compilernamen mittels Alias:

CodeBox BascomAVR
'###  Eingänge 1 und 2, gelesen wird das PIN-Register, müssen zum selben Port gehören  ###
Epin Alias Pinb                                             'Pinregister fürs lesen
Eport Alias Portb                                           'Portregister für die Pullups
E1 Alias 0
E2 Alias 1
'###  Ausgänge 1 und 2, geschrieben wird das Port-Register  ###
A1 Alias Portb.2
A2 Alias Portb.3
Beim Eingangsport wird das Port-Register für die Pullups benötigt, das Pin-Register für den Lesezugriff.
Die Eingänge werden bei der Encoder Instruktion verwendet:

CodeBox BascomAVR
  B = Encoder(epin.e1 , Epin.e2 , Links , Rechts , 1)

Für die Wahl des Modus (Richtung+Puls vs. L-R-Pulse) könnte man beides implementieren, ich definiere 'ne Kompilerkonstante und verwende später bedingte Kompilierung:

CodeBox BascomAVR
'###  Betriebsmodus: 1= Direction + Pulse, 0= Links- und Rechts-Pulse  ###
Const Dirpulsemode = 1
Ebenso ob die Ausgänge H- oder L-aktiv sein sollen:

CodeBox BascomAVR
'### Zustand der Ausgänge: 1= H-aktiv, 0=L-aktiv
Const H_active = 0
Außerdem noch die Entprell(warte)zeit und die Pulsdauer als Konstanten:

CodeBox BascomAVR
'###  Entprellwartezeit in ms  ###
Const Debouncetime = 10
'###  Pulszeit in µs  ###
Const Pulsetime = 100
Bis hier noch kein neuer Code...
Los geht's - die Ausgänge müssen entsprechend der vorgegebenen Modi in Grundstellung gebracht werden (bedingte Kompilierung):

CodeBox BascomAVR
'Ausgänge in (modiabhängigen) Grundzustand bringen:
#if H_active = 0
   Set A2
   #if Dirpulsemode = 0
      Set A1
   #endif
#endif
Config A1 = Output
Config A2 = Output
Bei den Eingängen sind die Pullups zu aktivieren:

CodeBox BascomAVR
'Pullups der Eingänge aktivieren
Set Eport.e1
Set Eport.e2
In der Hauptprogrammschleife beim Encoder-Aufruf die Aliases ersetzen, hatte ich schon; bei der Wait-Instruktion die definierte Konstante rein.
Die beiden Encoder-Ergebnisroutinen:

CodeBox BascomAVR
Links:
'Code für erkannten Links-Schritt
#if Dirpulsemode = 1                                        'bei DirPulseMode
   Reset A1
   #if H_active = 0                                         'L-aktive
      Reset A2
      Waitus Pulsetime
      Set A2
   #else                                                    'H-aktiv
      Set A2
      Waitus Pulsetime
      Reset A2
   #endif
#else                                                       'bei L-R-Mode
   #if H_active = 0                                         'L-aktiv
      Reset A1
      Waitus Pulsetime
      Set A1
   #else                                                    'H-aktiv
      Set A1
      Waitus Pulsetime
      Reset A1
   #endif
#endif
Return

Rechts:
'Code für erkannten Rechts-Schritt
#if Dirpulsemode = 1                                        'bei DirPulseMode
   Set A1
   #if H_active = 0                                         'L-aktive
      Reset A2
      Waitus Pulsetime
      Set A2
   #else                                                    'H-aktiv
      Set A2
      Waitus Pulsetime
      Reset A2
   #endif
#else                                                       'bei L-R-Mode
   #if H_active = 0                                         'L-aktiv
      Reset A2
      Waitus Pulsetime
      Set A2
   #else                                                    'H-aktiv
      Set A2
      Waitus Pulsetime
      Reset A2
   #endif
#endif
Return


Alles nochmal zusammen:

CodeBox BascomAVR
$regfile = "ATtiny2313A.DAT"                                ' specify the used micro
$crystal = 8000000                                          ' used crystal frequency (von wait-Instruktionen benötigt)
'###  Eingänge 1 und 2, gelesen wird das PIN-Register, müssen zum selben Port gehören  ###
Epin Alias Pinb                                             'Pinregister fürs lesen
Eport Alias Portb                                           'Portregister für die Pullups
E1 Alias 0
E2 Alias 1
'###  Ausgänge 1 und 2, geschrieben wird das Port-Register  ###
A1 Alias Portb.2                                            '=Direction oder Left
A2 Alias Portb.3                                            '=Pulse oder Right
'###  Betriebsmodus: 1= Direction + Pulse, 0= Links- und Rechts-Pulse ###
Const Dirpulsemode = 1
'###  Zustand der Ausgänge: 1= H-aktiv, 0=L-aktiv  ###
Const H_active = 0
'###  Entprellwartezeit in ms  ###
Const Debouncetime = 10
'###  Pulszeit in µs  ###
Const Pulsetime = 100

'###########################################################
'Ausgänge in (modiabhängigen) Grundzustand bringen:
#if H_active = 0
   Set A2
   #if Dirpulsemode = 0
      Set A1
   #endif
#endif
Config A1 = Output
Config A2 = Output

Dim B As Byte
'we have dimmed a byte because we need to maintain the state of the encoder
'Pullups der Eingänge aktivieren
Set Eport.e1
Set Eport.e2

Do
  B = Encoder(epin.e1 , Epin.e2 , Links , Rechts , 1)
  '                                               ^--- 1 means wait for change which blocks programflow
  '                               ^--------^---------- labels which are called
  '              ^-------^---------------------------- port PINs
Waitms Debouncetime                                         'Entprellung
Loop
End

Links:
'Code für erkannten Links-Schritt
#if Dirpulsemode = 1                                        'bei DirPulseMode
   Reset A1
   #if H_active = 0                                         'L-aktive
      Reset A2
      Waitus Pulsetime
      Set A2
   #else                                                    'H-aktiv
      Set A2
      Waitus Pulsetime
      Reset A2
   #endif
#else                                                       'bei L-R-Mode
   #if H_active = 0                                         'L-aktiv
      Reset A1
      Waitus Pulsetime
      Set A1
   #else                                                    'H-aktiv
      Set A1
      Waitus Pulsetime
      Reset A1
   #endif
#endif
Return

Rechts:
'Code für erkannten Rechts-Schritt
#if Dirpulsemode = 1                                        'bei DirPulseMode
   Set A1
   #if H_active = 0                                         'L-aktive
      Reset A2
      Waitus Pulsetime
      Set A2
   #else                                                    'H-aktiv
      Set A2
      Waitus Pulsetime
      Reset A2
   #endif
#else                                                       'bei L-R-Mode
   #if H_active = 0                                         'L-aktiv
      Reset A2
      Waitus Pulsetime
      Set A2
   #else                                                    'H-aktiv
      Set A2
      Waitus Pulsetime
      Reset A2
   #endif
#endif
Return
End
Kann das mal wer testen?? Controller, Taktfrequenz, Konstanten/Aliases und die Modi nach Wunsch vorgeben und dann compilieren/brennen/testen...
 
Zuletzt bearbeitet:
Soll der Code für die Auswertung eines Drehgebers sein? Falls ja - viel zu kompliziert. Es geht auch viel einfacher und kürzer
achim
 
Soll der Code für die Auswertung eines Drehgebers sein? Falls ja - viel zu kompliziert
Nein, die Auswertung des Drehgebers erfolgt nur in:

CodeBox BascomAVR
B = Encoder(epin.e1 , Epin.e2 , Links , Rechts , 1)
, und wie Bascom das handhabt, hab ich jetzt nicht reassembliert - ist für den standalone-Controller auch egal.
... viel zu kompliziert. Es geht auch viel einfacher und kürzer
Einfacher ist wie so oft relativ. Quick'n'Dirty ist es am einfachsten, die fertige Funktion zu nutzen, statt selbst was zu coden.
Der ganze Rest mit der bedingten Compilierung hat nur den Zweck, daß man jede der vier Ausgabemöglichkeiten einfach auswählen kann, indem man oben die Konstante entsprechend setzt. Bascom compiliert dann nur den relevanten Teil entsprechend den verwendeten #if...#else..#endif-Direktiven.

Ebenso sind die Ein- und Ausgangspins frei wählbar (wobei die Eingangspins Bascoms Encoder-Funktion folgend am selben Port sein müssen).

Sicher können wir (ich in Assembler, Du in einer Sprache Deiner Wahl) das effizienter und sicherer selbst coden, aber hier geht es um die ganzen ... weniger fähigen User, die dem armen Pirx auf die Pelle rücken, für sie wegen anderer Timings, anderer Pegel, anderer Controller sein Programm anzupassen, und ein neues HEXfile hochzuladen.
Und die könnten eben einfach mit Bascoms Encoder-Routine glücklich werden - mein Programm strickt ja nur die ganzen möglichen Anpassungen drumrum.
Wobei eben nur immer der relevante Teil des Codes compiliert wird. In den Links-/Rechts-Routinen landen je nur 3 bzw 4 Instruktionen...

Und wie immer gibt es wegen der Variabilität auch gewisse Abstriche, die ich in Kauf genommen habe...
 
Zuletzt bearbeitet:
Hallo
schau dir mal das Programm an:


CodeBox C
#define PHASE_A     (PINA & 1<<PA0)       // Eingang Encoder A  P98
#define PHASE_B     (PINA & 1<<PA1)       // Eingang Encoder B  P98   

//#define PHASE_A     (PINA & 1<<PA2)       // Eingang Encoder A  P32
//#define PHASE_B     (PINA & 1<<PA1)       // Eingang Encoder B  P32


#define LEDS_DDR    DDRB               // Ausgang LED
#define LEDS        PORTB               //

volatile int8_t enc_delta;               // -128 ... 127
static int8_t last;

void encode_init( void )
  {
   int8_t new;
   new = 0;
   if( PHASE_A ) new = 3;   //3
   if( PHASE_B ) new ^= 1;               // convert gray to binary
   last = new;                           // power on state
   enc_delta = 0;
   TCCR0A = (1<<WGM01);               // Timer 1 ms bei 16 Mhz
   TCCR0B = (1<<CS01) | (1<<CS00);       // CTC, prescaler 64
   OCR0A = 249;                       // 1ms
   TIMSK0 |= (1<<OCIE0A);
  }

ISR( TIMER0_COMPA_vect )               // 1ms for manual movement
  {
   int8_t new, diff;
   new = 0;
   if( PHASE_A ) new = 3;
   if( PHASE_B ) new ^= 1;               // convert gray to binary
   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 (+/-)
     }
  }

int8_t encode_read1( void )               // lesen einzel Schritt Encoder = schnell
  {
   int8_t val;
   cli();
   val = enc_delta;
   enc_delta = 0;
   sei();
   return val;                   // counts since last call
  }

int8_t encode_read2( void )               // lesen zwei Schritt Encoder = mittel
  {
   int8_t val;
   cli();
   val = enc_delta;
   enc_delta = val & 1;
   sei();
   return val >> 1;
  }

int8_t encode_read4( void )               // lesen vier Schritt Encoder = langsam
  {
   int8_t val;
   cli();
   val = enc_delta;
   enc_delta = val & 3;
   sei();
   return val >> 2;
  }

int main( void )                       // Hauptschleife
  {
   int32_t val = 0;
   LEDS_DDR = 0xFF;
   encode_init();
   sei();
   for(;;)
     {
       val += encode_read4();          // lesen 1,2 oder 4 Schritt Encoder
       LEDS = val;
     }
  }

Es stammt im ori von Peter Danneger und habe es an meine Hardware angepasst. Es arbeitet mit Timer und man kann die Eingänge wählen. Es sind 4 verschiedene Drehgeber im Code enthalten. Da durch kannst du fast jeden Typ verwenden. Einer ist ausgewählt, paasend zum verwendeten Typ. Zusätzlich habe ich noch (in einer anderen Anwendung) den Eingabe Knopf berücksicht. Diese Funktion an einem Knopf hat die Funktion Umschaltung, Kurz gedrückt und langgedrückt. Dadurch ist zusammen mit einer Anzeige eine Einknopfbedienung zur Auswahl in einem Menue mit mehreren Ebebenen und Reset entstanden. Ist zwar alles in C geschrieben, bestimmt auch in Basic vorhanden.
achim
 
Es geht doch hier nicht (nur) um die Auswertung des Encoders, sondern (im wesentlichen) darum, daß der Controller entsprechende Impulse (Möglichkeit 1: getrennt Links und rechts, Möglichkeit 2: Schritt und Richtung, und je mit wählbarer Ruhephasenlage und Pulslänge) generiert.
Pirx hatte damals keinen Timer mehr frei/verwendbar, und den Controller auch so schon weitgehend ausgelastet, daß er das ganze in einen seperaten Tiny-Controller ausgelagert hatte (der eben die ganze Dekodiererei übernimmt, und nur noch korrekt erkannte Schrittimpulse an den Hauptcontroller weiterleitete. Der Hauptcontroller mußte also pro Schritt nur noch auf eine(!) Flanke reagieren (IRQ in dem Fall), und zwei Pins einlesen. War für ihn einfacher, als im Hauptcontroller weiterzuoptimieren...
Danach kamen mehrere User, die genau diese Funktion mit eigenen Anpassungen von ihm realisiert haben wollten.
Und die hätten eben einfach(!) die Bascom-Bordmittel (in der Encoder-Funktion steckt quasi das was Du in den Timerinterrupt und die Encode_read-Funktion geschrieben hast - Bascom bietet das selbst (ohne was über die Qualität der Implementierung zu sagen)) nutzen können.
Ich habe jetzt nur die Erzeugung der jeweiligen Ausgabeimpulse drumrumgestrickt, und das ganze flexibel anpaßbar gestaltet - die ersten 19 Zeilen sind nur Compilerkonstanten/Direktiven, die festlegen, welcher Teil wie compilert wird (und davon die hälfte Kommentare).
Bei Deinem Code wird der Compiler sicher auch die nicht verwendeten "encode_readn"-Funktionen wegoptimieren.

Aber das stand schon bis zum erbrechen in den letzten dreißig Beiträgen oder so...

Bei Deinem Code sehe ich zB nicht, wo ich mal eben einfach die Phasenlage des Ausgabesignals umkehren kann - bei mir muß dazu nur die Compilerkonstante in Zeile13 geändert werden.
Oder wenn ein anderer Controller verwendet werden soll, ist lediglich das verwendete Regfile einzutragen. Ohne irgendwelche periphäre Hardware zu berücksichtigen (abgesehen von den verwendeten Pins und Controllern bei denen die Pullups nicht via DDR/PORT angesteuert werden. - Falls Bascom die überhaupt schon unterstützt).
Bei Dir muß dann das Encode-Init ggf angepaßt werden...
Zur Anpassung an den tatsächlichen Takt muß nur die Crystal-Direktive angepaßt werden, die Timings rechnet Bascom dann selbst aus (geht bei C und ASM auch, klar, aber das nutzt Du nicht).
Natürlich würde ich(!) das in einem konkreten Fall auch direkt selbst auf den konkreten Controller zurechtcoden, aber ich muß Pirx auch nicht fragen, ob er für mich seinen Code anpaßt, mir das HexFile schickt...
 
Ist nur ein Beispiel von mir. Bei Bascom muss ich leider passen. Die Anpassung der Frequenz habe ich in diesen Teilen nicht drin.
Die anderen möglichen Drehgeber werden hier eingestellt


CodeBox C
val += encode_read4();          // lesen 1,2 oder 4 Schritt Encoder

Durch aus möglich das einiges weg optimiert werden. egal, ein Vorschlag viôn mir zu dem Thema.
achim
 
; ==================================================================; ===== 8ms warten =================================================; ==================================================================; rcall wait8m ; (3) Warteschleife aufrufen; ================> ; 131858 Cyclen (incl Call+Ret) => ~8,24ms@16MHzwait8m: push r20 ; (2) r20 auf Stack retten (1tes) push r21 ; (2) r21 auf Stack retten (2tes) clr r20 ; (1) r20+r21 ergeben zusammen clr r21 ; (1) einen 2-Byte-Zaehler ; ; 2__________131841_ ; | 1__513__ | ; | | | | ; 12 Cycle = 256*((256*2+1)+2)+1+17loop8m: dec r20 ; (1) || niedrigstes Byte -1 brne loop8m ; (1f,2t)_/| 0 erreicht? nein -> Schleife dec r21 ; (1) | mittleres Byte -1 brne loop8m ; (1f,2t)__/ 0 erreicht? nein -> Schleife pop r21 ; (2) r21 zurueckholen (2tes) pop r20 ; (2) r20 zurueckholen (1tes) ret ; (4) Schleifenende, Rueckkehr

Moin!

@dino03 ich bin ein blutiger Anfänger, habe noch so gar keine Ahnung vom Assembler^^
Ist das der Wert (131843) den du in die Register r20 / r21 schreibst?

Ich bekomme da eine ganz andere Zeit raus..

upload_2017-10-21_14-5-28.png
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)