Forum: Mikrocontroller und Digitale Elektronik Eigenartiges Verhalten bei Interrupts (Arduino)


von Soder D. (soderdaen)


Lesenswert?

Hallo zusammen,

ich habe ein Problem mit den externen Interrupts beim Arduino.
Folgendes: Ich habe ein Sinussignal aus einem Funktionsgenerator, bei 
dem die negativen Halbwellen mit einer Diode herausgeschnitten werden, 
an den externen Interrupt Pin des Arduino angeschlossen. Mit dem Arduino 
möchte ich interruptgesteuert sowohl bei steigender als auch fallender 
Flanke eine Routine ausführen. D.h. im Nulldurchgang vor und nach der 
positiven Sinushalbwelle.
Mit dem Oszi habe ich aber etwas eigenartiges entdeckt. Der Interrupt 
für die steigende Flanke wird im Hochpunkt des Sinus gestartet und für 
die fallende Flanke kurz nach dem Hochpunkt, also nicht im 
Nulldurchgang.
Um Fehler im Programm auszuschließen habe ich mal nur auf die steigende 
Flanke geschaut und den Rest im Programm entfernt. Und selbiges Spiel. 
Das dürfte doch eigentlich gar nicht sein, woran kann das liegen?
Die Interruptroutine ist kurz (nen Pin auf High schalten), die Frequenz 
des Funktionsgenerators liegt zwischen 10 und 50Hz.

Hier der Programmcode, nur für die steigende Flanke:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <math.h>
4
#define F_CPU 16000000UL
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
8
void interrupt_init();
9
int main(void)
10
{
11
  DDRB   |= (1<<DDB4);  // LED
12
  DDRD   &= ~(1<<DDD2);  // ZeroCross Detection PIN
13
  interrupt_init();
14
  while (1)
15
    {
16
      PORTB |= (1<<DDB4);
17
    }
18
}
19
20
ISR(INT0_vect)
21
{
22
  PORTB &= ~(1<<DDB4);
23
};
24
25
void interrupt_init()
26
{
27
  EICRA |= (1<<ISC01);  // Interrupt konfigurieren
28
  EICRA |= (1<<ISC00);
29
  EIMSK |= (1<<INT0);
30
  EIFR  |= (1<<INTF0);    
31
  sei();          // Globale Interrupts freigeben
32
}

von Oliver S. (oliverso)


Lesenswert?

Eins und Null sind so herrlich digitale Werte, die Welt und auch dein 
Prozessor sind aber dann doch irgendwie analog. Was Null und was eins 
tatsächlich ist, steht im Datenblatt.

Um das Problem zu lösen, hat der Prozessor extra einen Komparator 
spendiert bekommen, genau für solche Aufgabenstellungen. Schau dir den 
mal an.

Oliver

von Wolfgang (Gast)


Lesenswert?

Soder D. schrieb:
> Der Interrupt für die steigende Flanke wird im Hochpunkt des Sinus
> gestartet und für die fallende Flanke kurz nach dem Hochpunkt, also
> nicht im Nulldurchgang.

Wenn du die Amplitude deines Sinussignals erhöhst, werden die Zeitpunkt 
auseinanderrücken. Aber Achtung: Das Signal am µC-Eingang darf VDD nur 
wenig übersteigen - also Schutzschaltung nicht vergessen, z.B. wie in 
der Atmel App-Note AVR182

> Das dürfte doch eigentlich gar nicht sein, woran kann das liegen?

Warum dürfte das nicht sein. In ihrem tiefen Inneren sind die Eingänge 
von µC auch nur nichtlineare Analogschaltungen mit einer 
Übertragungskennlinie. Ein paar Kennwerte zu den Schaltschwellen stehen 
im Datenblatt des auf dem Arduino Board verbauten Mikrocontrollers.

von Soder D. (soderdaen)


Lesenswert?

Wolfgang schrieb:

> Wenn du die Amplitude deines Sinussignals erhöhst, werden die Zeitpunkt
> auseinanderrücken. Aber Achtung: Das Signal am µC-Eingang darf VDD nur
> wenig übersteigen - also Schutzschaltung nicht vergessen, z.B. wie in
> der Atmel App-Note AVR182

Ja, daran meine ich mich noch von den Tests heute erinnern zu können, 
bringt mir natürlich nicht. Ich muss quasi im Spannungsanstieg unter 
einer ms einen Ausgang schalten. Im Datenblatt habe ich Figure 13-1 auf 
seite 70 gefunden, danach sollte das Flag nach knapp über 3 Takten clk 
aktualisiert werden (250ns). Bis die Routine fertig ausgeführt ist bin 
ich noch weit weg vom ms-Bereich. Zur Höhe, ab der eine steigende oder 
fallende Flanke erkannt wird, konnte ich auf die schnelle nichts im 
Datenblatt finden. Da man aber eh nicht mehr als 5V an den Pin anlegen 
sollte und 50 Hz für nen 16Mhz Prozessor nicht die Welt ist erwarte ich 
eigentlich schon, dass man da weit unter ner Millisekunde bleibt. Man 
möge mich hier gerne verbessern.


