Forum: Mikrocontroller und Digitale Elektronik Wellenpaketsteuerung mit ESP8266


von Chris H. (chris_h616)


Lesenswert?

Servus zusammen,
ich habe mir am Wochenende überlegt, ob ich meinen Heizungslüfter 
(Spaltpolmotor) nicht mit einer Wellenpaketsteuerung ausrüsten soll, da 
dies an anderen Heizungen mit entsprechendem Thermostad bereits 
geschieht.
Ich wollte das ganze mit einem ESP8266 steuern und hab mal angefangen zu 
basteln, bis zu einem gewissen punkt hat auch alles funktioniert, ich 
habe ein Wellenpaket raus bekommen und alles hat funktioniert. 
Allerdings möchte ich immer die gleiche Anzahl an Halbwellen bekommen, 
damit ich dem Motor keine Gleichspannung zumuten  muss, Leider ist der 
ESP8266 wohl zu langsam für 2 Interrupts mit der Geschwindigkeit von 
50Hz, jetzt habe ich mir überlegt das ganze mit einer externen Schaltung 
zu realisieren.
Leider habe ich grade keinen plan wie ich das realisieren könnte. Ich 
hab schon über einen Zähler nachgedacht der immer 2 Halbwellenzählt oder 
mit einem Zero Crossing Optokoppler, aber  die zündende Idee fehlt mir 
noch.
Hat von euch schon mal jemand eine Wellenpaketsteuerung gebaut oder 
villeicht schon mal ein ähnliches Problem gehabt und schon eine Lösung 
parat?

Ich hoffe jemand kann mir helfen

LG Chris :)

: Bearbeitet durch User
von Carsten-Peter C. (carsten-p)


Lesenswert?

Moin,
wenn Du ein SSR, das im Nulldurchgang schaltet nimmst, sollte es 
eigentlich gehen. Die Impulsdauer und Pausendauer sollten dabei ein 
vielfaches von 20 mSec. betragen. Damit triffst Du immer 2 Halbwellen. 
Nur, wenn die Impulse genau den Nulldurchgang treffen, könnte es 
kurzzeitig Abweichungen geben, bis die Netzfrequenz etwas weiter läuft. 
Das wirst Du nicht merken. Für meine Phasenabschnittssteuerung habe ich 
einen ATTiny 4313 mit 6 MHz genommen und einen Zähler mit 100Hz vom Netz 
synchronisiert. Das schafft der locker. Da Dein ESP viel schneller 
läuft, sollten die 2 INT kein Problem sein.
Gruß
 Carsten

von Rainer W. (rawi)


Lesenswert?

Chris H. schrieb:
> Leider ist der ESP8266 wohl zu langsam für 2 Interrupts mit der
> Geschwindigkeit von 50Hz

Bestimmt nicht - das muss am Programm liegen.

von Falk B. (falk)


Lesenswert?

Chris H. schrieb:

> damit ich dem Motor keine Gleichspannung zumuten  muss, Leider ist der
> ESP8266 wohl zu langsam für 2 Interrupts mit der Geschwindigkeit von
> 50Hz,

Sicher nicht.

> mit einem Zero Crossing Optokoppler, aber  die zündende Idee fehlt mir

https://www.mikrocontroller.net/articles/230V#Nulldurchgangsdetektoren

> villeicht schon mal ein ähnliches Problem gehabt und schon eine Lösung
> parat?

Mach's einfach richtig. Richtiger Nulldurchgangsdetektor, der die 
Phaseninformation erhält, der Rest ist bissel Logik in der Software. Der 
ESP32 langweilt sich dabei zu Tode.

von Chris H. (chris_h616)


Lesenswert?

Rainer W. schrieb:
> Chris H. schrieb:
>> Leider ist der ESP8266 wohl zu langsam für 2 Interrupts mit der
>> Geschwindigkeit von 50Hz
>
> Bestimmt nicht - das muss am Programm liegen.


Da hast du wohl recht, mein Programm funktioniert solange ich kein 
Display angeschlossen habe, mit Display entsteht manchmal eine 
Gleichspannung. Liegt wohl am Display program, aber wie kann ich das 
ganze beschleunigen, ich denke dass die Übertragung zum Display zu lange 
dauert.
Es handelt sich um ein Display mit SH1106 Treiber.

: Bearbeitet durch User
Beitrag #7854412 wurde vom Autor gelöscht.
von Sherlock 🕵🏽‍♂️ (rubbel-die-katz)


Lesenswert?

