Ausgang per Web schalten mit PHP

Hallo,
allerseits, ich versuche mich gerade daran, den Digitalen Pin3 per Webseite An bzw. Aus zuschalten.

Arduino Ethernet -->Webserver -->PHP-Seite mit Button AN und AUS

Mein Problem ist, mal wieder der Anfang, einen Sketch habe ich schon angefangen, aber ob er funktioniert weiß ich nicht, weil ich nicht weiß wie die PHP Seite aus sehen muss :blush:
Ich dachte da an GET oder so,aber mehr weiß ich auch nicht..
Mein Sketch bisher sieht so aus:

/*
  Webclient
  Es soll mittels einer PHP-Seite, die auf einem Webserver liegt,
  ein oder mehrere Ausgänge AN/AUS geschaltet werden.
*/

#include <SPI.h>
#include <Ethernet.h>

// Ethernet einrichten
byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0xEE, 0xF3 }; // Mac-Adresse Arduino Ethernet
byte ip[] = {192,168,178,230}; // IP-Adresse Arduino Ethernet
byte gateway[] = {192,168,178,1}; // Gateway 
byte subnet[] = {255,255,255,0}; 
IPAddress server(192,168,178,111); // IP-Adresse Server
char host[] = "192.168.178.111\n"; // Host Name oder IP-Adresse

EthernetClient client;  // Initialisierung der Ethernet client library

char url[]  = "/arduino/ausgang.php";	// Pfad zur PHP-Datei eingeben
char c;
int Pin3 = 3;

String readString = String(100); 

boolean Pin3ON = false;

void setup()
{
  Serial.begin(9600);
  pinMode(Pin3, OUTPUT);
  Serial.println("verbinde...");
  Ethernet.begin(mac, ip, gateway, subnet);
}

void loop()
{
  if (client.connect(server, 8000)) // Serverport bei mir 8000 bei bedarf ändern
  {
    char c = client.read();
    Serial.print(c);
  } 
  
  if (readString.length() < 100)
 {
  readString = readString + c;
 }
Serial.print(c);  //output chars to serial port
        if (c == '\n') {
if(readString.indexOf("3=einschalten") > -1) {
   digitalWrite(Pin3, HIGH);
    Serial.println("Pin 3 eingeschaltet!");
     Pin3ON = true;
}
if(readString.indexOf("3=ausschalten") > -1){
   digitalWrite(Pin3, LOW);
    Serial.println("Pin 3 ausgeschaltet!");
     Pin3ON = false;
}
}
 //clearing string for next read
 readString="";
 
 client.stop();
 client.flush();
}

Kann mir jemand Helfen ?

Ich würde mal sagen, falscher Ansatz. Wenn schon ein Webserver da ist, dann doch folgendermassen:

Browser <--> Webserver (PHP/HTML) <--> Arduino

Alternativ nur der Arduino als Webserver, aber wie da die Limits sind, haben wir ja schon gelernt :slight_smile:

Als erstes bastelst Du Dir mit PHP und HTML auf dem Webserver ein Webseite, mit der Du den Zustand z.B. einer LED abbildest und per Link oder Button den Zustand umschalten kannst. Das alles noch komplett ohne den Arduino.

Wenn das funktioniert, bringst Du Deinem PHP-Script bei, mit dem Arduino zu "reden". Dabei kannst Du auf den ganzen HTML-Kram verzichten und nur die wesentlichen Daten übertragen.
Du kannst z.B. mit PHP eine TCP-Verbindung zum Arduino aufbauen und schickst erstmal nur ein Zeichen
'S' -> (SET) setze wert
'R' -> (READ) lese wert

danach folgt z.b. die nummer des Pins als byte (z.b. 3 Wert, nicht das Zeichen '3')
beim Setzen des Wertes kommt noch ein drittes Byte, mit dem Wert.
Damit kannst Du aus mit 3 Bytes schon alle Pins setzen ('S',0x03,0x01)

Auf dem Arduino liest Du einfach Zeichenweise aus der Verbindung in ein Array

//Achtung super simpler Quickhack ohne Püfung der Eingabe oder ob Daten vorhanden sind
char input[3];
 
for(int i=0;i<3;i++) {
    input[i] = client.read();    
}

//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
}
//pin lesen und an den Client schicken
if(input[0] == 'R') {
   client.print(digitalRead(input[1]));
}

Die Lösung ist zwar für den Anfang komplexer, als nur der Arduino zu nehmen, dafür aber deutlich flexibler. Der Browser muss nicht mit dem Arduino reden, sondern nur mit dem Webserver. Wie der Webserver dann mit dem Arduino redet, ist für den Nutzer am Browser aber egal. Und Du kannst Die Seite auf dem Webserver so bunt und schick machen, wie Du lustig bist. Es gibt keine Limitierungen wie beim Arduino-Webserver.

Moin Moin,
ok, dann lege ich mal los (habe gerade irgendwie zwei sachen gleichzeitig, am machen...grrr)
Dane für deine schnelle Antwort und die Tips, setzte mich erstmal hin und zaubere eine PHP-Site.

Die Lösung ist zwar für den Anfang komplexer, als nur der Arduino zu nehmen, dafür aber deutlich flexibler.

Genau was ich brauche, Komplex aber super flexibel :smiley:
Versuche dann mal deine Tips und Ratschläge umzusetzten, so macht das richtig Spaß und man lernt...

Achso, hintergrund des ganzen ist, ich habe ein 8fach Relais von Sainsmart, womit ich meine Bewässerungsventile (24V) steuern möchte. UNd das ganze natürlich von ÜBERALL :grin:

Coole, wäre dann natürlich noch eine Zeitspanne die man festlegen kann, wie lange ein Ventil geöffnet sein soll. Aber erstmal eins nach dem anderen....

Bin dann mal im dunklen kämmerlein....... 8)

So da bin ich wieder...
Leider nicht so erfolgreich wie ich dachte :frowning:
Der Beispiel-Code der Webseite sieht jetzt so aus :

<html>
 <head>
  <title>Ventile schalten</title>
 </head>
 <body>
<table border="1">
  <tbody>
    <tr>
      <td>V_1</td>
      <td>V_2</td>
    </tr>
    <tr>
      <td><form action="test1.php" method="post" target="_self">
          <select name="Zeit_V1[]">
  	  <option value="15">15 min</option>
  	  <option value="30">30 min</option>
  	  <option value="60">60 min</option>
  	  </select>
  	  <input type="submit" name="senden" maxlength="10" value="Starten">
	  <input type="reset" name="stop" value="Stop" align="middle">
 	  </form>
     </td>
      <td><form action="test1.php" method="post">
          <select name="Zeit_V2[]">
 	  <option value="15">15 min</option>
	  <option value="30">30 min</option>
	  <option value="60">60 min</option>
	  </select>
	  <input type="submit" name="senden" maxlength="10" value="Starten">
	  <input type="reset" name="stop" value="Stop" maxlength="10" align="middle">
	  </form>
     </td>
    </tr>
    <tr>
      <td><?php
$auswahl1 = $_POST['Zeit_V1'];
for($i=0;$i<count($auswahl1);$i++)
{
 echo $auswahl1[$i] . '&nbsp;min wurden gestartet';
}
if (!$auswahl1) {
echo "Ventil zu";
}
?></td>
      <td>
<?php
$auswahl2 = $_POST['Zeit_V2'];
for($i=0;$i<count($auswahl2);$i++)
{
 echo $auswahl2[$i] . '&nbsp;min wurden gestartet';
}
if (!$auswahl2) {
echo "Ventil zu";
}
?>
</td>
    </tr>
  </tbody>
</table>
</body>
</html>

Aber weiter weiß ich jetzt auch nicht...
Ich steh-gerade-wie-ein-Ochs-vorm-Berg, wie soll ich weiter machen? :blush:

Du kannst z.B. mit PHP eine TCP-Verbindung zum Arduino aufbauen und schickst erstmal nur ein Zeichen
'S' -> (SET) setze wert
'R' -> (READ) lese wert

Ich versteh gerade nicht ganz wo ich das reinsetzten soll...
Bitte Mario, kannst du mir nochmal weiter Helfen... :blush:

Zum Senden an den Arduino kannst Du erstmal folgende einfache Funktion verwenden.

<?php
$arduino_ip="192.168.111.5";
$arduino_port="8088";

function arduino_send($ip,$port,$command) {
    $res = fsockopen($ip,$port);
    if($res) {
        fwrite($res,$command);
        return fread($res,1);
    } else {
        echo "Fehler, Kommando konnte nicht abgesetzt werden";
    }
}
?>

Aufgerufen wird die z.B. mit

arduino_send(192.168.111.5,8088,'S'.chr(9).chr(1));

Das erste ist die IP, dann der Port auf dem der Arduino lauscht. Danach der Kommando
S ist der Befehl zum "Setze Pin"
chr(9) schreibt das Byte 0x09 in den String, das ist die Pin -Nummer
chr(1) schreibt das Byte 0x01 in den String, das ist der Wert.

Den übermittelten Befehl musst Du dann auf dem Arduino auswerten wie bereits vorgeschlagen.

In Deinem PHP-Code werde ich aber noch nicht so recht schlau. Du hast zwei unabhängige Formulare gebaut, damit werden immer nur die Daten von einem Formular abgeschickt, jenachdem welchen Submit-Button Du anklickst.
Die Schleife

$auswahl1 = $_POST['Zeit_V1'];
for($i=0;$i<count($auswahl1);$i++)
{
 echo $auswahl1[$i] . '&nbsp;min wurden gestartet';
}

verstehe ich aber nicht. Es kann immer nur ein Wert übermittelt werden, warum dann das Array und eine Schleife die immer nur einmal durchlaufen wird?
Wenn das später mehr als ein Ventil werden soll, dann bau den Code dafür auch erst später. Jetzt geht es ja erstmal nur um die Kommunikation Webserver <-> Arduino.

Immer schön an KIS denken: Keep It Simple!
Mario.

Moin,
so nach stundenlangen rumprobieren und nicht verstehen, gebe ich auf =(
Ich verstehe es irgendwie nicht. Also, ich habe jetzt mal alles was ich vorher gepostet habe, weggelassen nd ganz Neu angefangen. Mit einer PHP Seite, mit deinem Code:

<?php
$arduino_ip="192.168.178.216";
$arduino_port="8088";

function arduino_send($ip,$port,$command) {
    $res = fsockopen($ip,$port);
    if($res) {
        fwrite($res,$command);
        return fread($res,1);
    } else {
        echo "Fehler, Kommando konnte nicht abgesetzt werden";
    }
}
?>

Was mir auffällt, bei dem Befehl "$command" wird nirgends gesagt was der machen soll, oder verstehe ich das falsch ?
Ich würde folgende noch eintragen: $command = "'S'.chr(3).chr(1)";

Und was ich nicht verstehe, wie ich deinen Befehl-Vorschlag aufrufen soll ?

Aufgerufen wird die z.B. mit

arduino_send(192.168.178.216,8088,'S'.chr(3).chr(1));

Soll das als HTML-Link dienen? (LINK)

Mein Sketch sieht so aus (vermutlich auch falsch :blush: ) :

#include <SPI.h>
#include <Ethernet.h>

// Ethernet einrichten
byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0xEE, 0xF3 }; // Mac-Adresse Arduino Ethernet
byte ip[] = {192,168,178,216}; // IP-Adresse Arduino Ethernet
byte port[] = {8088};
EthernetClient client;  // Initialisierung der Ethernet client library

