Arduino mit PHP über seriellen Port steuern

Hallo zusammen,
ich bin relativer Anfänger und würde gerne einen Arduino in einem lokalen Netzwerk ohne ETH-Shield o.ä. steuern. Dieser ist via USB mit dem Rechner verbunden. Im Prinzip stelle ich mir das folgendermaßen vor:

Browser (PHP-Skript) --> Webserver (XAMPP) --> Com-Port (Windows-Rechner) --> Arduino UNO

Ich habe auch schon eine Klasse gefunden, die ich in mein PHP-Skript einbinden kann, die diese Funktionalität grundlegend bereitstellt (php_serial.class.php von GITHUB)

Hier mal der Arduino-Code:

int ledPin12 = 12; // the pin that the red LED is attached to
char incomingByte;      // a variable to read incoming serial data into
void setup() {
   
   Serial.begin(9600); // initialize serial communication
  
   pinMode(ledPin12, OUTPUT);  // initialize the red LED pin as an output
}
void loop() {
  // see if there's incoming serial data:
 
  
  if (Serial.available() > 0) {
    incomingByte = Serial.read(); // read the oldest byte in the serial buffer
    //Preform the code to switch on or off the leds
    if (incomingByte == '9') {
      digitalWrite(ledPin12, HIGH); //If the serial data is 2 turn green LED on
      //Serial.println("9"); 
    } 
    if (incomingByte == '3') {
      digitalWrite(ledPin12, LOW); //If the serial data is 3 turn green LED off
      //Serial.println("3"); 
    }  
  }
}

und hier der PHP-Code:

<?php //declare(strict_types=1); // strict requirement
  
	//Load the serial port class
    require("php_serial.class.php");


	//Initialize the class  
$serial = new phpSerial();
$serial->phpSerial();

	// Variablen deklarieren
$value_on = '9';		// hier anscheinend egal ob '' oder ""
$value_off = "3";		//


	// Serielle Schnittstelle öffnen
$serial->deviceSet("COM5");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();


sleep(1);
$serial->sendMessage($value_on);
sleep(1);
$serial->sendMessage($value_off);
sleep(1);
$serial->sendMessage($value_on);
sleep(1);
$serial->sendMessage($value_off);
sleep(1);
    //We're done, so close the serial port again
$serial->deviceClose();
?>

Das funktioniert zwar so wie es hier steht, aber ich habe einige komisch Phänomene festgestellt die ich mir nicht erklären kann:

wenn ich im PHP-Skript bspw. $value_on = '1'; nutze, geht die LED nicht an (Im Arduino-Code natürlich auch auf den anderen Parameter geändert: if (incomingByte == '1')).

Bei der Kombination aus '3' = LED ein und '4' für LED aus geht die LED zwar an aber nicht mehr aus.

Die Parameter 'A' für LED ein und 'B' für LED aus funktionieren z.B. auch korrekt. Also gibt es aktuell Zeichen die ich als Befehl benutzen kann und welche bei denen es nicht funktioniert. Ich habe schon versucht mit strikten Datentypen im PHP zu arbeiten aber das hatte bei mir zumindest auch keinen unterschied bewirkt. Vielleicht habe ich auch was falsch gemacht, das will ich gar nicht ausschließen.

Hat von Euch jemand eine Idee oder kennt einen schöneren Weg wie z.B. auch flexibler darauf reagiert werden kann bzw. die Befehle auch komplexer gestaltet werden können?

Ich habe auch schon einen älteren Forumsbeitrag gefunden der etwas ähnliches abbildet aber der ist a) leider schon geschlossen und b) wird dort mit einem ETH-Shield (IP-Adressen usw. )gearbeitet. Ich würde es ja gerne direkt am COM-Port betreiben.

Ich hoffe auf Eure Hilfe und Eure Ideen woran das liegen kann.

Viele Grüße
Lukas

Ein Klassiker aus der Kategorie "wie kann ich ein einfaches Problem möglichst kompliziert (nicht) lösen".

Wieveil von den Teilen, die du beschrieben hast, verstehst du?

Ich wüsste einige Stellen in deinem Code, die man verbessern könnte.

Leider zeigst du nicht den fehlerhaften Code.
So kann ich auch den Fehler nicht sehen

Es wäre gut, den seriellen Monitor zu nutzen. Da der UNO nur eine UART hat, kannst Du auf SoftwareSerial ausweichen. Besser wäre ein Arduino mit mehreren UARTs.