Der Haken beim ESP8266 ist  dass das eigene Programm mehrmals pro 
Sekunde vom WLAN Teil unterbrochen wird. Die Unterbrechungen dauern bei 
schlechtem Empfang und bei Funkstörungen manchmal über 100ms.

von Chris H. (chris_h616)


Lesenswert?

Sherlock 🕵🏽‍♂️ schrieb:
> Der Haken beim ESP8266 ist  dass das eigene Programm mehrmals pro
> Sekunde vom WLAN Teil unterbrochen wird. Die Unterbrechungen dauern bei
> schlechtem Empfang und bei Funkstörungen manchmal über 100ms.

Deswegen wollte ich die Wellenpaketsteuerung über einen IC machen, damit 
der ESP nur sagen muss wie viele  wellen er durchlassensoll.

von Michael B. (laberkopp)


Lesenswert?

Chris H. schrieb:
> Leider ist der ESP8266 wohl zu langsam für 2 Interrupts mit der
> Geschwindigkeit von 50Hz,

Das ist er nicht, es hapert eher mit deinen Programmierfähigkeiten.

von Chris H. (chris_h616)


Lesenswert?

Michael B. schrieb:
> Chris H. schrieb:
>> Leider ist der ESP8266 wohl zu langsam für 2 Interrupts mit der
>> Geschwindigkeit von 50Hz,
>
> Das ist er nicht, es hapert eher mit deinen Programmierfähigkeiten.

ist möglich ich habe nicht gesagt dass ich perfekt programmieren kann, 
aber ich wüsste nicht wie ich mein Display schneller ansteuern kann.
Ich habe kein Delay im Display loop.
Aber evtl kannst du mir ja helfen meinen loop zu verbessern.

void Displayloop() {
  if (millis() - vorherigeMillisDisplay >= displayIntervall) {
    vorherigeMillisDisplay = millis();

    bool updateNeeded = false;  // Wird auf true gesetzt, wenn sich 
etwas geändert hat

    display.setTextSize(2);
    display.setTextColor(SH110X_WHITE);

    // Temperatur nur aktualisieren, wenn sich der Wert geändert hat
    if (TempBME != prevTempBME) {
      prevTempBME = TempBME;
      display.fillRect(0, 0, 128, 16, SH110X_BLACK); // Bereich 
überschreiben
      display.setCursor(0, 0);
      display.print(F("IST "));
      display.print(TempBME);
      display.print(F("C"));
      updateNeeded = true;
    }

    // Counter nur aktualisieren, wenn sich der Wert geändert hat
    if (counter != prevCounter) {
      prevCounter = counter;
      display.fillRect(0, 20, 128, 16, SH110X_BLACK);
      display.setCursor(0, 20);
      display.print("Soll");
      updateNeeded = true;
    }

    // Dimmersollwert nur aktualisieren, wenn sich der Wert geändert hat
    if (DimmersollWert != prevDimmersollWert) {
      prevDimmersollWert = DimmersollWert;
      display.fillRect(0, 40, 128, 16, SH110X_BLACK);
      display.setCursor(0, 40);
      display.print(DimmersollWert);
      updateNeeded = true;
    }

    // Display nur aktualisieren, wenn sich was geändert hat
    if (updateNeeded) {
      display.display();
    }
  }
}

: Bearbeitet durch User
von Carsten-Peter C. (carsten-p)


Lesenswert?

Moin,
ein Vorschlag zur Lösung:
Nimm einen kleinen ATTiny 84 o.Ä. und takte den mit 3,27800MHz. Der hat 
einen 16 Bit Timer, den Du als „Vorteiler“ nimmst und in Mode4 CTC 
einstellst. Mit OCR1A legst Du die Länge der Wellenpakete fest und lässt 
den Ausgang OCR1A toggeln. Dann verbindest Du den Ausgang PA6 mit dem 
Eingang vom 8 Bit Timer 0 PA3 (T0) zum Triggern. Den stellst Du auf 
Mode4 Fast PWM und kannst mit OCR0A Deine gewünschte Leistung in 255 
Stufen einstellen. Den Datenaustausch zum ESP kannst Du über die 
serielle Schnittstelle machen. Zusätzlich sind genügend Eingänge für 
Taster zum manuellen Bedienen vorhanden.
Viel Erfolg
 Carsten

von Falk B. (falk)


Lesenswert?