int Pin3 = 3;
char input[3];

void setup()
{
  Serial.begin(9600);
  pinMode(Pin3, OUTPUT);
  Serial.println("verbinde...");
  Ethernet.begin(mac, ip, port);
}

void loop()
{
 for(int i=0;i<3;i++) {
    input[i] = client.read();    
}

//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
}
//pin lesen und an den Client schicken
if(input[0] == 'R') {
   client.print(digitalRead(input[1]));
} 
}

Ich habe das Gefühl, ich habe den Fadeb verloren...
Sorry, aber irgendwann merkt man halt, das man Anfänger ist :disappointed_relieved:

Ok, ich versuche es nocheinmal schrittweise zu erklären.
Versuche evtl. erstmal Dich von der "Gesamtvorstellung" zu lösen und vergiss erstmal den Arduino. Vielleicht wird es dann einfacher.

  1. Du willst eine Webseite bauen, mit der Du einer oder mehrere Variablen einen Zustand vorgeben willst. Sagen wir z.B. mal, Du hast die Variablen $led1, $led2, $led3. Jede dieser Variablen kann den Zustand 1 oder 0 annehmen. Das ganze wird zunächst in einem HTML-Formular umgesetzt:
<form action="">
  <p>
    <input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >aus -  <input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >an

    <input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >aus -  <input type="radio" name="led2" value="1" <?php if($led2==1) echo "checked" ?> >an

    <input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >aus -  <input type="radio" name="led3" value="1" <?php if($led3==1) echo "checked" ?> >an

  </p>
  <input type="submit" name="submit" value="Abschicken">
</form>

