Zwei Impulse innerhalb einer bestimmten Zeit

Hallo alle zusammen. Um festzustellen ob meine Phasenanschnittsteuerung mit Netzspannung versorgt ist möchte ich meinen Pin des Nulldurchgangsdetektor überprüfen. Falls nicht innerhalb von 100ms der Impuls wieder da ist, ist entweder die Netzspannung ausgefallen oder mein Zerotrigger ist defekt. In jedem fall muss ich ja alles abschalten und melden. Nun zur meiner Frage. Den Zerotrigger nutze ich bereits zur Steuerung mittels Interrupt. Ist es parallel möglich ist, in der loop() den Pin abzufragen und damit einen Timer zu resetten der Quasi automatisch beim erreichen der 100ms ein Signalauslöst oder lässt sich das ganze auch einfacher ohne Timer lösen?

Besten Dank :slight_smile:

Das kann Dein Interrupt doch mit machen.
Eine volatile unsigned long Variable immer im Nulldurchgang auf millis() setzen und im loop atomar deren Differenz zu millis() abprüfen.

Gruß Tommy

1 Like

Lege Dir eine globale variable Zeitmerker an , erweitere die Funktion zeitscan und werte in loop aus.


uint32_t zeitmerker;
void zeitscan()
{
  if (nulldurchgang_erkannt == true)
  {
    zeitmerker=millis();
  }
    // delayMicroseconds(200);
    if (counter >= schnittzeitpunkt)
    {
      digitalWrite(triac, HIGH);
      digitalWrite(test, HIGH);
      counter = 0;
      nulldurchgang_erkannt = false;
      // Den Triac nach 10us auszuschalten brachte probleme.
    }
    else
    {
      counter++;
    }
  }
}

void loop()
{
if (millis()-zeitmerker>100)
{
  // Fehlerbehandlung
}
  analogwert = analogRead(poti);
1 Like

Manchmal sieht man die einfachsten Sachen vor lauter Code nicht mehr :rofl:
Vielen herzlichen dank für die Antwort :slight_smile:

Gerne, ich wusste nur das die Anschnittsteuerung auch von Dir kam und ich das nebenbei gelesen hatte... - Na dann viel Erfolg!

1 Like

War nicht zeitscan() eine InterruptServiceRoutine?
Dann müsste doch eigentlich noch ein wenig geändert werden (s.a. hier):

#include <util/atomic.h>
...
volatile uint32_t zeitmerker;
...
// Das geht schief, wenn der Zeitmerker sich während der Subtraktion ändert.
// if (millis()-zeitmerker>100)
bool isErrorActive;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 
{
  isErrorActive = millis() - zeitmerker > 100;
}
if (isErrorActive) 
{
  // Fehlerbehandlung
}
...

Gruß Walter

Das war nulldurchgang() - da wird "nulldurchgang_erkannt" gesetzt.
Hier das Ursprungsthema für alle zum nachlesen.

Auch.
Aus Phasenanschnitt bis zu 5kVA zeitprobleme, Eröffnungspost:

Timer1.attachInterrupt(zeitscan, schrittbreite);

Kann natürlich sein, dass das inzwischen anders ist :slight_smile:

Edit: Du warst schneller mit Verlinken des Originals.

Beide interrupts sind noch vorhanden, schaue ich morgen mal an :slight_smile:

Dann:
zeitmerker volatil machen und in der nulldurchgang_ISR den zeitmerker setzen.
Passt besser.

Bin jetzt schon häufiger über das Thema Atomic gestolpert. Wird das benötigt ? Wollte mich da am Wochenende sonst mal einlesen.

Ja, ich denke dass das benötigt wird.

Um das Ergebnis von millis() und den Zeitmerker zu subtrahieren, muss die arme kleine CPU das in mehreren Schritten erledigen. Die 32 Bit passen nicht in ein (8-Bit) Register [*], die Rechnung kann also nicht un-unterbrechbar mit einer Operation ausgeführt werden.

Wenn nun während dieser Rechnerei der Interrupt, der den Zeitmerker verändert, dazwischenfunkt, wurde ein Teil noch mit dem alten und wird der Rest dann mit dem neuen Wert gerechnet. Das kann ohne böse Auswirkungen gelingen, aber wenn z.B. zufällig im Interrupt ein Überlauf von einem zum nächsten Byte stattfand, kann das Ergebnis der Subtraktion mal gleich ganz falsch werden.

Deshalb ATOMIC - das sorgt dafür, dass alles in dem geklammerten Block ohne Unterbrechung abgearbeitet wird.

[*] Weiß gerade nicht, ob man mit den 16 Bit Indexregistern auch rechnen könnte.

Danke für deine Erklärung, werde mich dann entsprechend da mal einlesen. :slight_smile: