Arduino über LAN in IPS einbinden (2-Wege Kommunikation)

Hallo allerseits!

Ich hatte ja vor einiger Zeit mein Terrarium auf Arduino-Steuerung umgebaut. Hier nun das Ergebnis mit 2-Wege-Kommunikation :slight_smile:

>>> Download des Sketch am Ende dieses Beitrags

Da man das sowieso nicht 1zu1 übernehmen kann, erkläre ich gar nicht viel dazu. Einfach mal den Code vom Arduino-Sketch anschauen, da sieht man schon was man so anstellen kann :slight_smile:
Aber auf jeden Fall kann man vom IPS über Scripte Befehle an den Arduino senden und dieser schaltet dann z.B. einen Relaiskanal oder ändert Variablen oder liest die Temperatursensoren aus und schickt die Daten zurück ans IPS.

Wenn ihr den Sketch auf euch angepasst und auf euren Arduino geladen habt, dann braucht ihr auf der IPS Seite:


> I/O Instanz > ArduinoXY - ServerSocket - Port 6661
> Darunter eine „Register Variable“ mit diesem Script als Ziel:

<?
$GeraeteName = "Arduino01";
$Kategorie_Arduino01_Vars = 32993 /*[Hardware\Arduino\Arduino01 (Terrarium)]*/;  // Hier eine Kategorie eintragen, in der das Script die entsprechenden Variablen anlegt

if ($_IPS['SENDER'] == "Execute") {
   $Arduino01_ServerSocket = 41007 /*[Arduino01_Terrarium]*/;
   if (IPS_GetParent($_IPS['SELF']) != $Arduino01_ServerSocket) {
		IPS_SetParent(IPS_GetParent($_IPS['SELF']), $Arduino01_ServerSocket);
	}
}


if ($_IPS['SENDER'] == "RegisterVariable") {
	$data = RegVar_GetBuffer($_IPS['INSTANCE']);
   $data .= $_IPS['VALUE'];
   RegVar_SetBuffer($_IPS['INSTANCE'], $data);
   if (strpos($data, '!')) {
		$data = trim($data);
		$data = str_replace("!", "", $data);
      $datasets = explode(':', $data);
		EmpfangeneDatenVerarbeiten($datasets);
		RegVar_SetBuffer($_IPS['INSTANCE'], "");
	}
}


function EmpfangeneDatenVerarbeiten($datasets) {
	$Var = $datasets[0];
	$Wert1 = $datasets[1];
	$Wert2 = @$datasets[2];
	$Wert3 = @$datasets[3];
	//IPS_LogMessage("VAR", $Var);
	//IPS_LogMessage("WERT1", $Wert1);
	//IPS_LogMessage("WERT2", $Wert2);
	//IPS_LogMessage("WERT3", $Wert3);
	
	if ($Var == "Sternenhimmel") {
		if ($Wert1 == "AUS") {
		   $Wert1 = false;
			UpdateIPSvar($Var,$Wert1,0);
		}
		elseif ($Wert1 == "AN") {
		   $Wert1 = true;
			UpdateIPSvar($Var,$Wert1,0);
		}
	}
	elseif ($Var == "T5_Helligkeit") {
		UpdateIPSvar($Var,$Wert1,1);
	}
	elseif ($Var == "VERBUNDEN") {
	   $Var = "Check";
		UpdateIPSvar($Var,true,0);
	}
	elseif ($Var == "Sternenhimmel_Einstellungen") {
	   $Wert = "$Wert1,$Wert2,$Wert3";
		UpdateIPSvar($Var,$Wert,3);
	}
	elseif ($Var == "Relaiskarte") {
	   $Var = "Relaiskarte$Wert1";
	   if ($Wert2 == "AUS") {
		   $Wert2 = false;
		}
		elseif ($Wert2 == "AN") {
		   $Wert2 = true;
		}
		UpdateIPSvar($Var,$Wert2,0);
	}
	elseif ($Var == "TemperaturSensoren_Anzahl") {
		UpdateIPSvar($Var,$Wert1,1);
	}
	elseif ($Var == "TemperaturSensor") {
	   $Var = "$Var$Wert1";
		UpdateIPSvar($Var,$Wert2,2);
	}
}