Die Appnote kenne ich im Übrigen und die Schaltung wird auch so ähnlich 
aufgebaut, aber zum testen ist mir persönlich der Funktionsgenerator 
erst mal lieber als mit 230V zu arbeiten.

von Max M. (jens2001)


Lesenswert?

Soder D. schrieb:
> Zur Höhe, ab der eine steigende oder
> fallende Flanke erkannt wird, konnte ich auf die schnelle nichts im
> Datenblatt finden.

Aber dir ist schon klar dass es sich un DIGITAL-Eingänge handelt?

von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> Ich muss quasi im Spannungsanstieg unter
> einer ms einen Ausgang schalten.

Lt. Datenblat S. 313 erkennt der ATMega328P high (bei Vcc 2,4 - 5,5 V) 
ab 0,6 * Vcc -> bei 5V also ab 3 V.

Aber da hatten auch andere schon Probleme mit

Beitrag "Schaltschwelle bei Atmega digital Eingang"

von Walter S. (avatar)


Lesenswert?

Soder D. schrieb:
> Der Interrupt
> für die steigende Flanke wird im Hochpunkt des Sinus gestartet und für
> die fallende Flanke kurz nach dem Hochpunkt, also nicht im
> Nulldurchgang.

ist für dich Hochpunkt==Nulldurchgang?
Welche Spannung liefert der Generator?

von Soder D. (soderdaen)


Lesenswert?

Walter S. schrieb:
> Soder D. schrieb:
>> Der Interrupt
>> für die steigende Flanke wird im Hochpunkt des Sinus gestartet und für
>> die fallende Flanke kurz nach dem Hochpunkt, also nicht im
>> Nulldurchgang.
>
> ist für dich Hochpunkt==Nulldurchgang?
> Welche Spannung liefert der Generator?

Ne Hochpunkt ist für mich der Punkt, an dem der Sinus den maximalen Wert 
hat, also Vmax, Vpeak, mathematisch gesehen wo die Steigung null ist. 
Hoff das ist klar geworden was ich unter Hochpunkt verstehe.

Die Spannung des Generators stelle ich ein, ab etwa 3Vpp (mit dem Oszi 6 
Vpp) erkennt der Pin überhaupt erst den Interrupt bzw. die steigende 
Flanke, bei ca. 2Vpp (eingestellt, im Oszi 4Vpp) reagiert der Pin gar 
nicht und es wird kein Interrupt ausgeführt.

von Max M. (jens2001)


Lesenswert?

Einen Sinus an einen Digileingang legen und erwarten dass das was 
sinnvolles ergibt!
Auf so einen Blödsinn muss man erstmal kommen!

von Sebastian S. (amateur)


Lesenswert?

Spendier' uns doch mal eine Skizze des "Analogteils".

Zum einen sind Dioden nicht Symmetrisch, zum anderen ist die Definition 
(elektrisch) von Null und Eins mit einer kräftigen Hysterese versehen.

Also anders herum wird für mich ein Schuh daraus: Es würde mich wundern, 
wenn da was Symmetrisches herauskäme.

von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> etwa 3Vpp (mit dem Oszi 6
> Vpp) erkennt der Pin überhaupt erst den Interrupt

Dieter F. schrieb:
> Lt. Datenblat S. 313 erkennt der ATMega328P high (bei Vcc 2,4 - 5,5 V)
> ab 0,6 * Vcc -> bei 5V also ab 3 V.

Passt.

von Max D. (max_d)


Lesenswert?

Tipp für frühzeitiges triggern:
Sinus über einen Kondensator auf den kurz vor die Schltschwelle 
vorgespannten (mit einem Poti und Fingerspitzengefühl) Eingang legen.
Wie nah du an die Schwelle kannst bevor eine Temperaturänderung schon 
triggered musst du selber erporoben.

von Felix Adam (Gast)


Lesenswert?

Ernsthaft, der beste Tipp wurde schon oben gegeben: nimm den 
AnalogKomparator. Dafür ist der da.

von Route_66 H. (route_66)


Lesenswert?

Hallo!
Es geht wohl um die Nulldurchgangserkennung. Darüber wurde hier schon 
Seitenweise geschrieben.
Einfach nur suchen!

von Walter S. (avatar)


Lesenswert?

Soder D. schrieb:
>> ist für dich Hochpunkt==Nulldurchgang?
>> Welche Spannung liefert der Generator?
>
> Ne Hochpunkt ist für mich der Punkt, an dem der Sinus den maximalen Wert
> hat, also Vmax, Vpeak, mathematisch gesehen wo die Steigung null ist.