Der PHP-Code " <?php if($led1==0) echo "checked" ?>" sorgt dafür, das abhängig vom jeweiligen Wert der Variable der entsprechende Radio-Button ausgewählt ist.
Du musst nun noch den Code für das Auswerten des Formulars drum herum bauen. Versuch erstmal soweit zu kommen, das Du beim Abschicken des Formulars danach die entsprechenden Buttons wieder korrekt ausgwählt angezeigt bekommst. Sich die Webseite sozusagen den Zustand merkt. Das sollte nicht weiter schwierig sein.

  1. Die definiert Funktion arduino_send($ip,$port,$command) verwendest Du wie jede andere Funktion in PHP. Zum Beispiel im Daten in eine Datei zu schreiben oder aus einer Datei zu lesen. Nur das hier die Daten nicht in einer Datei landen, sondern an den Arduino geschickt werden. Das Prinzip ist aber genau das Gleiche. Dein PHP-Script verwendet eine "Schnittstelle" mit Hilfe der Funktion um Daten an ein "Medium" zu senden. Ob das eine Datei ist, oder Dein Arduino ist dabei egal. Statt z.B. "led1=0;led2=1;led3=1" in eine Datei "/tmp/daten.txt" zu schreiben (fopen() ... fwrite() ... fclose()) verwendest Du nun die Funktion arduino_send() um den Zustand Deiner Variablen an den Arduino zu schicken. Der Vorgang, die Daten in ein Format zu bringen, das Dein Arduino lesen kann, nennt man "Codieren". Du definierst also ein Format, das dem Zweck entspricht, den Du erreichen willst. In Deinem Fall ist das Format "1. Zeichen definiert ob setzen oder lesen eines Pins (S oder R)", "2.Zeichen definiert welcher Pin betroffen ist", "3.Zeichen definiert den Wert der evtl. gesetzt werden soll.
    Um Dir die Programmierung auf dem Arduino zu erleichtern, wenden IMMER 3 Bytes/Zeichen übertragen, auch wenn Du beim Lesen eigentlich kein 3. Zeichen brauchst. Dein Format das Du so definiert hast nennt man auch "Protokoll" (so wie HTTP für HyperText Transfer Protocol" steht. Es legt fest nach welchen Regeln die Daten übermittelt werden. Dein Aruino sendet dann immer genau ein Byte als Ergebnis zurück. Beim Lesen den Wert des Pins der für den Pin gerade gesetzt ist und beim Setzen den Wert der gesetzt wurde.
    Die Funktion "arduino_send()" baust Du nun in dein funktionierendes!!! PHP-Script ein. Also erst, wenn Punkt 1 angearbeitet ist. Das ist wichtig, denn wenn etwas nicht funktioniert musst Du nicht erst prüfen ob das PHP-Script die Eingaben vom Browser korrekt verabreitet, sondern kannst den Fehler bereits auf die Änderungen bezüglich Daten senden einschränken.

  2. Dein Arduino muss die Daten verarbeiten. Als Basis kannst Du den Chat-Server Sketch aus den Beispielen der IDE nehmen, der enthält bereits alles was Du brauchst um auf ankommende Verbindungen zu warten, Daten aus der Verbindung zu lesen und etwas an den Client (in dem Fall dann Dein PHP-Script auf dem Webserver, nicht der Browser der die Webseite aufruft) zu antworten.
    Da das Protokoll sagt, das immer 3 Bytes gesendet werden, musst DU nur warten bis ein Client kommt (PHP-Script) und genau 3 Bytes aus der Verbindung lesen und diese verarbeiten. 1. Byte sollte "S" oder "R" sein. Das 2. Byte ist die Nummer des Pins und das 3. Byte der Wert. Wenn "S" dann setze das Pin mit der übermittelten Nummer auf den übermittelten Wert und schreibe diesen Wert auch zurück an den Client (wie im Protokoll definiert). Wenn "R", dann ignoriere den übermittelten Wert einfach und schicke an den Client den aktuellen Wert des Pins zurück. Danach beende die Verbindung mittles client.close(); Damit weiss dann auch Dein PHP-Script (Funktion arduino_send()) das die Übertragung abgeschlossen ist.

Das ist "eigentlich" schon alles. Wichig ist das schrittweise vorgehen. Erst wenn ein Schritt funktioniert, dann den nächsten angehen. Bei Schritt 2, reagiert Dein Arduino ja noch nicht wirklich. Daher macht es da z.B. Sinn statt des tatsächlichen Sendens in der Funktion nur mit "echo" auszugeben was gemacht werden würde. Somit kannst Du auf der Webseite prüfen, ob sich Dein Script so verhält wie Du es erwartest. Wenn das dann klappt, machst Du mit Schritt 3 weiter. Wenn Dein Sketch sich dann compilieren und auf den Arduino spielen läßt, dann kannst Du im PHP-Script tatsächlich Daten senden.

Ich hoffe dieser kleine "Roman" hat ein wenig zum besseren Verständnis beigetragen.
Mario.

Hallo Mario,
vielen Dank,
Alles gelöscht und vergessen, werde jetzt mal von vorn anfangen...
Aber ich scheitere schon bei der ersten Aufgabe... =(
Ich glaube es ist schon zu spät und der Kopf zu voll :blush:
Oder ich bin einfach zu blöd, das zuverstehen.

Ok, ich versuche es nocheinmal schrittweise zu erklären.
Versuche evtl. erstmal Dich von der "Gesamtvorstellung" zu lösen und vergiss erstmal den Arduino. Vielleicht wird es dann einfacher.

  1. Du willst eine Webseite bauen, mit der Du einer oder mehrere Variablen einen Zustand vorgeben willst. Sagen wir z.B. mal, Du hast die Variablen $led1, $led2, $led3. Jede dieser Variablen kann den Zustand 1 oder 0 annehmen. Das ganze wird zunächst in einem HTML-Formular umgesetzt:
    Code:

>aus - >an

<input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >aus - <input type="radio" name="led2" value="1" <?php if($led2==1) echo "checked" ?> >an

<input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >aus - <input type="radio" name="led3" value="1" <?php if($led3==1) echo "checked" ?> >an

Der PHP-Code " <?php if($led1==0) echo "checked" ?>" sorgt dafür, das abhängig vom jeweiligen Wert der Variable der entsprechende Radio-Button ausgewählt ist.
Du musst nun noch den Code für das Auswerten des Formulars drum herum bauen. Versuch erstmal soweit zu kommen, das Du beim Abschicken des Formulars danach die entsprechenden Buttons wieder korrekt ausgwählt angezeigt bekommst. Sich die Webseite sozusagen den Zustand merkt. Das sollte nicht weiter schwierig sein.

Verstehe ich nicht .. Wenn ich deinen Code in eine HTML-Seite einbaue und dann den submit button drücke, merk er sich doch den zustand, oder verstehe ich mal wieder Bahnhof ??
Ok, ich gehe jetzt mal schlafen und versuche morgen mal mit einem leeren/freien Kopf an die Sache ranzugehen... :sleeping:

Dir eine ruhige Nacht und nochmal vielen Dank...

Das Problem ist einfach. Wenn Du das Formular im Browser abschickst, dann werden die Werte übertragen, die Du im Formular eingegeben hast.
Also z.B. led1=0;led2=1 und led3=1, weil Du die entsprechenden Radio-Buttons so angeklickt hast.
Dein PHP-Script kann also diese Daten auswerten.
Am Ende wird dann das Formular wieder ausgegeben. Wenn Du dabei nicht den eben übermittelten Zustand wieder setzt, wird im Browser das Formular wieder alle Radio-Buttons auf "aus" setzen.
Das siehst Du, wenn Du meinen Code einfach ausprobierst. D.h. der Nutzer der Webseite sieht nicht mehr, was er eigentlich vor dem Abschicken angeklickt hat.
Der folgende Code respektiert aber die Eingaben aus dem letzten Aufruf, die Webseite "merkt" sich also den Zustand zwischen den Aufrufen, indem das Script die Werte im Formular wieder mit den alten Daten vorbelegt.
Sowas nennt man auch "Monkey Script" (siehe http://www.php.de/wiki-php/index.php/Affenformular_(Standardverfahren))
Der Vorteil dabei ist, das Du nur ein Script brauchst, weil es sich immer wieder selbst aufruft und Du sehr einfach prüfen kannst ob alle Daten korrekt übermittelt und verarbeitet werden.

<html>
<head>
</head>
<body><h1>Arduino - Monkey Script</h1>
<?php
if(isset($_GET['led1']))  $led1 = $_GET['led1'];
if(isset($_GET['led2']))  $led2 = $_GET['led2'];
if(isset($_GET['led3']))  $led3 = $_GET['led3'];
?>
<form action="">  <p>
    LED 1 : <input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >aus -  <input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >an

    LED 2 : <input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >aus -  <input type="radio" name="led2" value="1" <?php if($
led2==1) echo "checked" ?> >an

    LED 3 : <input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >aus -  <input type="radio" name="led3" value="1" <?php if($
led3==1) echo "checked" ?> >an

  </p>
  <input type="submit" name="submit" value="Abschicken">
</form>
</body>
</html>

Es dauert manchmal ein wenig bis man dahinter kommt, wie eine Webanwendung "tickt". Das Problem im Gegensatz zu einem "normalen" Programm ist, das Dein PHP-Script sich den alten Zustand zwischen 2 Aufrufen nicht direkt merken kann (außer man verwendet Sessions, aber das ist ein ganz anderes Thema). Außerdem können ja parallel hunderte Requests von unterschiedlichen Browsern auf das gleiche Script gehen, die auch miteinander nichts zu tun haben. HTTP ist ein "zustandsloses" Protokoll. Dein Script verarbeitet immer nur genau die Daten die im Formular drin stehen, mehr nicht.
Mario.

Hallo,
ich glaube ich habe dich jetzt verstanden. Es wird jetzt nach dem klick auf den Abschick-Button, angezeigt was Ausgewählt wurde.
Hier der Code:

<html>
<head>
</head>
<body><h1>Arduino - Monkey Script</h1>
<?php
if(isset($_POST['led1']))  $led1 = $_POST['led1'];
if(isset($_POST['led2']))  $led2 = $_POST['led2'];
if(isset($_POST['led3']))  $led3 = $_POST['led3'];
?>
<form method="POST" action="<?php echo $PHP_SELF ?>">
  <p>
    LED 1 : <input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >aus -  <input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >an

    LED 2 : <input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >aus -  <input type="radio" name="led2" value="1" <?php if($led2==1) echo "checked" ?> >an

    LED 3 : <input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >aus -  <input type="radio" name="led3" value="1" <?php if($led3==1) echo "checked" ?> >an

  </p>
  <input type="submit" name="submit" value="Abschicken">
</form>
</body>
</html>

Wie gehts jetzt weiter ? Wie übermittel ich jetzt die Formular eingaben an den Arduino ?
Ich greife nochmal deinen Vorschlag auf und packe das in eine Datei Namens "senden.php":

<?php
$arduino_ip="192.168.178.216";
$arduino_port="8088";

function arduino_send($ip,$port,$command) {
    $res = fsockopen($ip,$port);
    if($res) {
        fwrite($res,$command);
        return fread($res,1);
    } else {
        echo "Fehler, Kommando konnte nicht abgesetzt werden";
    }
}
?>

Öffne ich den dann von deinem Monkey-Script aus ?

<form method="POST" action="senden.php">

Und/Aber wo kommet denn der Command Aufruf hin ?

arduino_send(192.168.178.216,8088,'S'.chr(3).chr(1));

Der ja sagt, schalte Ausgang 3 EIN.

Ich glaube ja , ich denke immer noch zu kompliziert.
Aber das Monkey-Script beispiel habe ich jetzt verstanden.
Manchmal sieht man den Wald vor lauter Bäumen nicht :roll_eyes:

Guten Morgen,
es wird doch langsam :-). Du brauchst aber kein extra "senden.php". Du baust die Aufrufe direkt in das "Monkey-Script" ein. Die Stelle an der das passiert drängt sich auch geradezu auf, nämlich dort, wo Du die GET-Parameter auswertest. Genau an dieser Stelle hast Du ja alle Informationen, um die Ausgänge zu schalten. Ich habe das am Wochenende mal aufgebaut, es geht problemlos.
Mario.

Nabend :wink:
das freut mich aber, das ich nicht ganz auf dem Holzweg bin...

Du baust die Aufrufe direkt in das "Monkey-Script" ein. Die Stelle an der das passiert drängt sich auch geradezu auf, nämlich dort, wo Du die GET-Parameter auswertest.

Also so :

<FORM action="arduino_send($ip, $port, $command)" method="GET">
<p>
LED 1 : 
<input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >
aus -
<input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >
an


<INPUT type="submit" name="senden" value="senden">
</FORM>

Mein gesamt-Code sieht jetzt so aus, ungetestet, weil ja noch ohne Arduino:

<html>
<head>
</head>
<body><h1>Arduino - Testseite</h1>
<?php
if(isset($_POST['led1']))  $led1 = $_POST['led1'];
if(isset($_POST['led2']))  $led2 = $_POST['led2'];
if(isset($_POST['led3']))  $led3 = $_POST['led3'];

$ip = "192.168.178.216";
$port = "80";
$led1 = "'S'.chr(3).chr(1)";
$command = "$led1";

function arduino_send($ip,$port,$command) {
    $res = fsockopen($ip,$port);
    if($res) {
        fwrite($res,$command);
        return fread($res,1);
    } else {
        echo "Fehler, Kommando konnte nicht abgesetzt werden";
    }
}
?>
<FORM action="arduino_send($ip, $port, $command)" method="GET">
<p>
LED 1 : 
<input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >
aus -
<input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >
an


LED 2 : 
<input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >
aus -  
<input type="radio" name="led2" value="1" <?php if($led2==1) echo "checked" ?> >
an

LED 3 : 
<input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >
aus -  
<input type="radio" name="led3" value="1" <?php if($led3==1) echo "checked" ?> >
an

<INPUT type="submit" name="senden" value="senden">
</FORM>
</body>
</html>

DANKE !!! Für deine Hilfe und Mühe :slight_smile:

Nein, leider nicht. Ich glaub so ganz verstanden hast Du es noch nicht.
Das "arduino_send()" ist eine Funktion, die Dein PHP-Script verwendet, um dem Arduino Befehle zu schicken. Also vom Webserver zum Arduino.
Da wo Du den Aufruf eingetragen hast, ist das doch HTML-Code, der vom Browser ausgeführt wird. Woher soll der Browser denn wissen, was er machen soll, wenn im "action" Parameter ein Aufruf einer PHP-Funktion steht? Das klappt ja sonst auch nicht. Der Browser "spricht" nur mit dem Webserver, also dem PHP-Script. Also GET-Parameter an eine URL schicken und HTML-Code zurück bekommen. Mehr macht der Browser nicht, der weiss noch nicht mal was vom Arduino.
Der Aufruf der arduino_send() Funktion gehört hier hin:

<?php
if(isset($_POST['led1']))  $led1 = $_POST['led1'];
if(isset($_POST['led2']))  $led2 = $_POST['led2'];
if(isset($_POST['led3']))  $led3 = $_POST['led3'];
?>

In diesem Block verarbeitet das Script die vom Browser kommenden Informationen. Dort musst Du den Aufruf der Funktion unterbringen.
Mario.

Guten morgen,
oh... :blush: Ok, ich habe es nochmal versucht, die Seite wird angezeigt und es sich auch der zustand gemerkt, zumindest sieht es so aus:

<html>
<head>
</head>
<body><h1>Arduino - Monkey Script</h1>
<?php
$ip="192.168.178.216";
$port="8088";

function arduino_send($ip,$port,$command) {
    $res = fsockopen($ip,$port);
    if($res) {
        fwrite($res,$command);
        return fread($res,1);
    } else {
        echo "Fehler, Kommando konnte nicht abgesetzt werden";
    }
}

if(isset($_POST["arduino_send($ip,$port,'S'.chr(1).chr(1));"])) // Senden
 $led1 = $_POST["arduino_send($ip,$port,'R'.chr(1).chr(1));"];  // Lesen
if(isset($_POST["arduino_send($ip,$port,'S'.chr(2).chr(1));"])) // Senden
 $led2 = $_POST["arduino_send($ip,$port,'R'.chr(2).chr(1));"];  // Lesen
if(isset($_POST["arduino_send($ip,$port,'S'.chr(3).chr(1));"])) // Senden
 $led3 = $_POST["arduino_send($ip,$port,'R'.chr(3).chr(1));"];  // Lesen
?>
<form method="POST" action="<?php echo $PHP_SELF ?>">
  <p>
    LED 1 : <input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >aus -  <input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >an

    LED 2 : <input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >aus -  <input type="radio" name="led2" value="1" <?php if($led2==1) echo "checked" ?> >an

    LED 3 : <input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >aus -  <input type="radio" name="led3" value="1" <?php if($led3==1) echo "checked" ?> >an

  </p>
  <input type="submit" name="submit" value="Abschicken">
</form>
</body>
</html>

Ich habe die Zeilen mal untereinander geschrieben, damit ich das unterscheiden kann.
Also, ich versuche das mal zu verstehen

if(isset($_POST["arduino_send(192.168.178.216,8088,'S'.chr(1).chr(1));"])) // Senden

Mit dem ersten Aufruf, wird der gewünschte Zustand gesetzt...

 $led1 = $_POST["arduino_send(192.168.178.216,8088,'R'.chr(1).chr(1));"];  // Lesen

Mit dem zweiten Aufruf, der gesetzte Zustand gelesen...
Und hiermit

<?php if($led1==0) echo "checked" ?>

wird gefragt, welche Zustand ist es 1 oder 0 und dann angezeigt.

Oder wieder verkehrt ? :frowning:
Manchmal frage ich mich, ob mir eine Gehirnzelle fehlt das ich das nicht verstehe oder
denke ich zu kompliziert ? :~

EDIT:
Ich merke sehe gerade, das ich ja nur 1 senden kann, aber nicht 0
Ich steh gerade auf'n schlauch...

if(isset($_POST["arduino_send(192.168.178.216,8088,'S'.chr(1).chr(1));"])) // Senden

Ist leider komplett daneben.
$_POST[] ist zwar korrekt, weil Du die Daten ja im Formular per POST verschickst. Aber was soll der Aufruf der Funktion da drin?
Als "Key" verwendet das $_POST[] Array doch den Namen des Input-Feldes, das Du abfragen willst.
Also:

//prüfen ob für led1 Daten übermittelt wurden
if(isset($_POST['led1'])) {
    //übergebenen Wert speichern.
    $led1 = $_POST['led1'];
    //Wert an Arduino (Pin 9) senden
    arduino_send($arduino_ip,$arduino_port,"S".chr(9).chr($led1));
} else {
    //else-Zweig wird aufgerufen, wenn keine Daten per POST übermittelt wurden.

   //daher daten vom Arduino (Pin 9) lesen und in $led1 speichern
    $led1 = arduino_send($arduino_ip,$arduino_port,"R".chr(9).chr(0));
}

Wichtig ist, das Du mit den Werten arbeitest, die Du von Deinem Formular bekommst. Du hast nur statisch den Wert "1" übermittelt, das bringt dann natürlich nicht viel.
Hier nochmal mein vollständiger PHP-Code, der einzige Unterschied ist, das ich mit GET arbeite. Da sehen zwar die URLs nicht so schön aus, aber man sieht was übermittelt wird, das macht es einfacher Fehler zu finden.

<h1>Test</h1>
<?php

$arduino_ip="192.168.0.29";
$arduino_port="23";

function arduino_send($ip,$port,$command) {
    $res = fsockopen($ip,$port);
    if($res) {
        fwrite($res,$command);
        $ret =fread($res,1);
        echo "arduino_send() returned = $ret 
\n";
        return $ret;
    } else {
        echo "Fehler, Kommando konnte nicht abgesetzt werden";
    }
}

if(isset($_GET['led1'])) {
    $led1 = $_GET['led1'];
    arduino_send($arduino_ip,$arduino_port,"S".chr(9).chr($led1));
} else {
    $led1 = arduino_send($arduino_ip,$arduino_port,"R".chr(9).chr(0));
}

if(isset($_GET['led2'])) {
    $led2 = $_GET['led2'];
    arduino_send($arduino_ip,$arduino_port,"S".chr(4).chr($led2));
} else {
    $led2 = arduino_send($arduino_ip,$arduino_port,"R".chr(4).chr(0));
}

if(isset($_GET['led3'])) {
    $led3 = $_GET['led3'];
    arduino_send($arduino_ip,$arduino_port,"S".chr(5).chr($led3));
} else {
    $led3 = arduino_send($arduino_ip,$arduino_port,"R".chr(5).chr(0));
}

?>
<form action="">
  <p>
    LED 1 : <input type="radio" name="led1" value="0" <?php if($led1==0) echo "checked" ?> >aus -  <input type="radio" name="led1" value="1" <?php if($led1==1) echo "checked" ?> >an

    LED 2 : <input type="radio" name="led2" value="0" <?php if($led2==0) echo "checked" ?> >aus -  <input type="radio" name="led2" value="1" <?php if($led2==1) echo "checked" ?> >an

    LED 3 : <input type="radio" name="led3" value="0" <?php if($led3==0) echo "checked" ?> >aus -  <input type="radio" name="led3" value="1" <?php if($led3==1) echo "checked" ?> >an

  </p>
  <input type="submit" name="submit" value="Abschicken">
</form>

Ich verwendet die Pins 4,5 und 9 auf dem Arduino. Da ich einen Arduino-Ethernet verwende, der die interne LED statt auf Pin 13 auf Pin 9 hat, kann ich gleich optisch prüfen ob das Senden klappt.

Hallo GOTT :wink:
äh, ich meine Mario...

Also, es funktioniert jetzt!!!
Jetzt habe ich glaube ich auch kapiert, was ich falsch gemacht habe.
Manchmal sieht es erst wenn es fertig ist. Habe zwar schon ein bischen mit PHP gemacht,
aber leider zu wenig um die kurzform der schreibweise zu verstehen.
Du bist wohl auch PHP-Guru, oder ?
Was wir hier,nein was DU, hier gemacht hast, hat ja eigentlich nix mit Arduino zu tun.
Also echt Suuper !! Mein Respekt, das du die Gedult hattest mich da so ran zu führen, das ein Anfänger wie ich, das auch versteht und es letztendlich läuft. DANKE !!

Jetzt muss das ganze noch für 8 Ausgänge optimiert werden und ein büschen aufhübschen... XD

Dennoch habe noch eine Frage, vieleicht bekomme ich das aber auch allein irgendwie raus.
Die Pins sind ja nun als Ausgänge deklariert "pinMode(Pin4, OUTPUT);" , wenn der Sketch startet, ist Pin4 AN, obwohl er AUS-geschaltet sein sollte.
Und wenn ich dann auf AN klicke schaltet er AUS, sozusagen sind 1 und 0 vertauscht.
Was ich aber nicht verstehe, da ich doch mit dem PHP-Script 1 (also AN) sende und er aber AUS macht.
Hier der funktionierende Sketch:

/*
  Webclient
  Es soll mittels einer PHP-Seite, die auf einem Webserver liegt,
  ein oder mehrere Ausgänge AN/AUS geschaltet werden.
*/

#include <SPI.h>
#include <Ethernet.h>

// Ethernet einrichten
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xEE, 0xF3 };
IPAddress ip(192,168,178,216);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255, 255, 255, 0);

