Forum: Mikrocontroller und Digitale Elektronik Interrupt wird nicht immer verarbeitet


von neuling (Gast)


Lesenswert?

Hallo zusammen,

Ich möchte Encoder gesteuert einige Funktionen ausführen. Die Fallende 
Flanke löst ein Interrupt aus welches ein Flag setzt und in der WHile1 
wir das Flanke zurück gesetzt und eine Funktion ausfgerufen. Im 
Interrupt prüfe ich ob das Flag zurücksetzt wurde. Wenn nein wird der 
Fehlercode 4 an meinen LEDs angezeigt.

Ich habe das Problem das bei einer Interrupt Frequenz von 500Hz in 
unregemäßigen Abständen   der ATmega 128 mit einem 14,...MHz Quarz nicht 
schafft das Interrupt zu verarbeiten und er immer in den Fehlerzustand 
geht.

Hier ist mein Code
1
#include "allHeader.h"
2
volatile int selftest_need = 0;
3
volatile int encoderA_flag = 0;
4
5
6
7
8
int main()
9
{
10
  
11
  
12
  
13
  initInputs();
14
  initOutputs();
15
  initStatusLEDs();
16
  
17
  
18
  // einstellen fallende Flanke + Aktivieren
19
  EICRB &= ~(1<<ISC40);
20
  EICRB |= (1<<ISC41);
21
  EIMSK |= (1<<INT4);
22
  
23
24
  sei();
25
  
26
  
27
28
29
  while(1)
30
  {  LEDPORT = selftest_need;
31
    
32
      if(encoderA_flag)
33
      {
34
        encoderA_flag = 0; //ggf. ans Ende
35
        
36
      }
37
38
  }
39
}
40
41
42
43
44
// Encoderinterrupt
45
ISR(INT4_vect)
46
{
47
  if(encoderA_flag == 1)
48
  {
49
    selftest_need = 4;
50
  }
51
  else
52
  {
53
    selftest_need = 0;
54
  }
55
  
56
  /*if(encoderDirection()!=LEFT)
57
  selftest_need = 5;*/
58
  
59
  encoderA_flag = 1;
60
  
61
}

Habt ihr eine Idee voran es liegen kann? Ich habe schon versucht mit 
einem Rechteckgenerator den Encoder zu ersetzten das Problem bleibt 
leider das Gleiche.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

> volatile int selftest_need = 0;

warum 16bit um 0 oder 1 zu speichern?

kosten sinnlos Rechenzeit und ist nicht mehr atomar. Ändere es mal auf 
uint8_t ab.

von neuling (Gast)


Lesenswert?

Nachtrag:

die Frequenz auf unter ein Hz einstellen für ebenfalls dazu das er das 
Interrupt nicht immer verarbeitet.

von Peter II (Gast)


Lesenswert?

Kann es sein das die kontakte prellen?

von neuling (Gast)


Lesenswert?

Peter II schrieb:
> Kann es sein das die kontakte prellen?

Ich habe ein minmale zappeln auf dem Rechtecksignal kann das die Ursache 
sein?

von Peter II (Gast)


Lesenswert?

neuling schrieb:
> Ich habe ein minmale zappeln auf dem Rechtecksignal kann das die Ursache
> sein?

ja

von neuling (Gast)


Lesenswert?

Peter II schrieb:
> neuling schrieb:
>> Ich habe ein minmale zappeln auf dem Rechtecksignal kann das die Ursache
>> sein?
>
> ja

ok und wie löse ich das jetzt am besten? Ein C gegen Masse? reicht das 
schon?

von (prx) A. K. (prx)


Lesenswert?

Tritt das Problem auch beim gezeigten Schrumpfprogramm auf, oder nur 
beim Original?

von neuling (Gast)


Lesenswert?

A. K. schrieb:
> Tritt das Problem auch beim gezeigten Schrumpfprogramm auf, oder
> nur
> beim Original?

auch bei dem minimal Beispiel bei unter 1Hz Interruptfrequenz!!!

von Peter II (Gast)


Lesenswert?

neuling schrieb:
> ok und wie löse ich das jetzt am besten? Ein C gegen Masse? reicht das
> schon?
wenn man alles richtig Dimensioniert ja, aber daran denken, das ein 
Kondensator im ersten Moment ein Kurzschluss ist

