Page 1 of 1

Überschreiten der Zykluszeit

Posted: 03 Jun 2022, 15:07
by Pompowac
Guten Tag,

ich habe alle verfügbaren Beispiele wie z.B. "Events with the mainloop()" , "Cyclic with python code" sowie Beiträge vom Zyklusüberschreiten auf dem Forum gelesen und trotzdem konnte mein Problem nicht lösen.
Ich bekomme regelmäßig einen Fehler mit Zyklusüberschreitung, egal ob die Zykluszeit auf 20ms oder auf 500ms eingestellt ist. Es gibt auch keine Information aus welchem Teil des Programm der Fehler kommt.
Trotz meines relativ großen Programm, benütze ich nur sehr selten die time.sleep() Funktion. Die Laufzeit des Programm sollte deshalb nicht das Problem sein.

Das Programm ist zu groß um es ganze zu zeigen, deswegen schicke ich einfach seine Struktur, vielleicht ist das genug um einen Fehler zu erkennen.

Die erste Datei ist vom RevPi:

Code: Select all

import revpimodio2

class RevPi:

    def __init__(self):
        try:
            self.revpi = revpimodio2.RevPiModIO(autorefresh=True, debug=True)
            self.revpi.cycletime = 250
            self.revpi.mainloop(blocking=False)
        except:
            print('Can not create revpi instantion')

    def set_output(self, output, value):

        try:
            if output == 1:
                self.revpi.io.O_1.value = value
            elif output == 2:
                self.revpi.io.O_2.value = value
            elif output == 3:
                self.revpi.io.O_3.value = value
            elif output == 4:
                self.revpi.io.O_4.value = value
            else:
                return -2
            return 0
        except:
            print('Der Ausgang konnte nicht aufgestellt werden')
            return -3

    def get_input(self, input):

        try:
            if input == 1:
                value = self.revpi.io.I_1.value
            elif input == 2:
                value = self.revpi.io.I_2.value
            elif input == 3:
                value = self.revpi.io.I_3.value
            elif input == 4:
                value = self.revpi.io.I_4.value
            else:
                return -2
            return value
        except:
            print('Der Eingang konnte nicht gelesen werden')
            return -3
Die zweite Datei enthaltet die ganze Logik der Maschine und hat folgende Struktur:

Code: Select all


# Thread  to monitor the status of the power supply
def thread_netzteil_pruefung(): 
	while True:
		if revpi.get_input(1):
            		netzteil_status_ok = True
        	else:
            		netzteil_status_ok = False
            
# Thread to control the LED lamp
def thread_lamp_output():
	while True:
		if connection_ok and netzteil_status_ok  and automatik_ein:
			revpi.set_output(1, True)
		else:
			revpi.set_output(1, False)
            
# Class initialisation
revpi = RevPi()

# Creating threads
thread_netzteil = Thread(target=thread_netzteil_pruefung)
thread_lamp = Thread(target=thread_lamp_output)

# Launching threads
thread_netzteil.start()
thread_lamp.start()

# Main part of the program
# Endless loop
while True:
          if step ==  0:
          	if revpi.get_input(2):
          		step = 10
          		
          if step ==  10:
          	revpi.set_output(1, True)
          	step = 20
          	delay = 0
          	
          if step == 20:
          
          	#Wait 2sec realized with 0.05 sleep until 2sec reached
          	time.sleep(0.05) 
          	delay = delay + 0.05
          	if delay > 2:
          		step = 30
          		
          if step == 30:
          	# end of the sequence
          	revpi.set_output(1, False)
          	step = 0
          	
Das ist ungefähr wie mein Programm aussieht. Es is viel größer, aber auf eine Schrittkette gebaut.
Was kann das Überschreiten verursachen? Wie ich gesagt habe - ist das ganz egal ob die Zykluszeit auf 20ms oder 400ms eingestellt ist.

Danke im Voraus für eure Unterstützung!!!
Gruß

Re: Überschreiten der Zykluszeit

Posted: 15 Jun 2022, 07:48
by Pompowac
Hallo,

Wir kämpfen immer noch mit diesem Problem, kann jemand uns dabei helfen?

Danke!

Re: Überschreiten der Zykluszeit

Posted: 27 Jun 2022, 15:36
by RevPiModIO
Könnt ihr mal eure CPU-Auslastung prüfen?

Es scheint mir, dass ihr durch eure `while True:`s den Prozessor killt. Und dann kommt die IO Aktualisierung auch nicht mehr hinterher und die Warnungen erscheinen :O

Ihr müsst da irgendwo `Verzögerungen` implementieren oder komplett mit dem reinen `.cycleloop` arbeiten.