// telnet defaults to port 23
EthernetServer server(23);
boolean gotAMessage = false; // whether or not you got a message from the client yet

int Pin4 = 4;
int Pin5 = 5;
int Pin9 = 9;

void setup() {
  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);
  // start listening for clients
  server.begin();
  // open the serial port
  Serial.begin(9600);
  pinMode(Pin4, OUTPUT);
  pinMode(Pin5, OUTPUT);
  pinMode(Pin9, OUTPUT);
}

void loop() {
  // wait for a new client:
  EthernetClient client = server.available();
  
  // when the client sends the first byte, say hello:
  if (client) {
    if (!gotAMessage) {
      Serial.println("We have a new client");
      gotAMessage = true;
    }
    
  //Achtung super simpler Quickhack ohne Püfung der Eingabe oder ob Daten vorhanden sind
char input[3];

for(int i=0;i<3;i++) {
    input[i] = client.read();    
}

//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
}
//pin lesen und an den Client schicken
if(input[0] == 'R') {
   client.print(digitalRead(input[1]));
} 
 }
 client.stop();
 client.flush();
}

Klar, ich kann einfach 1 und 0 tauschen, aber damit habe ich es ja nicht verstanden.

Ansonsten, nochmal VIELEN DANK für deine Mühe und Geduld Mario aka "mkl0815"