oder per Software

http://www.mikrocontroller.net/articles/Drehgeber

von Michael B. (laberkopp)


Lesenswert?

neuling schrieb:
> Ich möchte Encoder gesteuert einige Funktionen ausführen. Die Fallende
> Flanke löst ein Interrupt aus

Soll das jetzt ein Trollbeitrag sein ?

Natürlich ist es nicht zuverlässig, einen Encoder per Flankeninterrupt 
auszuwerten. Da muss man nicht auf die Desinformationskampagne von 
TorstenC und m.n. reinfallen.

Beitrag "Drehimpulsgeber"

von Karl H. (kbuchegg)


Lesenswert?

Was machen
>
>   initInputs();
>   initOutputs();
>   initStatusLEDs();

Die Pullups am Eingang hast du aktiviert?

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> neuling schrieb:
>> Ich habe ein minmale zappeln auf dem Rechtecksignal kann das die Ursache
>> sein?
>
> ja

Nicht bei dem Testcode.

Prellen spielt sich im Millisekundenbereich ab. Wenn ein mit 14Mhz 
getakteter M128 da nicht mitkommt, ist irgendwas anderes faul

von Bastler (Gast)


Lesenswert?

Doch bei dem Testcode.
Wenn nämlich "funktioniert" bedeutet: "keine Fehler-LED leuchtet" und 
wegen Prellen nach dem RETI nur einen "Hauptschleifenbefehl" ausgeführt 
wird, was nicht reicht um encoderA_flag zu löschen und der nächste Int 
dann schreit "Fehler".

Wenn man den μC verprellt, da spielt er manchmal nicht mehr mit ;-)

von dunno.. (Gast)


Lesenswert?

du greifst sowohl im interrupt als auch in deiner hauptschleife auf die 
gleiche variable zu. sind die zugriffe nicht atomic, geht das beinahe 
schon mit ansage schief.

kann natürlich auch hardwarebedingt sein, aber wenn du sagst du hast es 
schon mit nem generator getestet..

mach mal in der hauptschleife um die prüfung herum die interrupts aus.

von neuling (Gast)


Lesenswert?

Karl H. schrieb:
> Was machen
>>
>>   initInputs();
>>   initOutputs();
>>   initStatusLEDs();
>
> Die Pullups am Eingang hast du aktiviert?

void initOutputs()
{

  JETDDR |= (1<<JET1);
  JETDDR |= (1<<JET2);

}

void initInputs()
{
  ENCODERDDR &= ~(1<<ENCODERA);
  ENCODERDDR &= ~(1<<ENCODERB);

}


void initStatusLEDs()
{
  LEDDDR |= 255; // set LEDpins

}

dunno.. schrieb:
> mach mal in der hauptschleife um die prüfung herum die interrupts aus.
Dann funktioniert es. Muss ja auch so sein, denn das erneute aufrufen 
des Interrups löst ja den Fehler aus.

Wenn ich die Interrups aber aus mache, kann ich mir die Abfrage auch 
sparen. Ich möchte ja jeden fallenden Flankenwechsel erkennen. Es darf 
keiner verpasst werden. Sollten 2 Flankenwechsel ohne Verarbeitung 
dazwischen kommen benötitge ich den Fehler. Wenn das Interrupt während 
der Verarbeitung kommt wäre das ok solange Es bis zum nächsten Interrupt 
wieder in der Verarbeitung ist.

Wie löse ich das am saubersten.

von dunno.. (Gast)


Lesenswert?

neuling schrieb:
> Wenn ich die Interrups aber aus mache, kann ich mir die Abfrage auch
> sparen. Ich möchte ja jeden fallenden Flankenwechsel erkennen.

Wenn der interrupt während der Abfrage aus ist, wird nur nicht in die 
ISR gesprungen. Die Flanke wird aber trotzdem erkannt, und die ISR 
sofort ausgeführt, sobald der interrupt wieder aktiviert wird.

was du verpassen würdest, wäre, wenn du zur zeit der abfrage zwei 
interrupts bekommst. rechne mal aus wie schnell das sein musste, und mit 
wieviel u/min dein encoder gedreht werden müsste..

von Peter II (Gast)


Lesenswert?

dunno.. schrieb:
> rechne mal aus wie schnell das sein musste, und mit
> wieviel u/min dein encoder gedreht werden müsste..

oder er prellt

von dunno.. (Gast)


Lesenswert?

Peter II schrieb:
> oder er prellt

Richtig, das ist natürlich auch noch sehr gut möglich.

Trotzdem, der Code so wie er ist ist doch gerade das paradebeispiel aus 
ner vorlesung über race-conditions.

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


Lesenswert?

neuling schrieb:
> Wenn ich die Interrups aber aus mache
Jeder Interrupt, der nicht unbedingt benötigt und deshalb nicht 
verwendet wird, reduziert die möglichen Probleme um den Faktor 2..10. 
Und einen Drehgeber, an dem mit der Hand gedreht wird, liest man am 
Besten mit dem sowieso nötigen 1ms-TimerTic ein. Sieh dir dazu mal den 
Beitrag "Drehimpulsgeber" an. Dort wird die Thematik 
ausführlich und kontrovers diskutiert. Solange, bis zum Schluss die 
Interrupt-Verarbeiter übrig bleiben...

> Ich möchte ja jeden fallenden Flankenwechsel erkennen. Es darf keiner
> verpasst werden.
Wie schnell können diese Flanken denn überhaupt wechseln?

von neuling (Gast)


Lesenswert?

Mit Interrupt aus und wieder ein geht es. Jetzt habe ich ein anderes 
interesantes Problem.

Ich möchte jetzt noch 2 Lichtschranken über Interrupt einbinden und je 
nach Auslösung einen Trigger senden. Die Lichtschranken Liefern 5V und 
bei Unterbrechung fallen sie auf 0V.

Ich habe den Code wie folgt erweitert:

#include "allHeader.h"
volatile uint8_t selftest_need = 0;
volatile uint8_t encoderA_flag = 0;
volatile uint8_t ls1_flag = 0;
volatile uint8_t ls2_flag = 0;



int main()
{


  initInputs();
  initOutputs();
  initStatusLEDs();

  JETPORT &= ~(1<<JET1);
  JETPORT &= ~(1<<JET2);

  // einstellen fallende Flanke + Aktivieren
  EICRB &= ~(1<<ISC40);
  EICRB |= (1<<ISC41);
  EIMSK |= (1<<INT4);

  EICRB &= ~(1<<ISC50);
  EICRB |= (1<<ISC51);
  EIMSK |= (1<<INT5);

  EICRB &= ~(1<<ISC60);
  EICRB |= (1<<ISC61);
  EIMSK |= (1<<INT6);

  sei();
  while(1)
  {  LEDPORT = selftest_need;

    CAMPORT &= ~(1<<CAM1);
    CAMPORT &= ~(1<<CAM2);
    cli();
    if(encoderA_flag)
    {
      encoderA_flag = 0; //ggf. ans Ende
      JETPORT |= (1<<JET1);// im Regelfall nicht da
      JETPORT |= (1<<JET2);// im Regelfall nicht da
    }

    sei();
    cli();
    if(ls1_flag)
    {
      ls1_flag = 0; //ggf. ans Ende
      JETPORT |= (1<<JET1);
    }
    sei();
    cli();
    if(ls2_flag)
    {
      ls2_flag = 0; //ggf. ans Ende
      JETPORT |= (1<<JET2);
    }
    sei();
  }
}




// Encoderinterrupt
ISR(INT4_vect)
{
  if(encoderA_flag == 1)
  {
    selftest_need = 4;
  }
  else
  {
    selftest_need = 0;
  }

  encoderA_flag = 1;

}


// LS1interrupt
ISR(INT5_vect)
{
  if(ls1_flag)
  {
    selftest_need = 1;
  }
  else
  {
    selftest_need = 0;
  }
  ls1_flag = 1;

}

// LS2interrupt
ISR(INT6_vect)
{
  if(ls2_flag)
  selftest_need = 2;

  ls2_flag = 1;

}


Zum Problem:

Wenn ich am Encoderpin (hier PE4) den Encoder anlege lösen meine Trigger 
im Encodertakt aus. Wie gewollt.

Kommentiere ich das Trigger setzen im der Encoderverarbeitung aus, hätte 
ich erwartet wenn ich eine Lichtschranke unterbreche der gewünschte 
Trigger kommt. Lichtschranke 1 PE5 und Lichtschranke 2 PE6.
Ist meine Erwartung bis hier richtig?

