Zuverlässigkeit von Timern auf Raspberry Pi

Hallo,

ich habe festgestellt, dass die Ausführung eines sekündlichen Timers auf einem RaspberryPi nicht ganz zuverlässig ist.
Ich habe ein Skript, dass lediglich den Wert einer Variablen ausliest, 1 addiert und den neuen Wert wieder in die Variable schreibt. Das Skript wird über einen Timer jede Sekunde ausgeführt.
In der Datenbank sieht man aber, dass ca. alle 40 Sekunden der Timer nicht sekündlich ausgeführt wurde:

1445642671 2560
1445642672 2561
1445642674 2562
1445642675 2563
1445642676 2564
1445642676 2565
1445642677 2566

Beim ersten Mal tritt scheinbar eine Verzögerung auf. Dass dies passieren kann, ist mir klar, wenn z.B. alle PHP Threads belegt sind oder wenn die Skriptausführung zu lange dauer (beides sollte aber in meinem Testfall keine Rolle spielen).

Beim zweiten Mal gibt es allerdings 2 Einträge für eine Sekunde, demzufolge der Timer schon nach weniger als einer Sekunde wieder ausgeführt wurden musste.

Ist dies ein generelles Problem beim Rasperry (wegen der der geringen Leistung o.ä.) oder woran kann das Problem noch liegen?

Hat etwas länger gedauert, aber ich hatte nun eine Idee woran es liegen kann und der Fehler sollte im nächsten Update korrigiert sein!

Danke fürs melden!

paresy

Hm,

habe da auch gerade ein Problem mit den Timer :
Auszug :

   $Einschaltzeit=abs($y);
    IF ($Einschaltzeit <= 2) {
	 	$Einschaltzeit = 2;
	 }
    IF ($Einschaltzeit >= 20) {
	 	$Einschaltzeit = 20;
	 }

IPS_SetEventCyclic($EinschaltzeitID, 0, 0, 0, 0, 1 ,$Einschaltzeit);


if (IPS_GetName($_IPS['EVENT'])=='Einschaltzeit') {
		//Netzrelais aus
   	if ($Hand == 0)  { //Automatik ist an
			exec ('echo "1" > /sys/class/gpio/gpio17/value');
	      SetValueInteger($MischerID, 1); //Stop
		}
      IPS_SetEventActive($EinschaltzeitID,false);
      IPS_SetEventActive($WartezeitID,true);
  }

Das Skript wird alle 15 Sekunden aufgerufen, und der Timer Einschaltzeit wird mit dem berechneten Wert gestartet.
Wenn da jetzt 2 Sekunden drin ist, wird Timer um Sekunde 0 und Sekunde 30 richtig ausgeführt, bei Sekunde 15 und Sekunde 30 läuft der Timer aber statt 2 Sekunden nur 1 Sekunde.
Das verstehe ich nicht…

Habe gerade den Wartezeit Timer auf 16 Sekunden geändert, dann klappt es mit den 2 Sekunden

Ich verstehe gar nicht, was das Skript machen soll!?

paresy

Steuert dynamisch meinen Mischermotor an der Heizung, kleinste Taktzeit ist 2 Sekunden, max Taktzeit 14 Sekunden, wird berechnet von der Temperaturdifferenz Sollwert - Istwert.
Hier mal das ganze Skript :

<?
///$Kp=1.5;//1.1; // 5 Kp = Verstärkungsfaktor Proportionalregler
$Ki=1; //2.5 Ki = Verstärkungsfaktor Integralregler
$Kd=1; //0 Kd = Verstärkungsfaktor Differenzialregler


$EinschaltzeitID = IPS_GetObjectIDByName("Einschaltzeit", ($_IPS['SELF']));
$WartezeitID = IPS_GetObjectIDByName("Wartezeit", ($_IPS['SELF']));
$actionID = IPS_GetObjectIDByName("Zustand", IPS_GetParent($_IPS['SELF']));
$VorherigeRegelabweichungID = IPS_GetObjectIDByName("Regelabweichung", IPS_GetParent($_IPS['SELF']));
$HystereseID = IPS_GetObjectIDByName("Hysterese",  IPS_GetParent($_IPS['SELF']));
$MischerID = IPS_GetObjectIDByName("Mischer",  IPS_GetParent($_IPS['SELF']));
$SteilheitID = IPS_GetObjectIDByName("Steilheit", IPS_GetParent($_IPS['SELF']));
$Korrektur_MischerID = IPS_GetObjectIDByName("Korrektur_Mischer", IPS_GetParent($_IPS['SELF']));
$PumpeID = IPS_GetObjectIDByName("Pumpe", IPS_GetParent($_IPS['SELF']));
$KpID = IPS_GetObjectIDByName("Verstärkungsfaktor Proportionalregler", IPS_GetParent($_IPS['SELF']));
$min_MischerID = IPS_GetObjectIDByName("Mischer Min", IPS_GetParent($_IPS['SELF']));
$max_MischerID = IPS_GetObjectIDByName("Mischer Max", IPS_GetParent($_IPS['SELF']));
$WartezeitVarID = IPS_GetObjectIDByName("Wartezeit", IPS_GetParent($_IPS['SELF']));

$id = IPS_GetParent($_IPS['SELF']);
$id2= IPS_GetParent($id);
$id3= IPS_GetObjectIDByName("Regler Aussentemperatur", $id2);
$HandID = IPS_GetObjectIDByName("Hand_Auto", $id3);
$UhrID = IPS_GetObjectIDByName("Uhr Heizung", $id3);
$Soll_TagID = IPS_GetObjectIDByName("Soll Tag", $id3);
$Soll_NachtID = IPS_GetObjectIDByName("Soll Nacht", $id3);
$IstTemperaturAussenID = IPS_GetObjectIDByName("Temperatur_Aussen", $id3);

