Forum: Mikrocontroller und Digitale Elektronik Hysterese bei AVR (ACO oder ICP)


von Robert B. (robertb)


Lesenswert?

Hallo!

Ich suche eine Möglichkeit dem internen Komparator des AVRs eine 
Hysterese zu verpassen. Hat das schon mal jemand gemacht?

Konkret geht es um die Aufbereitung des in diesem Thread gezeigten 
Signals: Beitrag "Impulsaufbereitung für Moped-Zündung (Pickup-Spule)"

Momentan nehme ich den positiven Anteil des Signals (normale 1N4148), 
danach "schneide" ich mit einer Z-Diode und Widerstand gegen Masse 
weitere 10V weg und gehe dann per Vorwiderstand auf eine 4,7V Z-Diode 
(als Schutz) und einen Kerko (Tiefpass).
1
>>---1N4148----ZF10----*--1k--*--*------ AIN0
2
                       |      |  |
3
                       |      Z  1
4
                       1      F  0
5
                       k      4  n
6
                       |      .  F
7
                       |      7  |
8
                       |      |  |
9
>>---------------------*------*--*------ GND

Wenn ich das Signal mit einem regelbaren Netzteil simuliere erhalte ich 
manchmal auch beim Runterregeln ein Interrupt. Gleiches passiert 
seltsamerweise sogar auch wenn ich den Eingang mit z.B. +17V verbinde 
und dann wieder trenne.

Momentan ist der eingesetzte AVR ein AT90S2313 (Resteverwertung), kann 
aber auch einen mega168 oder mega8 nehmen (oder bestelle mir was).

: Verschoben durch User
von Ganymed (Gast)


Lesenswert?

Du führst die zu messende Spannung über
einen Spannungsteiler (R1 R2)mit Tiefpasswirkung (C1)
auf den nichtinvertierenden Eingang den
Comparators. Wenn ACO High ist, schaltet
ein Ausgang über einen Widerstand den AIN(+)
etwas positiver.
                       |-------------Ein Ausgang
                       |
                       R3
                       |
                       |
>>---1N4148----R1------*-----*------- AIN0
                       |     |
                       |     |
                       R2    C1
                       |     |
                       |     |
>>---------------------*-----*--------- GND

von Robert B. (robertb)


Lesenswert?

Hallo Ganymed,

vielen Dank für deine Antwort.

Allerdings bin ich immer noch etwas am grübeln ob das so gut 
funktionieren kann.

Beispiel:

AIN0 = 2,6V, AIN1 = 2,5V -> ACO wird high

ACO-Interrupt:
Um jetzt die Hysterese zu erzeugen senke ich die Referenzspannung an 
AIN1 ab (z.B. um 0,5V) -> AIN0 = 2,0V

Die Spannung an AIN0 fällt auf 1,999V -> ACO-Interrupt

im Interrupt müsste man nun die Referenzspannung wieder auf 2,5V setzen 
um die Hysterese für die steigende Flanke zu gewährleisten. Problem: 
Wird in dieser Zeit das Signal nur kurz 2,0001V wird wieder ein 
Interrupt ausgelöst. Und die Zeit bis das Interrupt auslöst und die 
Referenzspannung umgestellt hat ist in den Maßstäben eines unsauberen 
Eingangssignal warscheinlich recht lang.

Wahrscheinlich ist dass der Nachteil das ganze nicht mit einem eigenen 
OP-Amp zu machen. Oder habe ich etwas wesentliches übersehen?

Grüße
Robert

von Benedikt K. (benedikt)


Lesenswert?

Bei einem ATtiny261 kann man beim Komparator eine Hysterese zuschalten, 
das würde die ganze Sache stark vereinfachen.

von Robert B. (robertb)


Lesenswert?

Hallo!

Habe das ganze jetzt so gelöst:

An AIN0 liegt das Signal an. An AIN1 ist ein Spannungteiler mit 47k Poti 
der 2,5V liefert. Über einen 47k Widerstand kann man über PB6 die 
Spannung auf 2V (PB6 low) oder auf 3V (PB6 high) ändern. Gleichzeitig 
kann man gratis noch ne Kontrollled anschließen.

Codemäßig verwende ich sowohl den ICP-Int des Timers 1 (daran wird dann 
auch die Periode gemessen) bei falling edge (Signal größer Referenz) und 
den AC-Int bei rising edge (Signal kleiner Referenz).

Initialisierung:
1
void timer_init(void)
2
{
3
  /*
4
   * init timer1
5
   * ICNC1: Input Capture1 Noise Canceler (4 CKs)
6
   * ICES1: Input Capture1 Edge Select (0 = falling edge / 1 = rising edge)
7
   * prescaler
8
   */
9
  TCCR1B = (1<<ICNC1) | (0<<ICES1) | T1presc64;
10
  /*
11
   * interrupts
12
   * TICIE1: Timer/Counter1 Input Capture Interrupt Enable
13
   * TOIE0: Timer/Counter0 Overflow Interrupt Enable
14
   */
15
  TIMSK = (1<<TICIE1) | (1<<TOIE1);  // Input Capture und Overflow T1 und Output Compare Match T1 aktivieren
16
}
17
18
void aco_init(void)
19
{
20
  /*
21
   * init analog comparator
22
   * ACIE: Analog Comparator Interrupt Enable
23
   * ACIC: Analog Comparator Input Capture Enable
24
   * ACIS1/ACIS0: (1 0) - Comparator Interrupt on Falling Output Edge
25
   *              (1 1) - Comparator Interrupt on Rising Output Edge
26
   */
27
  ACSR = (1<<ACIE) | (1<<ACIC) | (1<<ACIS1) | (1<<ACIS0);
28
}

Interrupts:
1
ISR(TIMER1_CAPT1_vect)
2
{
3
  if (ACSR & (1<<ACO))
4
    return;
5
6
  // lower ref-voltage on AIN1 for hysteresis
7
  PORTD &= ~(1<<6);
8
  // clear pending aco-interrupt that might occured due to non-hysteresis
9
  ACSR |= (1<<ACI);
10
11
  // hier wird gearbeitet
12
}
13
14
ISR(ANA_COMP_vect) {
15
  if (!(ACSR & (1<<ACO)))
16
    return;
17
18
  // raise ref-voltage on AIN1 for hysteresis
19
  PORTD |= (1<<6);
20
  // clear pending icp-interrupt that might occured due to non-hysteresis
21
  TIFR |= (1<<ICF1);
22
}

Direkt zu Beginn der Interrupts wird geprüft ob die Bedingung noch 
vorliegt. Quasi ein Tiefpass. Danach wird sofort die Referenzspannung 
umgeschaltet. Sollte in der Zwischenzeit aufgrund der nicht-vorhandene 
Hystherese das komplementäre Interrupt ausgelöst worden sein wird dieses 
gelöscht. Zusammen mit der Abfrage zu Beginn scheint das etwas 
doppelt-gemoppelt zu sein aber so das Aufrufen des komplementären Ints 
vermieden und evtl. hab ich noch eine Konstellation nicht bedacht.

Vielleicht hilft dieser Code anderen die ein ähnliches Problem haben. 
Zudem würde ich mich über Anmerkungen sehr freuen falls ich doch nen 
Fehler gemacht habe.

Grüße
Robert

von (prx) A. K. (prx)


Lesenswert?


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.