Revpimodio2 - cycle time exeeded? Invalid Ioctl in dmesg?

Moderator: RevPiModIO

Post Reply
Lace
Posts: 10
Joined: 30 Jan 2018, 12:36
Answers: 0

Revpimodio2 - cycle time exeeded? Invalid Ioctl in dmesg?

Post by Lace »

Hallo,

ich bekomme bei der Verwendung von revpimodio2 immer folgende Meldung:

dmesg:

[ 1504.249543] piControl: Invalid Ioctl from python3

Wenn das Programm läuft kommt ständig folgendes:
/usr/lib/python3/dist-packages/revpimodio2/helper.py:477: RuntimeWarning: cycle time of 50 ms exceeded on lock
RuntimeWarning

ich habe den Parameter Cycletime ausgelesen und der ist bei 20ms. Ich habe die Zykluszeit auf 100ms eingestellt aber die Fehlermeldungen kommen weiterhin.
Hat jemand eine Idee?

Hier mein Programm, es liest zyklisch die IOs aus und pusht bei Änderungen die Daten in ein MQTT topic:

Code: Select all

import revpimodio2
import time
import paho.mqtt.client as mqtt
import json

def on_connect(client, userdata, flags, rc):
  print("Connected with result code " + str(rc))

firstcycle = True

mqttClient = mqtt.Client()
mqttClient.on_connect = on_connect
mqttClient.username_pw_set("mqtt","pierburg")
mqttClient.connect("localhost", 1883, 0)

# RevPiModIO Instantiieren
rpi = revpimodio2.RevPiModIO(autorefresh=False,monitoring=True)
rpi.cycletime = 100
rpi.autorefresh_all()

# Strg+C automatisch verarbeiten
rpi.handlesignalend()

# prepare list of inputs of all connected devices
myinputs = dict()
for name in rpi.device:
  if rpi.device[str(name)].position == 0:
    continue
  allinputs = rpi.device[str(name)].get_inputs()
  for thisinput in allinputs:
    myinputs[str(thisinput)] = 0

# cycle loop function
def cycleprg(zyklustools):
  global firstcycle

  # iterate through all inputs and check if value has changed
  # if it has changed or this is the first cycle mqtt publish it
  for k, v in myinputs.items():
    valChanged = False;
    if rpi.io[k].value != v:
      myinputs[k] = rpi.io[k].value
      valChanged = True
    if (valChanged == True) or (firstcycle == True):
      mqttClient.publish("revpi/inputs/"+k,myinputs[k], qos=0,retain=True)
  firstcycle = False
  time.sleep(1)

rpi.cycleloop(cycleprg)
User avatar
RevPiModIO
KUNBUS
Posts: 322
Joined: 20 Jan 2017, 08:44
Answers: 0
Contact:

Re: Revpimodio2 - cycle time exeeded? Invalid Ioctl in dmesg?

Post by RevPiModIO »

Moin Lace!

Das bekommen wir sehr schnell gelöst (fast).

Der Fehler "piControl: Invalid Ioctl from python3" ist leider im piControl Treiber und tritt immer auf, wenn man sich per Python mit dem Prozessabbild verbindet. Daran arbeitet Kunbus - Es tritt ja auch nur einmal bei Programmstart auf.

Zu deinem Programm:
- Variable "firstcycle" kann ganz weg, da kannst du zyklustools.first wunderbar verwenden.
- "rpi.cycletime = 100" kannst du auch entfernen, da man diese beim Aufruf von .cycleloop(...) im Standard auf 50 Millisekunden gesetzt wird. Man kann diese dort mit dem Parameter cycletime setzen rpi.cycleloop(cycleprg, cycletime=100).
(Das könnte ich evtl noch einmal bei mir ändern, dass er bei expliziten setzen diese verwendet)
- Die Laufzeit der Zyklusfunktion darf niemals länger sein, als die Zykluszeit. Da bei dir am Ende ein time.sleep(1) steht, braucht diese Funktion zu lange und die Meldungen werden ausgegeben.

Du hast nun verschiedene Möglichkeiten (aber time.sleep muss weg):
1) cycletime auf 1000 setzen. Die Funktion wird dann exakt einmal pro Sekunde aufgerufen
2) Flankenmerker der cycletools verwenden. Bei 100 ms Zykluszeit wäre der Flankenmerker "flank10c" im ersten Zyklus True und dann erst wieder nach 10 Zyklen (10 * 100ms = 1 Sekunde).

Teste doch einmal diese Änderungen und berichte:

Code: Select all

import revpimodio2
import paho.mqtt.client as mqtt
import json


def on_connect(client, userdata, flags, rc):
  print("Connected with result code " + str(rc))


mqttClient = mqtt.Client()
mqttClient.on_connect = on_connect
mqttClient.username_pw_set("mqtt","pierburg")
mqttClient.connect("localhost", 1883, 0)