und warum sollte der Interrupt deiner Meinung nach im Nulldurchgang 
kommen?
Du hast einen Digitaleingang der nicht bei 0 und Vcc, sondern bei 
bestimmten Spannungen schaltet.
Das wurde auch mehrfach erwähnt aber du verstehst es scheinbar nicht

von Michael U. (amiga)


Lesenswert?

Hallo,

daß ein mit 5V betriebener AVR bei rund 3V sucher H erkennt, wurde schon 
erwähnt.
Im Datenblatt steht auch, unterwelcher Schwelle er sicher L erkennt.
Prktisch liegt die Schaltschwelle irgendwo um Ub/2, als bei ca, 2,5V. 
Der Eingang hat Triggerverhalten, die Schaltschwellle von H auf L liegt 
also etwas drunter. Etwas sind vielleicht 200mV unter diesen Umständen. 
Ist exemplarabhängig, sicher auch temperaturabhängig. Interessiert real 
niemanden, da der Bereich bei einer digitalen Flanke sehr schnell 
durchlaufen wird.

Mal Dir Deine Sinsuhalbwelle auf. Kennzeichne Dir den Punkt 2,6V auf der 
steigenden Seite und 2,4V auf der fallenden Seite. Mach das für Deine 
Generatorspannungen im Maßstab.
Mal es Dir auch für einen 220V-Sinus auf.
Du wirst sehen, daß der AVR alles richtig macht.
Bei 220V ist der Bereich von 0 auf 2,6V auf der steigenden und der von 
2,4V auf 0V auf der fallenden Seite sehr klein, die Spannungsänderung um 
den Nullpunkt nahezu senkrecht. Damit klappt der Trick aus der AppNote.

Mit kleinen Sinusspannungen kann es so nicht gehen.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Soder D. (soderdaen)


Lesenswert?

Walter S. schrieb:
> Soder D. schrieb:
>>> ist für dich Hochpunkt==Nulldurchgang?
>>> Welche Spannung liefert der Generator?
>>
>> Ne Hochpunkt ist für mich der Punkt, an dem der Sinus den maximalen Wert
>> hat, also Vmax, Vpeak, mathematisch gesehen wo die Steigung null ist.
>
> und warum sollte der Interrupt deiner Meinung nach im Nulldurchgang
> kommen?
> Du hast einen Digitaleingang der nicht bei 0 und Vcc, sondern bei
> bestimmten Spannungen schaltet.
> Das wurde auch mehrfach erwähnt aber du verstehst es scheinbar nicht

Wow Walter S.
Da fragt man !!!!!EIN!!!!EINZIGES!!!! mal nach und man wird beschuldigt 
es nicht zu verstehen. Großartiges Menschenverständnis haben Sie da 
vorzuweisen, wenn doch nur alle so wären. Achja, an einem Analogeingang 
kommt der Interrupt genau so spät. Das sollten Sie doch wissen ?!
Hier werden leider zu viele nichtsaussagende Postings gemacht, 
hauptsache meckern, aber keine Vorschläge bringen. Chapeau!

Bedanken möchte ich mich aber an die anderen, die meine Fragen 
freundlich beantworten und Lösungshinweise geben. Besonderen Dank an 
Michael B. aus Berlin. Deine Erklärung macht natürlich Sinn. Da ich aber 
längstmöglich ohne 230V testen möchte habe ich schonmal angefangen da 
was zu Basteln. Bisher ist reagiert der Komparator perfekt, aber leider 
zu genau. Man kann die Hystere zwar auf 1,1V setzen, aber da verstreicht 
dann doch wieder zu viel Zeit.

von Wolfgang (Gast)


Lesenswert?

Soder D. schrieb:
> Man kann die Hystere zwar auf 1,1V setzen, aber da verstreicht
> dann doch wieder zu viel Zeit.

Wieso verstreicht dann ZU VIEL ZEIT?

Der Generator gibt doch hoffentlich ein periodisches Signal ab, d.h. bei 
bekannter Verzögerung zwischen Nulldurchgang und Trigger kann man sich 
ziemlich genau ausrechnen, wann der nächste Nulldurchgang kommt. Das ist 
das ganze Geheimnis. Der Jitter vom Nulldurchgang der Netzfrequenz ist 
zu vernachlässigen, wenn das Netz nicht allerübelst gestört ist.

von Soder D. (soderdaen)


Lesenswert?

Wolfgang schrieb:
> Soder D. schrieb:
>> Man kann die Hystere zwar auf 1,1V setzen, aber da verstreicht
>> dann doch wieder zu viel Zeit.
>
> Wieso verstreicht dann ZU VIEL ZEIT?
>
> Der Generator gibt doch hoffentlich ein periodisches Signal ab, d.h. bei
> bekannter Verzögerung zwischen Nulldurchgang und Trigger kann man sich
> ziemlich genau ausrechnen, wann der nächste Nulldurchgang kommt. Das ist
> das ganze Geheimnis. Der Jitter vom Nulldurchgang der Netzfrequenz ist
> zu vernachlässigen, wenn das Netz nicht allerübelst gestört ist.