$Aussentemp=GetValueFloat($IstTemperaturAussenID);
$Soll_Tag = GetValue($Soll_TagID);
$Soll_Nacht = GetValue($Soll_NachtID);
$Hand = GetValue($HandID);
$Uhr = GetValue($UhrID);

//var_dump ($Hand);
$Soll_Temperatur_MischerID = IPS_GetObjectIDByName("Soll_Temperatur_Mischer", IPS_GetParent($_IPS['SELF']));
$IstTemperaturID = IPS_GetObjectIDByName("Temperatur", IPS_GetParent($_IPS['SELF']));
$Hysterese =GetValueFloat($HystereseID);
$Steilheit = GetValue($SteilheitID);
$Korrektur_Mischer = GetValue($Korrektur_MischerID);
$Kp = GetValue($KpID);
$min_Mischer = GetValue($min_MischerID);
$max_Mischer = GetValue($max_MischerID);
$Wartezeit = GetValue($WartezeitVarID);

IPS_SetEventCyclic($WartezeitID, 0, 0, 0, 0, 1 ,$Wartezeit);

if ($Hand == 0)  { //Automatik ist an

	if ($Uhr == 1)  {
		$Raumsollwert= $Soll_Tag ;//12 Nacht
		} else{
		$Raumsollwert= $Soll_Nacht ;//12 Nacht
	}
//Sommer, Pumpe aus, Kessel aus, Mischer zu
   if ($Aussentemp < $Raumsollwert ) {
      exec ('echo "0" > /sys/class/gpio/gpio23/value'); // Pumpe ein
		$Vorlauftemperatur_Mischer=min(max(round((0.55*$Steilheit*(pow($Raumsollwert,($Aussentemp/(320-$Aussentemp*4))))*((-$Aussentemp+20)*2)+$Raumsollwert+$Korrektur_Mischer)*1)/1,$min_Mischer),$max_Mischer);
		SetValueFloat($Soll_Temperatur_MischerID, $Vorlauftemperatur_Mischer);
     } else{
// Ausentemp grösserr Raumsollwert
     exec ('echo "1" > /sys/class/gpio/gpio23/value');// Pumpe aus
     SetValueFloat($Soll_Temperatur_MischerID,$min_Mischer);//Wert anpassen !!!!!
     }
}

$e = (GetValueFloat($Soll_Temperatur_MischerID)- GetValueFloat($IstTemperaturID));
// Die Berechnung des neuen Regelwertes
//$y = ($Kp * $e + $Ki * $Ta * $esum + $Kd * ($e - $ealt) / $Ta);
$y = $Kp * $e;
$Einschaltzeit=$y;

if ($Hand == 1)  { //Hand ist an
	$action = 'Hand';
}

SetValueFloat($VorherigeRegelabweichungID, $y);
   $Einschaltzeit=abs($y);
    IF ($Einschaltzeit <= 2) {
	 	$Einschaltzeit = 2;
	 }
    IF ($Einschaltzeit >= 14) {
	 	$Einschaltzeit = 14;
	 }

IPS_SetEventCyclic($EinschaltzeitID, 0, 0, 0, 0, 1 ,$Einschaltzeit);


if (IPS_GetName($_IPS['EVENT'])=='Einschaltzeit') {
		//Netzrelais aus
   	if ($Hand == 0)  { //Automatik ist an
			exec ('echo "1" > /sys/class/gpio/gpio17/value');
	      SetValueInteger($MischerID, 1); //Stop
		}
      IPS_SetEventActive($EinschaltzeitID,false);
      IPS_SetEventActive($WartezeitID,true);
  }

if (IPS_GetName($_IPS['EVENT'])=='Wartezeit') {
    $Soll_VL = GetValue($Soll_Temperatur_MischerID);
    $Ist_VL = GetValue($IstTemperaturID);
	 if ($Hand == 0)  { //Automatik ist an
		    $action = 'Idle';
		    if ($Ist_VL < ($Soll_VL - $Hysterese) ) $action = 'Auf';
		    if ($Ist_VL > ($Soll_VL + $Hysterese) ) $action = 'Zu';

		//    if (GetValue(32015 /*[Objekt #32015 existiert nicht]*/) == False)    $action = 'Idle';

		    Switch ($action){

		        Case 'Idle':
		        break;

		        Case 'Zu':
					//Richtungsrelais aus
					exec ('echo "1" > /sys/class/gpio/gpio27/value');
		         //Netzrelais ein
					exec ('echo "0" > /sys/class/gpio/gpio17/value');
					SetValueInteger($MischerID, 3); //Zu
		        break;

		        Case 'Auf':
					//Richtungsrelais ein
					exec ('echo "0" > /sys/class/gpio/gpio27/value');
					//Netzrelais ein
					exec ('echo "0" > /sys/class/gpio/gpio17/value');
					SetValueInteger($MischerID, 0); //Auf
		        break;
 		     }
    }
    SetValueString($actionID,$action);
    IPS_SetEventActive($EinschaltzeitID,true);
    IPS_SetEventActive($WartezeitID,false);
}

$x = intval(exec ('cat /sys/class/gpio/gpio23/value'));
if ($x == 1){ $x=0;} else { $x=1; }
SetValueBoolean($PumpeID,$x);

//}

?>

Kurze Rückmeldung: Das Problem scheint nun nicht mehr aufzutreten.
Vielen Dank!