# RevPiModIO Instantiieren
rpi = revpimodio2.RevPiModIO(autorefresh=False, monitoring=True)
rpi.autorefresh_all()

# Strg+C automatisch verarbeiten
rpi.handlesignalend()

# prepare list of inputs of all connected devices
myinputs = dict()
for name in rpi.device:
  if rpi.device[str(name)].position == 0:
    continue
  allinputs = rpi.device[str(name)].get_inputs()
  for thisinput in allinputs:
    myinputs[str(thisinput)] = 0


# cycle loop function
def cycleprg(zyklustools):

  if zyklustools.flank10c:
    # Do this every 10 cycles
    # iterate through all inputs and check if value has changed
    # if it has changed or this is the first cycle mqtt publish it
    for k, v in myinputs.items():
      valChanged = False;
      if rpi.io[k].value != v:
        myinputs[k] = rpi.io[k].value
        valChanged = True
      if (valChanged == True) or (zyklustools.first == True):
        mqttClient.publish("revpi/inputs/"+k,myinputs[k], qos=0,retain=True)


rpi.cycleloop(cycleprg, cycletime=100)
Alternativ haben wir MQTT auch in unserem RevPiPyLoad integriert.
https://revpimodio.org/nodered-mqtt/

Gruß, Sven
python3-RevPiModIO - https://revpimodio.org/ || Der RevPi ist das Beste, was passieren konnte!
Lace
Posts: 10
Joined: 30 Jan 2018, 12:36
Answers: 0

Re: Revpimodio2 - cycle time exeeded? Invalid Ioctl in dmesg?

Post by Lace »

RevPiModIO wrote: 02 Sep 2019, 12:46 Der Fehler "piControl: Invalid Ioctl from python3" ist leider im piControl Treiber und tritt immer auf, wenn man sich per Python mit dem Prozessabbild verbindet. Daran arbeitet Kunbus - Es tritt ja auch nur einmal bei Programmstart auf.
Ok. Also hat das schonmal nichts mit dem Problem zu tun
RevPiModIO wrote: 02 Sep 2019, 12:46 Zu deinem Programm:
- Variable "firstcycle" kann ganz weg, da kannst du zyklustools.first wunderbar verwenden.
- "rpi.cycletime = 100" kannst du auch entfernen, da man diese beim Aufruf von .cycleloop(...) im Standard auf 50 Millisekunden gesetzt wird. Man kann diese dort mit dem Parameter cycletime setzen rpi.cycleloop(cycleprg, cycletime=100).
(Das könnte ich evtl noch einmal bei mir ändern, dass er bei expliziten setzen diese verwendet)
- Die Laufzeit der Zyklusfunktion darf niemals länger sein, als die Zykluszeit. Da bei dir am Ende ein time.sleep(1) steht, braucht diese Funktion zu lange und die Meldungen werden ausgegeben.
Ok, hab ich verstanden. Das time.sleep hatte ich nachträglich eingefügt, der Fehler mit der Zykluszeit-Überschreitungswarnung war vorher auch schon da.

Ich bin zwischenzeitlich den Alternativweg über registrierte Events gegangen, den Zykluszeitfehler habe ich dann nicht mehr:

Code: Select all

#!/usr/bin/python3
#
# Requirements:
# sudo apt-get install python3-revpimodio2
# pip3 install paho-mqtt

import revpimodio2
import time
import paho.mqtt.client as mqtt
import json


class RevPiIOtoMQtt():
	def __init__(self):
		self.revpi = revpimodio2.RevPiModIO(autorefresh=True)
		self.revpi.handlesignalend(self.exitfunktion)
		
		self.mqttClient = mqtt.Client()
		
		self.revpi.io.I_1.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_2.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_3.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_4.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_5.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_6.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_7.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_8.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_9.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_10.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_11.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_12.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_13.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_14.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_15.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)
		self.revpi.io.I_16.reg_event(
			self.on_inputevent, edge=revpimodio2.BOTH, prefire=True
		)

	def on_connect(client, userdata, flags, rc):
		print("Connected with result code " + str(rc))

	def exitfunktion(self):
		print("terminate program")

	def on_inputevent(self, ioname, iovalue):
		print(ioname)
		print(iovalue)
		self.mqttClient.publish("revpi/inputs/"+ioname,iovalue, qos=0,retain=True)
			
	def start(self):
		self.mqttClient = mqtt.Client()
		self.mqttClient.on_connect = self.on_connect
		self.mqttClient.username_pw_set("user","password")
		self.mqttClient.connect("localhost", 1883, 0)

		self.revpi.mainloop()
		
if __name__ == "__main__":
	root = RevPiIOtoMQtt()
	root.start()
Post Reply