Chris H. schrieb:
> Michael B. schrieb:
>> Chris H. schrieb:
>>> Leider ist der ESP8266 wohl zu langsam für 2 Interrupts mit der
>>> Geschwindigkeit von 50Hz,
>>
>> Das ist er nicht, es hapert eher mit deinen Programmierfähigkeiten.
>
> ist möglich ich habe nicht gesagt dass ich perfekt programmieren kann,
> aber ich wüsste nicht wie ich mein Display schneller ansteuern kann.
> Ich habe kein Delay im Display loop.
> Aber evtl kannst du mir ja helfen meinen loop zu verbessern.

Wieso? Wenn man WIRKLICH einen Interrupt nutzt, hat der IMMER Priorität 
und kann das laufende Hauptprogramm unterbrechen. Wo ist der bei dir?

von Chris H. (chris_h616)


Lesenswert?

Falk B. schrieb:
> Chris H. schrieb:
>> Michael B. schrieb:
>>> Chris H. schrieb:
>>>> Leider ist der ESP8266 wohl zu langsam für 2 Interrupts mit der
>>>> Geschwindigkeit von 50Hz,
>>>
>>> Das ist er nicht, es hapert eher mit deinen Programmierfähigkeiten.
>>
>> ist möglich ich habe nicht gesagt dass ich perfekt programmieren kann,
>> aber ich wüsste nicht wie ich mein Display schneller ansteuern kann.
>> Ich habe kein Delay im Display loop.
>> Aber evtl kannst du mir ja helfen meinen loop zu verbessern.
>
> Wieso? Wenn man WIRKLICH einen Interrupt nutzt, hat der IMMER Priorität
> und kann das laufende Hauptprogramm unterbrechen. Wo ist der bei dir?

mein Programm ist zu groß um das ganze hier zu posten, der interrupt ist 
in einem anderen Programmteil untergebracht

//Programm das bei interrupt ausgeführt wird /Positivehalbwelle
void IRAM_ATTR Positiv() {
  // Wenn die Verzögerung noch nicht vergangen ist, den Interrupt 
ignorieren
  if (millis() - last_positiv_time >= debounce_positiv) {
    positiv++;  // Zähler erhöhen
    last_positiv_time = millis();  // Speichern der aktuellen Zeit
  }
}

//Programm das bei interrup ausgeführt wird/Negativehalbwelle
void IRAM_ATTR Negativ() {
    if (millis() - last_negativ_time >= debounce_negativ) {
    negativ++;  // Zähler erhöhen
    last_negativ_time = millis();  // Speichern der aktuellen Zeit
  }
}

von Falk B. (falk)


Lesenswert?

Chris H. schrieb:

>> Wieso? Wenn man WIRKLICH einen Interrupt nutzt, hat der IMMER Priorität
>> und kann das laufende Hauptprogramm unterbrechen. Wo ist der bei dir?
>
> mein Programm ist zu groß um das ganze hier zu posten,

Glaub ich nicht, man kann hier mehrere MB anhängen . . .

> der interrupt ist
> in einem anderen Programmteil untergebracht

> //Programm das bei interrupt ausgeführt wird /Positivehalbwelle
> void IRAM_ATTR Positiv() {
>   // Wenn die Verzögerung noch nicht vergangen ist, den Interrupt
> ignorieren
>   if (millis() - last_positiv_time >= debounce_positiv) {
>     positiv++;  // Zähler erhöhen
>     last_positiv_time = millis();  // Speichern der aktuellen Zeit
>   }
> }

Auch wenn das hier nicht das zentrale Problem ist, sollte man die 
aktuelle Zeit nur einmal lesen und dann damit arbeiten.

now = millis();

Aber ich sehe hier keinerlei Aktion zum Phasenanschnitt! Eigentlich muss 
hier eine Verzögerung per Timer gestartet werden, die dann nach xx ms 
den Phasenanschitt einschaltet. Diese Aktion muss ebenfall mit einem 
Interrupt passieren, damit das nahezu verzögerungsfrei zu jeder Zeit 
gemacht werden kann. Man kann NICHT in der Hauptschleife hoffen, daß man 
den Zeitpunkt schon irgendwie gut genug erwischt! Eine Abfrage mit dem 
Konzept millis() ala Arduino ist hier untauglich! Hier muss man an die 
echten Timer des Controllers ran! Die sind nur manuell konfigurierbar 
und nutzbar. Oder man findet eine Bibliothek, die das macht.

Außerdem fehlt die Logik für die gerade Anzahl der Halbwellen.

von Manfred P. (pruckelfred)


Lesenswert?