Gruß
Sven

Re: Überschreiten der Zykluszeit

Posted: 27 Jun 2022, 16:05
by RevPiModIO
Super grob, ohne weiteres Wissen wäre es mit dem .cycleloop z.B. so:

Code: Select all

# -*- coding: utf-8 -*-
"""Demo for @Pompowac."""
__author__ = "Sven Sager"
__copyright__ = "Copyright (C) 2022 Sven Sager"
__license__ = "GPLv3"

import revpimodio2


def set_output(ct: revpimodio2.Cycletools, output, value):
    try:
        if output == 1:
            ct.io.O_1.value = value
        elif output == 2:
            ct.io.O_2.value = value
        elif output == 3:
            ct.io.O_3.value = value
        elif output == 4:
            ct.io.O_4.value = value
        else:
            return -2
        return 0
    except:
        print('Der Ausgang konnte nicht aufgestellt werden')
        return -3


def get_input(ct: revpimodio2.Cycletools, input):
    try:
        if input == 1:
            value = ct.io.I_1.value
        elif input == 2:
            value = ct.io.I_2.value
        elif input == 3:
            value = ct.io.I_3.value
        elif input == 4:
            value = ct.io.I_4.value
        else:
            return -2
        return value
    except:
        print('Der Eingang konnte nicht gelesen werden')
        return -3


def func_netzteil_pruefung(ct: revpimodio2.Cycletools):
    """Function  to monitor the status of the power supply."""
    while True:
        if get_input(ct, 1):
            ct.var.netzteil_status_ok = True
        else:
            ct.var.netzteil_status_ok = False


def func_lamp_output(ct: revpimodio2.Cycletools):
    """Function to control the LED lamp."""
    if ct.var.connection_ok and ct.var.netzteil_status_ok and ct.var.automatik_ein:
        set_output(ct, 1, True)
    else:
        set_output(ct, 1, False)


def main(ct: revpimodio2.Cycletools):
    "This will be executed every x ms, depending on the given cycletime."
    if ct.first:
        # This ist only once
        ct.var.step = 0
        ct.var.delay = 0.0
        ct.var.connection_ok = False
        ct.var.automatik_ein = False
        ct.var.netzteil_status_ok = False

    func_netzteil_pruefung(ct)
    func_lamp_output(ct)

    if ct.var.step == 0:
        if get_input(ct, 2):
            ct.var.step = 10

    if ct.var.step == 10:
        set_output(ct, 1, True)
        ct.var.step = 20
        delay = 0

    if ct.var.step == 20:
        # time.sleep(0.05) never use a sleep in the cycle function, just count
        # Wait 2sec realized with 0.05 sleep until 2sec reached
        ct.var.delay += 0.05
        if ct.var.delay > 2.0:
            ct.var.delay = 0.0
            ct.var.step = 30

    if ct.var.step == 30:
        # end of the sequence
        set_output(ct, 1, False)
        ct.var.step = 0


# Class initialisation
revpi = revpimodio2.RevPiModIO(autorefresh=True)
revpi.handlesignalend()
revpi.cycleloop(main, cycletime=50)  # Default 50 ms

Re: Überschreiten der Zykluszeit

Posted: 11 Jul 2022, 15:45
by Pompowac
Vielen Dank RevPiModIO,

dein Demoprogramm hat geholfen. Tatsächlich ist dieses Verhalten von der "while True" Schleife verursacht worden.

Jetzt läuft mein Programm korrekt aber ich muss manchmal eine HTTP Abfrage schicken die ungefähr eine Sekunde dauert und damit verursacht den Zykluszeit Fehler.
Ich versuchte die Zykluszeit vor der Abfrage auf eine Sekunde einzustellen um den Fehler zu vermeiden und nachher zurück auf 300ms einzustellen aber habe ich einen Fehler bekommen dass die Zykluszeit im Programm nicht geändert werden kann.

Wie soll ich diese Situation lösen?

Danke!

Re: Überschreiten der Zykluszeit

Posted: 11 Jul 2022, 16:52
by nicolaiB
Bist du auf die Antwort dieses Requests im Zyklus angewiesen? Falls nicht würde ich den Request nebenläufig (z.B. im einem Thread) behandeln

Nicolai

Re: Überschreiten der Zykluszeit

Posted: 11 Jul 2022, 17:11
by Pompowac
Nein, im Programm must ich auf die Antwort nicht warten.

Ich versuchte das auch mit einem Thread zu machen aber ich habe auch die ganze Zeit die Wartung bekommen.
Ich habe Thread von der Threading Bibliothek und die Funktion .start() benutzt.