Hallo,
wilkommen im Forum.
Erst mal denke ich du hast Dich für den sicher umständlichsten Weg entschieden. Ich vermute ja da kommt mehr auf der seiellen Schnittstelle an als Du vermutest. Dazu solltest Du erst mal alle Zeichen auslesen , auch die nicht druckbaren, also in hex Darstellung anzeigen lassen. das geht in einer schleife ganz einfach solange Serial.available() > 0 ist.

Grundsätzlich solltest Du aber mal über die Möglichkeit nachdenken den Webserver auf den Controller zu bringen. Das geht am einfachsten mit einem ESP 2866 oder ESP32 über WiFi. Natürlich geht das auch mit einem Aruino und Ethernet über Kabel. Allerdings kommst Du dann zumindest bei einem UNO schnell an Grenzen bezüglich des Speichers.

Beispiele was da alles so machbar ist findest Du z.B hier https://fipsok.de/

Heinz

LED an / aus ist wahrscheinlich nur zu Testzwecken.

Was willst du denn am Ende mit dem Arduino machen?

Sehe ich auch so.

Momentan hast du den USB-Anschluss des Arduino-Uno mit dem PC verbunden und dein PHP-Script kommuniziert über diese Schnittstelle.

Genau diese Schnittstelle wird normalerweise zum debuggen benutzt.
Daher der Vorschlag Software-serial zu benutzen.
Dann brauchst du aber einen USB-TTL-Adapter.
oder du müsstest für die Debug-Ausgabe ein LC-Display nehmen.

Alles Klimmzüge die man vermeiden kann
wenn du für schlappe 5,30 Euro einen ESP32 kaufst

Denn kannste dann direkt in dein häusliches WLAN einbinden und dann ohne HTML-Kenntnisse über die ESPUI-libaray eine eine Webseite programmieren.
Dann kannste über jedes Browserfähige Endgerät dem ESP32 Steuerbefehle senden.

Den ESP32 kann man dann genauso mit der Arduino-IDE programmieren wie einen Arduino.

Edit:

ja richtig. Man kann sich da anschauen was alles so machbar ist.
Lernen wie man es programmiert erfordert HTML-Kenntnisse
Wenn die vorhanden sind mag es ja gehen. Sonst ziemlich anspruchsvoll.

@Rentner
gibt es bei fipsok inzwischen gaaaaanz simple Beispiele?

Simpel im Sinne von da wird

  • Auf der Webseite ist ein singulärer Schiebeschalter plus der Code der das umschalten auswertet
  • ein singuläres Textfeld zum anzeigen eines Wertes plus Code das den Text aktualiisert
    gaaanz simpel als for-Schleife die den Wert hochzählt?
    oder meinetwegen auch eine vorbereitete function der man einen Intergerwert übergibt und dann wird in der function der entsprechende html-Code zusammengesetzt?

Lieber Stephan,

ich weiß sehr wohl das Du eine Abneigung gegen HTML und Java-Skript hast. Und zudem anscheinend eine kurze Zündschnur.
Soll ich einem neuen User hier verschweigen was geht und wie man das machen kann, nur weil der liebe Stephan eine andere Vorliebe hat. ? Ist Doch gut wenn Du Dich in das Thema ESPUI lib eingearbeitet hast und das ebenfalls als Möglichkeit angeben kannst.

Gruß Heinz

Erstmal vielen Dank für die schnellen Rückmeldungen.

Ich versuche mal auf alle Kommentare einzugehen:

1.: Ich verstehe eigentlich alle Teile des Codes.

2.: Natürlich ist der Code verbesserungswürdig aber mir geht es jetzt erst mal um die Grundfunktion. Das ist der Vollständige Code sowohl im PHP und des Arduinos. Ich habe jetzt lediglich die php_Serial-Klasse nicht eingebunden. Der Code funktioniert ja im Prinzip auch abgesehen von den Phänomenen, dass nicht alles Zeichen gleichwertig benutzt werden können.

3.: Wenn ich den seriellen Monitor oder Putty als Interface zum Com-Port benutze gehen auch die Zeichen 1, 2,... Da macht das keinen Unterschied. Lediglich beim verwenden des PHP-Skripts gibt es Zeichen die nicht gehen. Ich kann auch, wenn ich die php_serial-Klasse richtig interpretiere auf einem Windows-Rechner nichts zurücklesen weil das in der Klasse nicht implementiert wurde.