Stimmt, das ist liese sich so schon mit dem Funktionsgenerator machen.
Wenn der aber mal weg ist kommt leider ein nicht ganz so sauberes 
Signal.

von Wolfgang (Gast)


Lesenswert?

Soder D. schrieb:
> Wenn der aber mal weg ist kommt leider ein nicht ganz so sauberes
> Signal.

Immerhin gibt es Tiefpassfilter, die einen Haufen höherfrequenter 
Störungen vom Komparator fernhalten können.

von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> Da ich aber
> längstmöglich ohne 230V testen möchte habe ich schonmal angefangen da
> was zu Basteln. Bisher ist reagiert der Komparator perfekt, aber leider
> zu genau. Man kann die Hystere zwar auf 1,1V setzen, aber da verstreicht
> dann doch wieder zu viel Zeit.

Kannst Du mal vorstellen, wie Du das machst? Das wäre wirklich 
interessant.

von Soder D. (soderdaen)


Lesenswert?

Dieter F. schrieb:
> Soder D. schrieb:
>> Da ich aber
>> längstmöglich ohne 230V testen möchte habe ich schonmal angefangen da
>> was zu Basteln. Bisher ist reagiert der Komparator perfekt, aber leider
>> zu genau. Man kann die Hystere zwar auf 1,1V setzen, aber da verstreicht
>> dann doch wieder zu viel Zeit.
>
> Kannst Du mal vorstellen, wie Du das machst? Das wäre wirklich
> interessant.

Was meinst du genau?
Komm erst wieder Montag dazu mich genauer damit zu beschäftigen.

von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> Was meinst du genau?

Soder D. schrieb:
> Bisher ist reagiert der Komparator perfekt, aber leider
> zu genau. Man kann die Hystere zwar auf 1,1V setzen, aber da verstreicht
> dann doch wieder zu viel Zeit.

Ich verstehe schlicht nicht, wie der Komparator zu genau sein kann und 
wieso bei einer kleinen Hysterese dann doch zuviel Zeit verstreicht. Du 
kannst doch immer vom entsprechenden Trigger-Zeitpunkt aus den 
Nulldurchgang berechnen - oder liege ich da komplett falsch?

von Soder D. (soderdaen)


Lesenswert?

> Ich verstehe schlicht nicht, wie der Komparator zu genau sein kann
Weil dem Oszibild nach der Komparator den Interrupt auch während der 
negativen (abgeschnittenen) Halbwelle ständig auslöst.

> wieso bei einer kleinen Hysterese dann doch zuviel Zeit verstreicht. Du
> kannst doch immer vom entsprechenden Trigger-Zeitpunkt aus den
> Nulldurchgang berechnen - oder liege ich da komplett falsch?

Die Spannungsmessung später im Betrieb wird schwankende Spannungen im 
Bereich 0-300V effektiv messen und auch die Frequenz wird Schwankungen 
unterliegen ca. +- 2 Hz.

von Soder D. (soderdaen)


Angehängte Dateien:

Lesenswert?

Ich konnte wieder etwas testen, der Komparator arbeitet nicht so wie ich 
mir das genau vorstelle, habe ich ihn falsch eingestellt?
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <math.h>
4
#define F_CPU 16000000UL
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#define BAUDRATE 9600
8
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
9
10
void comparator_init();
11
12
int main(void)
13
{  
14
  DDRD   &= ~(1<<DDB7);
15
  DDRB   |=  (1<<DDB5);
16
  comparator_init();
17
  while (1)
18
    {
19
      _delay_ms(1);
20
      PORTB &= ~(1<<DDB5);    
21
    }
22
}
23
24
25
ISR(ANALOG_COMP_vect)
26
{
27
  PORTB |= (1<<DDB5);
28
};
29
30
31
void comparator_init()
32
{
33
  ACSR = 0B01011011;
34
  sei();    
35
}

Der Delay ist drinnen, weil das Oszi sonst die Peaks nicht rauslesen 
kann.
Der Komparator sollte eigentlich auf die steigende Flanke anspringen, 
springt aber auch auf die fallende Flanke an, oder gar nicht, oder eben 
beide...

: Bearbeitet durch User
von Walter S. (avatar)


Lesenswert?

Soder D. schrieb:
> Der Delay ist drinnen, weil das Oszi sonst die Peaks nicht rauslesen
> kann.

und wenn du den delay noch größer machst wirst du sogar noch mehr Peaks 
sehen ..

von vn nn (Gast)


Lesenswert?

Soder D. schrieb:
> Achja, an einem Analogeingang
> kommt der Interrupt genau so spät.

Offensichtlich hast du nicht verstanden, was der ADC macht.