Es passiert leider garnix.

Nächste Erwartung:
Wenn ich folgene Änderung mache:
Keine änderung in der Verdrahtung
// Encoderinterrupt
ISR(INT4_vect) -> ISR(INT5_vect)
// LS1interrupt
ISR(INT5_vect) -> ISR(INT4_vect)
// LS2interrupt
ISR(INT6_vect) -> ISR(INT6_vect)

Ich hätte erwartet das jetzt mit dem Encodertakt der Trigger JET1 
ausgelöst wird. Erwartung falsch?

Was passiert: Die Lichtranke 1 löst bei Unterbrechung den Trigger JET1 
aus. Warum?

Nächste Erwartung:
Wenn ich folgene Änderung mache:
Keine änderung in der Verdrahtung
// Encoderinterrupt
ISR(INT4_vect) -> ISR(INT5_vect)
// LS1interrupt
ISR(INT5_vect) -> ISR(INT6_vect)
// LS2interrupt
ISR(INT6_vect) -> ISR(INT4_vect)

Ich hätte erwartet das jetzt mit dem Encodertakt der Trigger JET2 
ausgelöst wird. Oder aber nach dem eben erlebten. Die Lichtranke 2 löst 
bei Unterbrechung den Trigger JET2 aus.  Erwartung falsch?

Was passiert: Die Lichtranke 1 löst bei Unterbrechung den Trigger JET2 
aus. Warum?

Ich kann es mir nicht erklären hat jemand eine Idee warum. Bitte etwas 
ausführlcih erklären ich möchte es verstehen und die Problem in Zukunft 
nicht mehr haben.

von Karl H. (kbuchegg)


Lesenswert?