Kein Problem, der Aufwand war ja überschaubar und Du hast einiges gelernt. Mit HTML und PHP wurschtel ich schon seit über 10 Jahren herum. Ich wollte halt nur nicht sofort die komplette Lösung liefern, Du solltest schon selbst bestimmte Dinge machen. Es geht ja schliesslich darum, das Du am Ende etwas lernst.
Ansonsten würde ich noch aufpassen, beim Ethernet-Shield und beim Arduino-Ethernet wird das Pin 4 glaub ich für das Chip-Select der SD-Karte verwendet. Keine Ahnung, ob das einen Einfluss hat. Ich denke nicht zwar nicht, aber man weiss ja nie.
0 und 1 sollten eigentlich nicht vertauscht sein, ist es bei mir auch nicht. Schau mal nach, nicht das Dein HTML-Formular bei den radio-buttons die Werte vertauscht hat. Das ist der Grund warum ich GET statt POST verwende, da sehe ich in der URL sofort was verschickt wird.
Hier der Code auf dem Arduino, den ich verwende:

/*
 Arduino TCP Control
 
 A simple server that waits for incoming connections to set or read 
 digital Output Pins
 
 Using an Arduino Wiznet Ethernet shield or an Arduino Ethernet. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 2012-04-28
 by Mario Keller
 
 */