Soder D. schrieb:
> Da fragt man !!!!!EIN!!!!EINZIGES!!!! mal nach und man wird beschuldigt
> es nicht zu verstehen.

Zurecht. An 230V basteln, aber Vertändnis = 0.

von Soder D. (soderdaen)


Lesenswert?

Walter S. schrieb:
> Soder D. schrieb:
>> Der Delay ist drinnen, weil das Oszi sonst die Peaks nicht rauslesen
>> kann.
>
> und wenn du den delay noch größer machst wirst du sogar noch mehr Peaks
> sehen ..

Hab das mal ausprobiert, weder bei längeren noch bei kürzeren Delays 
gibt es großartige Unterschiede.

Könntest du mir noch erklären, wie du auf deine Schlussfolgerug gekommen 
bist?


> Offensichtlich hast du nicht verstanden, was der ADC macht.

Erklärs mir doch dann.

> Soder D. schrieb:
>> Da fragt man !!!!!EIN!!!!EINZIGES!!!! mal nach und man wird beschuldigt
>> es nicht zu verstehen.
>
> Zurecht. An 230V basteln, aber Vertändnis = 0.

Wie gesagt arbeite ich nicht an 230V. Später möglicherweise und dann 
unter Aufsicht. Vielleicht beruhigt dich das und du kannst mir bei einer 
heißen Tasse Kaffee erklären wie ich den Komparator richtig einstelle.

von Walter S. (avatar)


Lesenswert?

Soder D. schrieb:
>> und wenn du den delay noch größer machst wirst du sogar noch mehr Peaks
>> sehen ..
>
> Hab das mal ausprobiert, weder bei längeren noch bei kürzeren Delays
> gibt es großartige Unterschiede.
>
> Könntest du mir noch erklären, wie du auf deine Schlussfolgerug gekommen
> bist?

ich vermute dass das Oszi zu langsam abtastet und du damit nicht alle 
Peaks mitbekommst, deshalb mal mit 50ms delay probieren.
dass der Interrupt auf beide Flanken reagiert könnte an deinem 
Eingangssignal liegen, wenn da Störungen drauf sind können auch bei 
fallendem Sinus steigende Flanken da sein

Ist das gelbe Signal am Eingang des Comparators?

: Bearbeitet durch User
von Soder D. (soderdaen)


Angehängte Dateien:

Lesenswert?

> ich vermute dass das Oszi zu langsam abtastet und du damit nicht alle
> Peaks mitbekommst, deshalb mal mit 50ms delay probieren.
> dass der Interrupt auf beide Flanken reagiert könnte an deinem
> Eingangssignal liegen, wenn da Störungen drauf sind können auch bei
> fallendem Sinus steigende Flanken da sein
>
> Ist das gelbe Signal am Eingang des Comparators?

Im Anhang das Bild mit 50ms als Delay. Da wird wohl der ein oder andere 
Interrupt verschluckt worden sein.

Gelb ist das Ausgangssignal vom Signalgenerator (Agilent 33250A), blau 
ist greife ich am Pin ab.

von Walter S. (avatar)


Lesenswert?

Soder D. schrieb:
> Im Anhang das Bild mit 50ms als Delay. Da wird wohl der ein oder andere
> Interrupt verschluckt worden sein.
ist etwas ungeschickt jedesmal mit einer anderen Frequenz zu arbeiten,
die 50ms bezogen sich auf das vorherige Oszillogramm,
jetzt würden die 1ms durchaus passen


>
> Gelb ist das Ausgangssignal vom Signalgenerator (Agilent 33250A), blau
> ist greife ich am Pin ab.
und was liegt am mega an welchem Pin an?

von Soder D. (soderdaen)


Angehängte Dateien:

Lesenswert?

Walter S. schrieb:
> Soder D. schrieb:
>> Im Anhang das Bild mit 50ms als Delay. Da wird wohl der ein oder andere
>> Interrupt verschluckt worden sein.
> ist etwas ungeschickt jedesmal mit einer anderen Frequenz zu arbeiten,
> die 50ms bezogen sich auf das vorherige Oszillogramm,
> jetzt würden die 1ms durchaus passen
>
>
>>
>> Gelb ist das Ausgangssignal vom Signalgenerator (Agilent 33250A), blau
>> ist greife ich am Pin ab.


Stimmt schon, Spiel hier nur mit allen Parametern rum um auf irgendein 
Ergebnis zu kommen.
Im Anhang deshalb nochmal zwei Oszillogramme mit 50Hz.
Im ersten Bild ist der Komparator folgendermaßen eingestellt:
MIT Band Gap
STEIGENDE FLANKE

Im zweiten Bild so:
OHNE Band Gap
Steigende Flanke


> und was liegt am mega an welchem Pin an?
Meinst du am Arduino Mega? Ich benutze zwar den Uno, aber am Pin ist nur 
ne LED + Vorwiderstand dran.


1
#include <avr/io.h>
2
#include <stdlib.h>
3
#define F_CPU 16000000UL
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
7
8
void comparator_init();
9
10
int main(void)
11
{
12
  DDRD   &= ~(1<<DDD6);
13
  DDRD   &= ~(1<<DDD7);
14
  DDRB   |=  (1<<DDB5);
15
  comparator_init();
16
  while (1)
17
  {
18
    _delay_us(10);
19
    PORTB &= ~(1<<DDB5);
20
  }
21
}
22
23
24
ISR(ANALOG_COMP_vect)
25
{
26
  PORTB |= (1<<DDB5);
27
};
28
29
30
void comparator_init()
31
{
32
  ADCSRB &= ~(1<<ACME);
33
  ACSR   |=  (1<<ACBG);
34
  ACSR   |=  (1<<ACI);
35
  ACSR   |=  (1<<ACIE);
36
  ACSR   |=  (1<<ACIS1);
37
  ACSR   |=  (1<<ACIS0);
38
  sei();          // Globale Interrupts freigeben
39
}

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

In welchem zeitlichen Zusammenhang soll eigentlich das delay() zu dem 
Interrupt stehen?

Wenn vor dem delay() ein sleep() kommt, dann wartet die Hauptschleife 
auf einen Interrupt, da eventuell von Libs noch andere laufen sollte 
noch geprüft werden, ob der "DebugPin" tatsächlich auf 1 ist, wartet n 
μs und setzt das Signal zurück. So gibt das definierte Impulse, wobei 
natürlich Interrupts während der Wartezeit verschickt werden.

 So wie bisher gelöst, kann ein "DebugPuls" von 0,5..10μs jeden Wert 
annehmen. Denn kurzen z.B. wenn der Interrupt genau am Ende eines 
delay() auftritt.

von Walter S. (avatar)


Lesenswert?

Soder D. schrieb:
> Stimmt schon, Spiel hier nur mit allen Parametern rum um auf irgendein
> Ergebnis zu kommen.
> Im Anhang deshalb nochmal zwei Oszillogramme mit 50Hz.
dann bleib jetzt mal bei den 50Hz und stell 1 ms delay ein

> Im ersten Bild ist der Komparator folgendermaßen eingestellt:
> MIT Band Gap
> STEIGENDE FLANKE
>
> Im zweiten Bild so:
> OHNE Band Gap
> Steigende Flanke
ein Komparator hat zwei Eingänge, an den einen legst du sinnvollerweise 
als Rferenz die Bandgap (überleg mal was im zweiten Bild anliegt und 
warum das Ergebnis so aussieht)

>
>> und was liegt am mega an welchem Pin an?
> Meinst du am Arduino Mega? Ich benutze zwar den Uno, aber am Pin ist nur
> ne LED + Vorwiderstand dran.
die LED interessiert doch nicht, interessant ist wo das Signal am 
Prozessor anliegt und wie es an DIESER Stelle aussieht

und bau den Hinweis von Carl ein:
im main warten bis der PIN gesetzt ist, dann 1ms warten und dann erst 
pin zurücksetzen

Fehlersuche ist ein essentieller Teile von Hard- und 
Softwareentwicklung,
das geht nicht durch rumprobieren sondern durch systematisches Vorgehen

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Stell mal bitte Deinen Komparator auf "Toggle" ein - OHNE BANDGAP - und 
lege AIN1 an GND und AIN0 an Dein Signal. Dann brauchst DU auch kein 
Delay, um den Pin-Toggle aus der ISR zu erkennen :-)
1
void comparator_init()
2
{
3
//  ADCSRB &= ~(1<<ACME);
4
//  ACSR   |=  (1<<ACBG);
5
  ACSR   |=  (1<<ACI);
6
  ACSR   |=  (1<<ACIE);
7
  ACSR   &=  ~(1<<ACIS1);
8
  ACSR   &=  ~(1<<ACIS0);
9
  sei();          // Globale Interrupts freigeben
10
}

Walter S. schrieb:
> Fehlersuche ist ein essentieller Teile von Hard- und
> Softwareentwicklung,
> das geht nicht durch rumprobieren sondern durch systematisches Vorgehen

Wichtig ist es auch, Datenblätter zu lesen:

The Analog Comparator compares the input values on the positive pin AIN0 
and negative pin AIN1. When the voltage on the positive pin AIN0 is 
higher than the voltage on the negative pin AIN1, the Analog Comparator 
Output, ACO, is set.

Beim Toggeln wird, wenn AIN0 wieder kleiner als AIN1 wird (also 
negativ), erneut ACO gesetzt. Also genau das gewünschte Ergebnis.

Trotzdem - für Netzspannung -> App. Note.

von Soder D. (soderdaen)


Angehängte Dateien:

Lesenswert?

Carl D. schrieb:

> Wenn vor dem delay() ein sleep() kommt, dann wartet die Hauptschleife
> auf einen Interrupt, da eventuell von Libs noch andere laufen sollte
> noch geprüft werden, ob der "DebugPin" tatsächlich auf 1 ist, wartet n
> μs und setzt das Signal zurück. So gibt das definierte Impulse, wobei
> natürlich Interrupts während der Wartezeit verschickt werden.

Sorry, ich versteh da nur Bahnhof.

Walter S. schrieb:
> ein Komparator hat zwei Eingänge, an den einen legst du sinnvollerweise
> als Rferenz die Bandgap (überleg mal was im zweiten Bild anliegt und
> warum das Ergebnis so aussieht)

Im zweiten Bild ist Band Gap off, an AIN0 liegt meine Messspannung an, 
an AIN1 liegt GND an. Ich schätze mal, dass der Komparator sehr genau 
ist und deswegen leicht, und dementsprechend oft ausschlägt was man in 
den blauen Spitzen sehen kann. Dagegen spricht, dass Arduino und 
Funktionsgenerator auf dem selben GND liegen.

Walter S. schrieb:
> die LED interessiert doch nicht, interessant ist wo das Signal am
> Prozessor anliegt und wie es an DIESER Stelle aussieht

Liegt im Fall ohne Band Gap an AIN0 an und im Fall mit Band Gap an AIN1.

Walter S. schrieb:
> Fehlersuche ist ein essentieller Teile von Hard- und
> Softwareentwicklung,
> das geht nicht durch rumprobieren sondern durch systematisches Vorgehen

Das stimmt natürlich !

Dieter F. schrieb:
> Stell mal bitte Deinen Komparator auf "Toggle" ein - OHNE BANDGAP - und
> lege AIN1 an GND und AIN0 an Dein Signal. Dann brauchst DU auch kein
> Delay, um den Pin-Toggle aus der ISR zu erkennen :-)

Im Anhang das Oszillogramm dazu. Das schaut schon ganz gut aus, wenn da 
nicht die Spikes ab Mitte der negativen Halbwelle wären.

von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> Im Anhang das Oszillogramm dazu. Das schaut schon ganz gut aus, wenn da
> nicht die Spikes ab Mitte der negativen Halbwelle wären.

Zeige bitte Dein aktuelles Programm - und beschreibe, wie Du den 
Komparator beschaltet hast.

von Soder D. (soderdaen)


Lesenswert?

Dieter F. schrieb:
> Soder D. schrieb:
>> Im Anhang das Oszillogramm dazu. Das schaut schon ganz gut aus, wenn da
>> nicht die Spikes ab Mitte der negativen Halbwelle wären.
>
> Zeige bitte Dein aktuelles Programm - und beschreibe, wie Du den
> Komparator beschaltet hast.
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#define F_CPU 16000000UL
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
7
8
void comparator_init();
9
10
int main(void)
11
{
12
  DDRD   &= ~(1<<DDD6);
13
  DDRD   &= ~(1<<DDD7);
14
  DDRB   |=  (1<<DDB5);
15
  comparator_init();
16
  while (1)
17
  {
18
    PORTB &= ~(1<<DDB5);
19
  }
20
}
21
22
23
ISR(ANALOG_COMP_vect)
24
{
25
  PORTB |= (1<<DDB5);
26
};
27
28
29
void comparator_init()
30
{
31
  //  ADCSRB &= ~(1<<ACME);
32
  //  ACSR   |=  (1<<ACBG);
33
  ACSR   |=  (1<<ACI);
34
  ACSR   |=  (1<<ACIE);
35
  ACSR   &=  ~(1<<ACIS1);
36
  ACSR   &=  ~(1<<ACIS0);
37
  sei();          // Globale Interrupts freigeben
38
}

Beschaltung:
Funktionsgenerator

  °       ~       °
  |               |
  ---D------R-----
        |         |
       AIN0      GND---AIN1
        |         |      |
  ---------------------------
  |      Arduino             |
  ---------------------------

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> Beschaltung:
> Funktionsgenerator
>
>   °       ~       °
>   |               |
>   ---D------R-----
>         |         |
>        AIN0      GND---AIN1
>         |         |      |
>   ---------------------------
>   |      Arduino             |
>   ---------------------------

Wss hast Du denn da für einen Funktionsgenerator?

Das Signal solltest Du nicht auch noch an GND anschließen. An AIN1 
gehört als Referenz nur GND dran - sonst nichts.

von Soder D. (soderdaen)


Angehängte Dateien:

Lesenswert?

Dieter F. schrieb:

> Wss hast Du denn da für einen Funktionsgenerator?
>
> Das Signal solltest Du nicht auch noch an GND anschließen. An AIN1
> gehört als Referenz nur GND dran - sonst nichts.