function UpdateIPSvar($ident,$value,$type) {
	 Global $Kategorie_Arduino01_Vars;
	 $parent = $Kategorie_Arduino01_Vars;
    if (is_int($type))
    {
        $ips_type=$type;
    } else {
        switch ($type)
        {
                 case "i1":
                 case "i2":
                  case "i4":
            case "ui1":
            case "ui2":
            case "ui4":
                $ips_type=1;
                break;
            case "boolean":
                $ips_type=0;
                break;
            case "uuid":
            case "dateTime":
            case "string":
                $ips_type=3;
                break;
            default:
                echo "Unbekannter Datentyp:".$type.PHP_EOL;
                return;
                break;
        }
    }
    $var_id = @IPS_GetObjectIDByIdent($ident,$parent);
    if ($var_id === false)
    {
        $var_id = IPS_CreateVariable($ips_type);
        IPS_SetName($var_id,$ident);
        IPS_SetIdent($var_id,$ident);
        IPS_SetParent($var_id,$parent);
    }
    switch ($ips_type)
    {
        case 0:
           if (GetValueBoolean($var_id) <> (bool)$value)
           {
              SetValueBoolean($var_id,(bool)$value);
           }
           elseif ($ident == "Check") {
              SetValueBoolean($var_id,(bool)$value);
           }
            break;
        case 1:
            if (GetValueInteger($var_id) <> (int)$value)
            {
               SetValueInteger($var_id,(int)$value);
            }
            break;
        case 2:
            if (GetValueFloat($var_id) <> round((float)$value,2))
            {
               SetValueFloat($var_id,round((float)$value,2));
            }
            break;
        case 3:
            if (GetValueString($var_id) <> $value)
            {
               SetValueString($var_id,$value);
            }
            break;
    }
}
?>

Dieses Script legt dann automatisch Variablen an und aktualisiert diese auch.
Arduino_Variablen-Uebersicht.png

Zur Bedienung/Steuerung habe ich mir eine Funktion gebaut, diese sieht wie folgt aus:

<?
//Arduino_Befehl_Senden("Arduino01", "help!");
//Arduino_Befehl_Senden("Arduino01", "Sternenhimmel,AN!");
//Arduino_Befehl_Senden("Arduino01", "Sternenhimmel,AUS!");
//Arduino_Befehl_Senden("Arduino01", "TemperaturSensoren_Anzahl!");
//Arduino_Befehl_Senden("Arduino01", "TemperaturSensor_Abfragen,0!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,1,AN!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,1,AUS!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,2,AN!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,2,AUS!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,3,AN!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,3,AUS!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,4,AN!");
//Arduino_Befehl_Senden("Arduino01", "Relaiskarte,4,AUS!");
//Arduino_Befehl_Senden("Arduino01", "T5_Helligkeit,50!");
//Arduino_Befehl_Senden("Arduino01", "T5_Helligkeit,150!");
//Arduino_Befehl_Senden("Arduino01", "T5_Helligkeit,255!");
//Arduino_Befehl_Senden("Arduino01", "Sternenh_Einstellungen,2,1,10!");


function Arduino_Befehl_Senden($Device, $Befehl) {
	if ($Device == "Arduino01") {
		$InstanzID = 41007 /*[Arduino01_Terrarium]*/;
	}

	if (IPS_SemaphoreEnter($Device, 9000)) {
		$result = @SSCK_SendText($InstanzID, $Befehl);
		if (!$result) {
		   IPS_Sleep(3000);
		   @SSCK_SendText($InstanzID, $Befehl);
		}
		IPS_Sleep(250);
	   IPS_SemaphoreLeave($Device);
	}
}
?>

Die Temperaturen kann ich dann z.B. mit diesem Script, per Timer gesteuert, auslesen:

<?
include 'Arduino.ips.php';

for ($ts = 0; $ts <= 8; $ts++) {
   Arduino_Befehl_Senden("Arduino01", "TemperaturSensor_Abfragen,$ts!");
   IPS_Sleep(800);
}
?>

Die Ausgabe erfolgt sowohl über LAN an den ServerSocket (IPS), als auch per Seriell (falls man USB angeschlossen hat, gut zum Testen).

Bevor einer was sagt, ja, man sollte das Senden auch über die RegVar machen, aber ich kam noch nicht dazu es umzubauen g Und da ich momentan kaum Zeit habe und alles läuft, bleibt es erstmal so :slight_smile:

Sooo…hab ich was vergessen? Ich hoffe nicht :slight_smile: Viel Spaß damit :slight_smile:

Grüße,
Chris


!!! ACHTUNG !!! BENUTZUNG AUF EIGENE GEFAHR !!! ERST AUF EUCH ANPASSEN !!!

Arduino-Sketch_Terrarium_v1.5.zip (3.9 KB)

Damit man auch immer weiß, ob der Arduino noch lebt und auch brav auf Befehle reagiert, habe ich eine kleine Überwachung gebaut.

Dazu sende ich einen Befehl an den Arduino und dieser meldet ein OK zurück, sofern er kann :smiley: Wenn die Meldung bestätigt wird vom Arduino ist die Variable auf OK, kommt nichts zurück für eine bestimmte Zeit, dann steht die Variable auf Störung. Ob man sich dann eine Push-Nachricht senden lässt oder was auch immer macht, das bleibt euch selbst überlassen :slight_smile:

Arduino_Ueberwachung.png

Script-Inhalt:

<?
include 'Arduino.ips.php';