#include <SPI.h>
#include <Ethernet.h>

// MAC und IP Konfiguration
byte mac[] = { 
  0xDE, 0xAD, 0xBC, 0xAF, 0xFE, 0xED };
IPAddress ip(192,168,0, 29);
IPAddress gateway(192,168,0, 252);
IPAddress subnet(255, 255, 255, 0);

// warten auf port 23
EthernetServer server(23);

void setup() {
  //Ethernet initialisieren
  Ethernet.begin(mac, ip, gateway, subnet);
  // Server starten
  server.begin();
  // serielle konsole öffnen (debug)
  Serial.begin(9600);
}

void loop() {

  // auf eine eingehende Verbindung warten
  EthernetClient client = server.available();
  //wenn verbindung, dann 3 bytes lesen; 
  if (client) {

    char command =client.read();
    byte pinnumber =client.read();
    byte pinvalue =client.read();
    byte returnvalue = 0;

    //Kommando auswerten
    switch(command) {

    case 'S':
      Serial.print("S Kommando empfangen, setze Pin ");
      Serial.print(pinnumber);
      Serial.print(" auf ");
      Serial.println(pinvalue);
      pinMode(pinnumber,OUTPUT);
      digitalWrite(pinnumber,pinvalue);
      //gesetzten wert auch zurückliefern
      returnvalue=pinvalue;
      break;

    case 'R':
      returnvalue = digitalRead(pinnumber);
      Serial.print("R Kommando empfangen, lese Pin ");
      Serial.print(pinnumber);
      Serial.print(". Wert = ");
      Serial.println(returnvalue);
      break;

    default:
      Serial.println("Fehler, unbekanntes Kommando");    
      break;

    }  
    
    // rückantwort senden (1 byte) die "+48" sorgen dafür das der Wert 0 oder 1 als Zeichen "0" oder "1" übertragen werden. 
    //das vereinfacht die verarbeitung in php.
    client.write(returnvalue+48);
    
    //übertragung erzwingen
    client.flush();
    
    //10ms delay damit daten sicher gesendet werden.
    delay(10);
    
    //wichtg! client verbindung beenden
    client.stop();
  }
}