Es handelt sich um ein Agilent 33250A.
An AIN1 ist ja GND dran. Das GND ist mit dem Funktionsgenerator 
verbunden weil die Spannungsversorgung des Arduino über ein USB Netzteil 
läuft. Am USB Anschluss des PCs brauch ich die gemeinsame GND Verbdinung 
natürlich nicht.
Im Anhang als das Oszillogramm mit der Stromversorgung über den PC. AIN1 
mit GND vom Arduino verbunden, Arduino nur über die Verbindung AIN0 zum 
Punkt zwischen Diode und Widerstand.

von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> AIN0 zum
> Punkt zwischen Diode und Widerstand

Hänge doch bitte mal die Messspitze des Oszilliskops an die gleiche 
Stelle. Dann sieht man auch, womit der Komparator vergleicht!

Ich würde beides weglassen und die Signal-Quelle (Funktionsgenerator) 
direkt mit AIN0 verbinden. Dann wird es auch funktionieren.

von Route_66 H. (route_66)


Lesenswert?

Dieter F. schrieb:
> Ich würde beides weglassen und die Signal-Quelle (Funktionsgenerator)
> direkt mit AIN0 verbinden. Dann wird es auch funktionieren.

Und die negative Halbwelle des Signals killt was genau im Arduino?

von Soder D. (soderdaen)


Lesenswert?

Route 6. schrieb:
> Dieter F. schrieb:
>> Ich würde beides weglassen und die Signal-Quelle (Funktionsgenerator)
>> direkt mit AIN0 verbinden. Dann wird es auch funktionieren.
>
> Und die negative Halbwelle des Signals killt was genau im Arduino?


Mit geeignet hohem Vorwiderstand sollte nichts passieren.

von Dieter F. (Gast)


Lesenswert?

Route 6. schrieb:
> Und die negative Halbwelle des Signals killt was genau im Arduino?

Na, sag schon, was denn?

Soll das heißen, das das nicht korrekt ist?:

To protect the device from voltages above VCC  and below GND, the AVR 
has internal clamping diodes on the I/O pins (see Figure 1). The diodes 
are connected from the pins to VCC  and GND and keep all input signals 
within the AVR’s operating voltage). Any voltage higher than VCC + 0.5V 
will be forced down to VCC + 0.5V (0.5V is the voltage drop over the 
diode) and any voltage below GND - 0.5V will be forced up to GND - 0.5V.

Aus dem Grund weise ich jetzt zum x-ten Mal auf die App-Note hin ...

Soder D. schrieb:
> Mit geeignet hohem Vorwiderstand sollte nichts passieren.

Korrekt. (Wobei der bei dem Funktionsgenerator als Signalquelle nicht 
erforderlich sein sollte)

von Dieter F. (Gast)


Lesenswert?

Und - wie sieht das Oszilloskop-Bild jetzt aus?

von Soder D. (soderdaen)


Angehängte Dateien:

Lesenswert?

Dieter F. schrieb:
> Und - wie sieht das Oszilloskop-Bild jetzt aus?

Gut, natürlich sollte man nicht vergessen den Krokoklemenmassenschluss 
am Tastkopf auch auf das getrennte GND zu legen. Siehe erstes Bild, 
schaut gut aus, auch wenn es mehrere Ausschläge bei der steigenden 
Flanke gibt. Das lässt sich leicht beheben, ich schalte in der ISR die 
globalen Interrupts aus und im main nach dem delay wieder ein.
Doof ist nur, dass der erste Impuls schon ca 0,6ms vor Spannungsanstieg 
stattfindet.

Weiteres Problem: Wenn ich den Arduino am Steckernetzteil betreiben 
möchte ist das Oszillogramm leider nicht mehr so schön, siehe Bild 2.

Edit: Achja, der Messzweig liegt immernoch zwischen Diode und 
Widerstand.

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Soder D. schrieb:
> Achja, der Messzweig liegt immernoch zwischen Diode und
> Widerstand

Und warum?

Oh Mann, dann heb halt die Spannung an AIN1 mit einem Spannungsteiler 
(Poti > 10 kOhm) auf 0,1 ... 0,5 V -> also natürlich vorher von GND 
lösen.

Da musst Du halt ein wenig mit der Referenz rumspielen, wenn Du bei 
Deiner Widerstand-/Dioden-Lösung bleiben willst. GND geht dabei 
(offensichtlich) nicht.

Soder D. schrieb:
> Weiteres Problem: Wenn ich den Arduino am Steckernetzteil betreiben
> möchte ist das Oszillogramm leider nicht mehr so schön, siehe Bild 2.

Dann hänge halt ein vernünftiges Netzteil dran :-)

von Dieter F. (Gast)


Lesenswert?

Na, war es das jetzt? Rückmeldung Fehlanzeige?

von Soder D. (soderdaen)


Lesenswert?

Dieter F. schrieb:
> Na, war es das jetzt? Rückmeldung Fehlanzeige?

Ich mache gerne auch mal Feierabend ;)

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.