neuling schrieb:
> Karl H. schrieb:
>> Was machen
>>>
>>>   initInputs();
>>>   initOutputs();
>>>   initStatusLEDs();
>>
>> Die Pullups am Eingang hast du aktiviert?
>
> void initOutputs()
> {
>
>   JETDDR |= (1<<JET1);
>   JETDDR |= (1<<JET2);
>

Und wo sind die Pullups?

von Karl H. (kbuchegg)


Lesenswert?

Bastler schrieb:
> Doch bei dem Testcode.
> Wenn nämlich "funktioniert" bedeutet: "keine Fehler-LED leuchtet" und
> wegen Prellen nach dem RETI nur einen "Hauptschleifenbefehl" ausgeführt
> wird, was nicht reicht um encoderA_flag zu löschen und der nächste Int
> dann schreit "Fehler".

Wie lange dauert bei 14Mhz die Ausfuehrung eines Hauptschleifenbefehls 
und in welchen Zeitrauemen spielt sich Tastenprellen ab?

Alles was ihr angefuehrt habt ist soweit richtig. Nur spielt es in 
seinem Testcode keine Rolle. Sein Eingang ist ohne Pullup und faengt 
sich Stoerungen ein. Ganz einfach

Das muss euch doch selber auffallen, dass da eine enorme Zeitdiskrepanz 
vorliegt. Der AVR hat eine Zykluszeit vun unter 0.1 mikrosekunden. Und 
den willst du mit Kontaktprellen ueberfahren?

Seine Hauptschleife laeuft in geschaetzten 1 Mikrosekunde einmal rum. 
Selbst wenn ich fuer die Isr noch was zugebe, ist das Flag spaetestens 
nach 3 Mikrosekunden wieder geloescht. Und da hab ich schon alles Worst 
Case angenommen und alle Huehneraugen mit zugedrueckt.

: Bearbeitet durch User
von neuling (Gast)


Lesenswert?

Lothar M. schrieb:
> Wie schnell können diese Flanken denn überhaupt wechseln?

Der Encoder häng an einem kleine Föderband welchen über einen Motor 
angetrieben wird. Die Flanken können sich therotisch zwischen 275µs..2ms 
wiederholen. Mich würde ja schon freunen wenn es im oberen Bereich geht.

von neuling (Gast)


Lesenswert?

neuling schrieb:
> CAMPORT &= ~(1<<CAM1);
>     CAMPORT &= ~(1<<CAM2);

Muss natürlich JETPORT heißen

von neuling (Gast)


Lesenswert?

Karl H. schrieb:
> Und wo sind die Pullups?

Ups die sidn beim minimalisieren verschwunden.

von Bastler (Gast)


Lesenswert?

> Seine Hauptschleife laeuft in geschaetzten 1 Mikrosekunde einmal rum.
Selbst wenn ich fuer die Isr noch was zugebe, ist das Flag spaetestens
nach 3 Mikrosekunden wieder geloescht.

Da ist alles valide, nur: wenn er die Hauptschleife per CLI/SEI gegen 
parallele Interrupts verriegelt, dann geht's. Denn dann kommt kein neuer 
Int bevor das Flag gelöscht ist. Solange der "Drehgeber" keinen Namen 
hat, sind die ms nur geschätzt. Und die Indizien sprechen für mehrfache 
INT's in kurzer Zeit. Wie sonst sollte das gepostete Programm sich sonst 
so verhalten. Aber ist nur so meine Idee, darf jeder beliebig anders 
sehen.

von neuling (Gast)


Lesenswert?

Bastler schrieb:
> olange der "Drehgeber" keinen Namen
> hat, sind die ms nur geschätzt.

das ist der verwendete Encoder:
http://www.conrad.de/ce/de/product/198518/Kuebler-Inkremental-Drehgeber-Typ-2400-Vollwelle-Wellen-6-mm-Aufloesung-1024-ImpU-Drehzahl-max-12000-Umin?ref=list

Bastler schrieb:
> Und die Indizien sprechen für mehrfache
> INT's in kurzer Zeit.
Und wie löse ich das am besten?

von Karl H. (kbuchegg)


Lesenswert?

neuling schrieb:
> Bastler schrieb:
>> olange der "Drehgeber" keinen Namen
>> hat, sind die ms nur geschätzt.
>
> das ist der verwendete Encoder:
> 
http://www.conrad.de/ce/de/product/198518/Kuebler-Inkremental-Drehgeber-Typ-2400-Vollwelle-Wellen-6-mm-Aufloesung-1024-ImpU-Drehzahl-max-12000-Umin?ref=list
>
> Bastler schrieb:
>> Und die Indizien sprechen für mehrfache
>> INT's in kurzer Zeit.
> Und wie löse ich das am besten?

IM Grunde indem du überhaupt keinen externen Interrupt benutzt. Wozu 
auch?

Bei den Zeiten, die du hast reicht es einen Timer aufzusetzen, der alle 
paar zig µS den Eingangsport abfragt und dann die Werte mit den jeweils 
vorhergehenden verglicht.
Zb Timer0 (8 Bit Timer), Vorteiler 1 oder 8, in der Overflow ISR das PIN 
Register auslesen und mitzählen wie oft du den gleichen Wert gekriegt 
hast. Hast du 3 oder 4 mal hintereinander den gleichen Wert, dann ist 
der Wert auch real. Ansonsten hast du irgendwelche Spikes am Eingang - 
wo auch immer die herkommen.


Externer Interrupt wird überbewertet. Das hört sich zwar alles nett an, 
sobald man da aber Spikes ausfiltern muss, ist es gleich gar nicht mehr 
so einfach.

Einen Timer hingegen braucht man sowieso in den meisten Programmen. Da 
kann der das dann auch noch gleich mit erledigen.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Bastler schrieb:
>> Seine Hauptschleife laeuft in geschaetzten 1 Mikrosekunde einmal rum.
> Selbst wenn ich fuer die Isr noch was zugebe, ist das Flag spaetestens
> nach 3 Mikrosekunden wieder geloescht.
>
> Da ist alles valide, nur: wenn er die Hauptschleife per CLI/SEI gegen
> parallele Interrupts verriegelt, dann geht's.

Hab ich das überlesen oder wo hast du diesen CLI/SEI her?

> hat, sind die ms nur geschätzt. Und die Indizien sprechen für mehrfache
> INT's in kurzer Zeit.

Das streitet auch keiner ab.
Nur tendiere ich zur einfachsten Erklärung. Im Falle fehlender Pullups 
habe ich die erst mal im Auge, als eine Mechanik, die es schafft mir in 
weniger als 3µs zwei fallende Flanken auf einen Eingang zu legen.

von Bastler (Gast)


Lesenswert?

Cli/sei sind aus der Version, die dann funktioniert haben soll.
Ok, für mich war "mehrfache INT's ohne daß Main das Flag zurücksetzten 
kann" die Krankheit. BTW, der Sensor hat 1μs Flanken, typischer 
(hochohmiger) Bastleraufbau und die mehreren INT's im μs-Bereich sind 
da.

von Peter D. (peda)


Lesenswert?

neuling schrieb:
> das ist der verwendete Encoder:
> 
http://www.conrad.de/ce/de/product/198518/Kuebler-Inkremental-Drehgeber-Typ-2400-Vollwelle-Wellen-6-mm-Aufloesung-1024-ImpU-Drehzahl-max-12000-Umin?ref=list

Die Dinger sind optisch, also prellfrei. Kann man nicht mit schrottigen 
Handencodern für 1% des Preises vergleichen.
Ich würds mit nem Pin-Change-Interrupt auf beide Pins auslesen.

von m.n. (Gast)


Lesenswert?

Peter D. schrieb:
> 
http://www.conrad.de/ce/de/product/198518/Kuebler-Inkremental-Drehgeber-Typ-2400-Vollwelle-Wellen-6-mm-Aufloesung-1024-ImpU-Drehzahl-max-12000-Umin?ref=list
>
> Die Dinger sind optisch, also prellfrei. Kann man nicht mit schrottigen
> Handencodern für 1% des Preises vergleichen.
> Ich würds mit nem Pin-Change-Interrupt auf beide Pins auslesen.

Da liest mal jemand das Datenblatt und wird dadurch gleich zum Verräter 
;-)

@Neuling
In der Codesammlung stehen einige Beispiele, wie man solche Drehgeber 
entweder mit INT0/INT1 oder PCINT auswertet. Es ist recht einfach und 
geht locker bis in den zig kHz-Bereich.
Beitrag "Drehgeber per Interrupt auswerten, AVR"
Beitrag "Schrittmotor als Drehgeber mit Dynamik, AVR"

von neuling (Gast)


Lesenswert?

Peter D. schrieb:
> Ich würds mit nem Pin-Change-Interrupt auf beide Pins auslesen.

Da wäre jetzt auch meine Idee gewesen.
Wenn ich das richtig verstanden habe lege ich Phase A des Encoders an 
den ICP3-PIN (PE7).

Setze dann im TCCR3 Register mit Cs00..CS02 Steigende oder fallende 
Flanke.
Im TCCR3B kann ich dir Rauschunterdrückeung über ICNC3 aktivieren.

In ISR(ICF3) Frage ich jetzt bei Pins ab und habe die Drehrichtung. Kann 
mein Flag setzen und in der main den Rest machen und das Flag zurück 
setzen.


Ist das so richtig? Oder habe ich das Falsch verstanden?

von reto (Gast)


Lesenswert?

neuling schrieb:
> Ist das so richtig? Oder habe ich das Falsch verstanden?

Das ist richtig.

von neuling (Gast)


Lesenswert?

Mein Code dazu sieht wie folgt aus:

#include "allHeader.h"
volatile uint8_t selftest_need = 0;
volatile uint8_t encoderA_flag = 0;


int main()
{

  initInputs();
  initOutputs();
  initStatusLEDs();



  TCCR3B |= (1<<ICNC3);

  TCCR3C |= (1<<CS30);
  TCCR3C |= (1<<CS31);
  TCCR3C |= (1<<CS32);
  ETIMSK |= (1<<TICIE3);

  sei();
  while(1)
  {  LEDPORT = selftest_need;
      JETPORT &= ~(1<<JET1);
      JETPORT &= ~(1<<JET2);

      cli();
      if(encoderA_flag)
      {
        encoderA_flag = 0; //ggf. ans Ende
        JETPORT |= (1<<JET1);
        JETPORT |= (1<<JET2);

      }

      sei();

  }
}
// Encoderinterrupt

ISR(INT7_vect)
{
  if(encoderA_flag == 1)
  {
    selftest_need = 4;
  }

  encoderA_flag = 1;

}

Jetzt löst der jeder Takt einen Reset aus. Ich verstehe nur nicht warum.

von neuling (Gast)


Lesenswert?

neuling schrieb:
> Jetzt löst der jeder Takt einen Reset aus. Ich verstehe nur nicht warum.

ok das lag an der Fehlenden Zeile
  EIMSK |= (1<<INT7);

Jetzt habe ich alt bekanntes Problem das. Das Interrupt nicht bearbeiter 
wird und die FehlerLED wieder 4 anzeigt. Sollte die Funktion nicht gnau 
das verhindern?

von Peter D. (peda)


Lesenswert?

neuling schrieb:
> Wenn ich das richtig verstanden habe lege ich Phase A des Encoders an
> den ICP3-PIN (PE7).

Will man die höchste Auflösung, muß jeder Zustandswechel gezählt werden. 
Also beide Anschlüsse als Pin-Change und dann die Zählroutine, wie im 
Timerinterrupt für manuelle Encoder.
Timerinterrupt wäre bei der Pulszahl doch recht hohe Interruptlast.

von neuling (Gast)


Lesenswert?

Peter D. schrieb:
> Will man die höchste Auflösung, muß jeder Zustandswechel gezählt werden.

Mir reicht die Auflösung von einem

Peter D. schrieb:
> Will man die höchste Auflösung, muß jeder Zustandswechel gezählt werden.
> Also beide Anschlüsse als Pin-Change und dann die Zählroutine, wie im
> Timerinterrupt für manuelle Encoder.
> Timerinterrupt wäre bei der Pulszahl doch recht hohe Interruptlast.

Wo lege ich dann Phase B an?

Die Frage die ich mir stelle warum verarbeite er das Interrupt nicht 
sauber? Es muss doch möglich sein über eine einfache ISR nur die 
fallenden Flaken zu erkennen und dann was zu machen.

Ich würde mich sehr freuen wenn mir jemand an meinem Code helfen könnte 
das zum laufen zu bekommen.

von Bastler (Gast)


Lesenswert?

Wie sieht denn der Aufbau aus, und wie sieht das Signal direkt am Pin 
aus. Sind das schöne Rechtecke oder wegen "hochohmig abgeschlossener" 
langer Kabel an den Flanken ausklingende n MHz Schwingungen. Irgendwie 
scheint es ja manchmal zu INT's im Abstand kleiner als 1-stellige μs zu 
kommen und das macht der AVR ja nicht ohne Grund.
Ich schalte gern zum Testen am Anfang einer ISR ein Pin und am Ende 
wieder zurück. 10€ LA dran und man sieht sofort, ob man wirklich mehrere 
INT's hat. Der bisherige "Versuchsaufbau" läst das nur vermuten. Messen 
ist besser!
Dieses LA Vorgehen zeigt aus schon graphisch die CPU-Last, wenn in der 
main-Schleife wenn's nix mehr zu tun gibt kurz bis zum nächsten Int 
schläft, und um dieses sleep herum ein Pin toggled. Bleibt "Sleep" lange 
genug an, dann ist alles im grünen Bereich. Einfacher als Takte 
addieren.

von OldMan (Gast)


Lesenswert?

Der Hersteller, Fa. Kübler, gibt an, dass die Ausgänge der Drehgeber mit 
einer Mindestlast von 1 kOhm betrieben werden sollen. Hast Du daran 
gedacht?
Siehe dieses Dokument:
https://www.kuebler.com/PDFs/kataloge_publikationen/Grundlagen-Drehgeber-2011-DE.pdf

von neuling (Gast)


Lesenswert?

OldMan schrieb:
> Der Hersteller, Fa. Kübler, gibt an, dass die Ausgänge der Drehgeber mit
> einer Mindestlast von 1 kOhm betrieben werden sollen. Hast Du daran
> gedacht?

Ja habe ich berücksichtigt.


Mit folgendem Code im Interrupt :
1
// Encoderinterrupt
2
3
ISR(INT7_vect)
4
{
5
        JETPORT |= (1<<JET1);
6
  delay_us(500);
7
  JETPORT &= ~(1<<JET1);
8
  if(ls1_flag)
9
  {
10
    selftest_need = 1;
11
  }
12
  else
13
  {
14
    selftest_need = 0;
15
  }
16
  ls1_flag = 1;
17
  
18
  
19
  if(encoderA_flag == 1)
20
  {
21
    selftest_need = 4;
22
  }
23
24
  encoderA_flag = 1;
25
26
}