Hallo,
also dein Sketch sieht Professionell aus, mit Überprüfung und so, nicht schlecht :slight_smile:
Ich habe rausgefunden, warum die LED immer an war, obwohl 0 gesendet wurde.
Ich würde mal sagen, klassischer Anfänger Fehler, ich hatte verkehrtrum gepohlt.
:grin:

Jetzt gehts :smiley:
Nun geht es weiter, das ganze per Zeit zu steuern, also das ich sage, öffne Ventil für 15min und dann wieder zu, mal sehen, wie weit ich da kommen... :~

Mach ich das am besten per PHP und übergebe das dann an den Arduino ?
Oder sollte der Arduino das machen ? (Mit millis oderso ?)

Moin Moin,
kann man auch ein viertes Byte übertragen ?
Z.b. 15 ?
Soll bedeuten, das die LED für 15 min AN ist und sich dann wieder ausschaltet.
Ich dachte da an sowas wie, die "15" wird an millis/delay übergeben.

//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
   delay[3];
}

Auszug aus der PHP:

if(isset($_GET['led2'])) {
    $led2 = $_GET['led2'];
    arduino_send($arduino_ip,$arduino_port,"S".chr(9).chr(1).chr($led2[])); //Pin9 AN für x min
} else {
    $led2 = arduino_send($arduino_ip,$arduino_port,"R".chr(9).chr(0));
}
....
<form action="">
  <p>
   <select name="led2[]">
    <option value="15">15 min</option>
    <option value="30">30 min</option>
    <option value="60">60 min</option>
   </select>
  </p>
   <input type="submit" name="submit" value="Starten">
   <input type="reset" name="stop" value="Stop">
</form>

Geht sows oder mal wieder völlig daneben ? :blush:

Du willst also eine Zeitshaltung bauen? Natürlich geht das, allerdings wird das aus verschiedenen Gründen etwas komplexer.
Aber der Reihe nach.

//pin setzen
if(input[0] == 'S') {
   digitalWrite(input[1],input[2]);
   delay[3];
}

Das geht schon mal nicht, wenn schon dann delay(input([3]), was aber bei input[3]=15 nur 15 Millisekunden und nicht 15 Minuten wären. Ein 4. Byte übertragen ist kein Problem, das ist nur eine Anpassung im PHP Code, indem Du dem "$command" ein 4. byte hinzufügst. Dein Problem beim Delay ist aber, das der Arduino dann die nächsten X Minuten (im schlimmsten Fall eine Stunde) nicht auf weitere Verbindungen reagieren würde.
Die Zeitsteuerung über PHP zu machen ist auch keine gute Idee, da Du ja ständig "reloads" der Seite machen müßtest, bzw. mit Ajax arbeiten. Und wenn der User den Browser schliesst, dann geht dein Ventil im schlimmsten Fall nie wieder zu :slight_smile:

Ein guter Grundsatz bei komplexen Systemen ist immer, das Aufgaben nach Möglichkeit an den Stellen (in den Komponenten) gelöst werden, wo sie anfallen.
In Deinem Fall ist das der Arduino, der ja nach z.b. 15 Minuten das Ventil wieder schliessen muss.
Ich würde einfach für jedes "Ventil" (sprich Arduino Ausgang) eine Variable "unsigned long vtimer1 = millis() + (1000 * 60 * input[3])" definieren, wenn das "Ventil" über die PHP-Funktion geschaltet wird. vtimer1 (als Beispiel für Ventil 1) enthält dann den Zeitpunkt, wann das Ventil wieder umgeschaltet werden soll. Das kannst Du dann in jedem loop() Durchlauf mit dem aktuellen Wert von millis() vergleichen. Das kannst Du dann unabhängig für jedes Ventil machen, ohne ein delay() verweden zu müssen.

Zu Deinem PHP-Code:
Warum verwendest Du immer Arrays in den Variablennamen?
z.b. <select name="led2[]">
Das ist eher unübersichtlich und eigentlich unnötig, außer Du willst ALLE "Ventile" in ein Array packen, dann würde es Sinn machen, müßte aber auch anders aussehen.
Mario.