$ArduinoVerbindungOK = 50982 /*[Skripte & Variablen\Arduino\Arduino01\Überwachung der Kommunikation\Stoerung]*/;


if (@IPS_GetName($_IPS['EVENT']) == "Terrarium_Hauptschalter_AUS_3Uhr") {
   AktorSteuerung('Terrarium_Hauptschalter', 'SPERRE', 'AUS');
	AktorSteuerung('Terrarium_Hauptschalter', 'AUS');
	SetTimerByName_UhrzeitStunde($_IPS['SELF'], "Terrarium_Hauptschalter_AUS_3Uhr", false);
}
elseif (@IPS_GetName($_IPS['EVENT']) == "Terrarium_Hauptschalter_AN_4Uhr") {
	AktorSteuerung('Terrarium_Hauptschalter', 'AN');
	SetTimerByName_UhrzeitStunde($_IPS['SELF'], "Terrarium_Hauptschalter_AN_4Uhr", false);
}
else {
   Arduino_Befehl_Senden("Arduino01", "helo!");
   $CheckVar_ID = IPS_GetVariableIDByName("Check", 32993 /*[Hardware\Arduino\Arduino01 (Terrarium)]*/);
	$CheckVar = IPS_GetVariable($CheckVar_ID);
	$CheckVar_LastUpdatedTime = $CheckVar['VariableUpdated'];
	$TimeAktuell = time();
	$TimeDiff = $TimeAktuell - $CheckVar_LastUpdatedTime;
	IPS_Sleep(2000);
	echo $TimeDiff;

	if ($TimeDiff > 900) {
		SetValue($ArduinoVerbindungOK, false);
	   SetTimerByName_UhrzeitStunde($_IPS['SELF'], "Terrarium_Hauptschalter_AUS_3Uhr", 3);
	   SetTimerByName_UhrzeitStunde($_IPS['SELF'], "Terrarium_Hauptschalter_AN_4Uhr", 4);
	}
	else {
		SetValue($ArduinoVerbindungOK, true);
		SetTimerByName_UhrzeitStunde($_IPS['SELF'], "Terrarium_Hauptschalter_AUS_3Uhr", false);
		SetTimerByName_UhrzeitStunde($_IPS['SELF'], "Terrarium_Hauptschalter_AN_4Uhr", false);
	}
}



function SetTimerByName_UhrzeitStunde($parentID, $name, $Stunde) {
	Global ${$_IPS['SELF']};
   $eid = @IPS_GetEventIDByName($name, $parentID);
   if($eid === false) {
	   $eid = IPS_CreateEvent(1);
      IPS_SetParent($eid, $parentID);
      IPS_SetName($eid, $name);
      IPS_SetInfo($eid, "this timer was created by script #".$_IPS['SELF']);
   }
   if ($Stunde === false) {
      IPS_SetEventActive($eid, false);
   	return $eid;
   }
   else {
   	IPS_SetEventCyclicTimeFrom($eid, $Stunde, 0, 0);
   	IPS_SetEventActive($eid, true);
   	return $eid;
	}
}
?>

Eigentlich ein interessantes Projekt… ich müsste wohl nur die Led-Sache von dem Rest etwas abstrahieren. Hilfreich wäre natürlich, wenn du noch auflistest welche HW du bei dem Projekt mit dem Arduino verwendest/anhängst… also welche Temperatursensoren aber insbesondere Nachthimmel Led etc… auch ein kleiner Schaltplan vom Arduino wo du was anhängst wäre natürlich noch schöner :slight_smile: Naja man will ja immer alles gelle. aber aktuell würde mir die Sache mit dem Lichthimmel reichen :-)=

Abend!
Ich hatte einen schönen Plan der Platine am Computer erstellt, aber bevor ich alles speichern konnte ist das Programm gecrasht :frowning: Deshalb gibt es nur einen Ausdruck mit etwas Gekritzel und das wars :smiley:

Aber an sich nichts wildes. Die extra Platine mit den Mosfet musste ich nur machen, weil ich 4 x 10 LED parallel gemacht habe und die mit 12V laufen.

Grob gesagt 4 x PWM vom Arduino auf 4 x Mosfet, das ganze mit 12V versorgt, paar Widerstände, fertig :slight_smile:

Und die 1-Wire Leitung (Temperatursensoren fertig in einer Fühlerspitze mit Schrumpfschlauch und bissi Kabel dran, im 10er Pack, für kleines Geld) hab ich auch nur über die Platine gemacht, damit ich schöne Schraubklemmen habe und der notwendige Widerstand auch direkt mit auf der Platine ist…

Ich werd die Tage mal sehen, was ich noch an Infos und Fotos finde und das mal posten. Aber einfach 1:1 „kopieren“ wird wohl nichts :wink:

Schau ma mal, melde mich die Tage…

Grüße,
Chris