Sehe ich bei const Low am InterruptPin am Jet1Pin Alle 50Hz die 50us als 
High. Ziehe ich das Netzteil aus der Steckdose sind die 50Hz weg. Kann 
das mein Problem sein?

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


Lesenswert?

neuling schrieb:
> Mit folgendem Code
Könntest du bitte mal die Bedienungsanleitung ein paar Zeilen über der 
Eingabebox lesen? Dort steht:
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
3
:
4
:
5
Formatierung (mehr Informationen...)
6
    [c] C-Code [/c]
Probiers aus.

: Bearbeitet durch Moderator
von dunno.. (Gast)


Lesenswert?

Spätestens jetzt wäre dann der Zeitpunkt, an dem ein Schaltplan, eine 
Erklärung des Aufbaus, und ggfs. ein Foto des selben nötig sind. Dabei 
bitte die Hinweise zu Bildformaten und Größen beachten..

von m.n. (Gast)


Lesenswert?

dunno.. schrieb:
> Spätestens jetzt wäre dann der Zeitpunkt,

Ich glaube, Du erwartest zu viel, denn:

neuling schrieb:
> Ich möchte Encoder gesteuert einige Funktionen ausführen.
neuling schrieb:
> Der Encoder häng an einem kleine Föderband welchen über einen Motor
> angetrieben wird.

Was denn nun?

neuling schrieb:
> Ich würde mich sehr freuen wenn mir jemand an meinem Code helfen könnte
> das zum laufen zu bekommen.

Ich habe mir Deinen Code nur oberflächlig angesehen. Warum, weil er 
keinen Sinn ergibt. Ich denke, das geht nicht nur mir so.
Erwarte nicht, daß ein undurchsichtiger Ansatz eines unbekannten 
Problems hier zu glänzender Funktion geführt wird.

Erkläre doch zunächst, wie Dein Drehgeber verwendet werden soll, und 
lese auch die Links, die Dir genannt wurden.

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


Lesenswert?

m.n. schrieb:
> und lese auch die Links, die Dir genannt wurden.
Und versuche, sie zu verstehen.
Und wenn dann was nicht klar ist: nachdenken, überlegen und evtl. 
fragen.

neuling schrieb:
> Ziehe ich das Netzteil aus der Steckdose sind die 50Hz weg.
> Kann das mein Problem sein?
Welches Netzteil?
Das ist ja wieder mal grausame Salamitaktik hier...
Aus https://de.wikipedia.org/wiki/Salamitaktik:
1
Eine weitere Verwendung für Salamitaktik beschreibt die Vorgehensweise, 
2
die Wahrheit nur scheibchenweise zu "servieren". Eine in Bedrängnis geratene 
3
Person, verrät nur so viel von ihrem (vermeintlichen) rechtlichen oder 
4
moralischen Fehlverhalten, wie ihr bereits nachgewiesen werden kann oder 
5
wie sie es für als taktisch sinnvoll erachtet.[6]
6
7
Im Zusammenhang mit Software- oder Hardwareprojekten wird unter Salamitaktik 
8
das unerwünschte Verhalten des Kunden bezeichnet, immer wieder neue 
9
Anforderungen an ein Projekt zu stellen. Die Situation ist in diesem Fall 
10
gekennzeichnet durch mangelhafte Planung und unkoordinierte sowie 
11
fehleranfällige Umsetzung.

von OldMan (Gast)


Lesenswert?

neuling schrieb:
> Ja habe ich berücksichtigt.
>
> Mit folgendem Code im Interrupt :

Was hat Dein Code mit meinem Hinweis bzgl. der Last für den Drehgeber zu 
tun?
Langsam bin ich der Meinung, dass Du überhaupt nicht verstehst was Du 
tust.

von problem (Gast)


Lesenswert?

>Sehe ich bei const Low am InterruptPin am Jet1Pin Alle 50Hz die 50us als
>High. Ziehe ich das Netzteil aus der Steckdose sind die 50Hz weg. Kann
>das mein Problem sein?

Dein Problem liegt ganz wo anders.

Was willst du?
Was machst du?
Warum machst du es so?
Wieso im Interrupt ein delay?

Zeig uns den Aufbau!
Zeig uns den Code!
Sag was nicht geht!

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.