4.: Mir ist bewusst, dass es mit einem ETH-Shield oder WiFi-Chip einfacher geht, ich will aber verstehen, wo die Unterschiede herkomen wenn ich den Seriellen Monitor/Putty oder das PHP-Skript benutze.

5.: Die Funktion soll sein Relais zu schalten also ob LED oder Relais ist erst mal egal. Erweitern kann man das ja immer noch wenn man versteht wo die aktuellen Probleme herkommen.

6.: Ein LCD-Display habe ich grade nicht zur Hand. WIe bereits beschrieben, oben ist der Vollständige Code. Dieser sollte in Kombination mit der Klasse lauffähig sein. Ich will primär verstehen wieso diese Unterschiede auftauchen.

Ich hoffe das gibt euch Aufschluss über meine Situation. Bei weiteren Fragen lasst es mich gerne wissen.

Ich würde 8 LEDs anschliessen und als Binäranzeige für das empfangene Zeichen nehmen.
Und dann vom PHP-Script aus mal alle druckenbaren ASCII-Zeichen senden und dann vergleichen.

SD-Karte mit dem Arduino verbinden und die empfangen Zeichen dort hin speichern

Hat du einen USB-nach-TTL-Wandler?
Hast du einen zweiten Arduino

Da wird mehr gesendet als du vermutest. Du benötigst eine zweite Schnittstelle am Arduino + Converter.
Stell dir einfach vor da werden zwei Zeichen gesendet. Du konntest noch die Serielle leerlesen und bei jedem eingelesen Zeichen die Bedingung abfragen.

Eventuell gibt es ein Terminalprogramm für den PC das auf dem verwendeten Com Port mithören kann.

Sehe ich auch so.
Com-Sniffer (14 Tage Testversion)
USB-Anallysator

Einfach mal ausprobieren. Ich habe sie nicht getestet.

Gruß Tommy

Wenn ich dir einen Rat geben darf:
Nimm ein Board auf Basis eines ESP8266 oder ESP32 und programmiere direkt diesen Microcontroller (mit Wifi) und verwende deinen UNO für sonstige "Offline" Aktivitäten.

Die ESP's gibt es auch fix und fertig verdrahtet mit Relais. Da sparst sogar gegenüber dem Einzelkauf von Uno+Relaisboard.

= UNO R4

@elektrometaller1
bitte nimm ein sonstiges Board wie z.B. ein NodeMCU oder Wemos D1.

Teuer 30 Euro. Immer noch ziemlich neu = wenig vorhandener Code.
Code weicht vom de fakto-Standard ESP32-NodeMCU ab

Vielen Dank für den Tipp. Ich habe mir jetzt mal den USB Analysator runtergeladen und installiert. Wenn ich auf dem Port des Arduino lausche, dann kann ich dort genau die Zeichen sehen, die Übertragen werden. Es gibt eine ganze Reihe von Paketen, die da in der Liste auftauchen aber ich kann auch genau meine gesendeten Zeichen ausmachen. Diese tauchen dort in der Liste z.B. als "41 A" auf. Wobei die 41 den Wert der ASCII-Tabelle darstellt. Genauso kommt z.B. "31 1" wenn ich eine 1 sende.

Schlauer, wieso manche Zeichen funktionieren und andere nicht, bin ich aber jetzt immer noch nicht. Hilft es jemand wenn ich ein Bild der Protokolle schicke, die in der Software erscheinen?

P.S.:
Es soll nicht unhöflich sein aber die Kommentare "nimm eine andere Hardware" helfen bei meinem Problem leider absolut nicht --> Ich will das "wieso geht es nicht mit allen Zeichen" verstehen!! Alle anderen Tipps und Hilfestellungen sind gerne weiterhin willkommen. Vielen Dank an alle, die sich die Mühe machen mir zu helfen.

Viele Grüße

Nimm' den Seriellen Monitor von der ArduinoIDE und grobier deine Kommandos aus. Das Webgedröhns macht ja auch nix anderes.

Das habe ich ja schon alles gemacht (wie auch oben zu lesen). Mit Putty und der IDE funktionieren alle Zeichen die ich getestet habe. Mit PHP funktionieren manche Zeichen eben nicht und das will ich verstehen wieso das nicht geht.

Dann macht dein PHP Gedröhns Mist. Lass einfach die Daten, die an den Arduino geschickt werden sollen, auf der Konsole ausgeben.

Welche Zeichenkodierung hat Dein HTML?

Gruß Tommy