Chris H. schrieb:
> Da hast du wohl recht, mein Programm funktioniert solange ich kein
> Display angeschlossen habe, mit Display entsteht manchmal eine
> Gleichspannung. Liegt wohl am Display program, aber wie kann ich das
> ganze beschleunigen, ich denke dass die Übertragung zum Display zu lange
> dauert.

Dein Display wird nicht alle paar Millisekunden neu beschrieben, vermute 
ich mal. Dein Motor hat eine mechanische Trägheit.

Du könntest als Workaround die Ansteuerung des Motors sperren, solange 
das Display beschrieben wird, was ja wohl nur alle XX-Sekunden passieren 
muß.

Bei mir, andere Umgebung / andere Anwendungen, vergleiche ich Werte und 
beschreibe das Display nur bei Änderungen anstatt permanent zyklisch.

von Michael B. (laberkopp)


Lesenswert?

Chris H. schrieb:
> Aber evtl kannst du mir ja helfen meinen loop zu verbessern.

Wenn dieser code nicht innerhalb eines Interrupts abläuft, ist er ja 
durch Interrupts untebrechbar, sollte also nicht Ursache des Problems 
sein.

Allerdings weiss man nicht, ob irgendwelche Klassenfunktionen von 
display die Interupts sperren, z.B. display.display() wäre so ein 
Kandidat.

Insgesamt ist der Code enorm aufwändig, jede der aufgerufenen 
Klassenfunktionen isg ja extrem mächtig, z.B. display.print().

Aber, wenn die Interrupts nicht gesperrt werden und dir die Performance 
reicht, ist es letztlich egal.

von Chris H. (chris_h616)


Lesenswert?

Michael B. schrieb:
> Chris H. schrieb:
>> Aber evtl kannst du mir ja helfen meinen loop zu verbessern.
>
> Wenn dieser code nicht innerhalb eines Interrupts abläuft, ist er ja
> durch Interrupts untebrechbar, sollte also nicht Ursache des Problems
> sein.
>
> Allerdings weiss man nicht, ob irgendwelche Klassenfunktionen von
> display die Interupts sperren, z.B. display.display() wäre so ein
> Kandidat.
>
> Insgesamt ist der Code enorm aufwändig, jede der aufgerufenen
> Klassenfunktionen isg ja extrem mächtig, z.B. display.print().
>
> Aber, wenn die Interrupts nicht gesperrt werden und dir die Performance
> reicht, ist es letztlich egal.

ich hab jetz mal alles unnötige deaktiviert aber immer noch das selbe 
problem, villeicht liegts tatsächlich an meinem Programm, scheinbar 
tritt der fehler auch nur bei längeren wellenpaketen auf, jedenfalls 
habe ich mim Oszi die wellen bis 20 Wellen gezählt, dort passt alles, 
aber wenn ich bei 98 halbwellen bin (Laut programm) dann schneidet er 
mir nur noch eine Halbwelle ab und nicht 2 Halbwellen

void Wellenpacketsteuerungsetup(){
  pinMode(Dimmer, OUTPUT);
  WP = 100;             //größe des Wellenpaketes
}

void Wellenpacketsteuerung(){
  DimmersollWert = counter;
  Halbwellen=positiv+negativ+1;   //muss 1 sein, da wenn dass Programm 
startet, befindet sich die Phase bereits in der ersten halbwelle und 
wird sonst nicht gezählt

  //Wird benötigt wenn der Sollwert auf 1% geht, da diese sonst nicht 
ausgegeben werden.
  if (DimmersollWert==1){
    DimmersollWert=2;
  } else if (counter < 0){
    counter = 0;
  } else if (counter > WP){
    counter = WP;
  }

  // Dimmer einschalten für die ersten 10 Halbwellen
  if (DimmersollWert > 0){
    if (Halbwellen < DimmersollWert) {
      digitalWrite(Dimmer, HIGH);  // Dimmer ein
      //Serial.println(Halbwellen);
    } else {
      // Dimmer ausschalten nur bei geraden Wellen
      if ((Halbwellen & 1) == 0) {
        digitalWrite(Dimmer, LOW);  // Dimmer aus
        //Serial.println("AUS" + String(Halbwellen));
      }
    }
  } else {
    digitalWrite(Dimmer, LOW);  // Dimmer aus
    //Serial.println("AUS");
  }

  // Nach 100 Halbwellen zähler zurücksetzen
  if ((Halbwellen >= WP) || (DimmersollWert==0)) {
    positiv = 0;
    negativ = 0;
  }
}

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.