PHP+Arduino (Serielle COM-Verbindung)

Hallo!
Mein Arduino ist per USB mit dem PC verbunden auf COM3.
In der Arduino konsole klappt es, wenn ich z.B. 300C eingebe, sprich der Servo bewegt sich.
Wenn ich aber in PHP 300C sende, dann passiert nichts. (auch keine Fehler werden ausgegeben…)
(ich habe hier den Zeilenumbruch, welcher das Ende des “kommandos” signalisiert testhalber durch ein “C” ersetzt)

Hier mein Code:

Arduino:

#include <Servo.h> 
Servo myservo;
int servoPin = 11;
const int ledPin = 13; // pin the LED is connected to
int serial_input=0; // blink rate stored in this variable

void setup()
{
  Serial.begin(9600); // Initialize serial port to send and receive at 9600 baud
  pinMode(ledPin, OUTPUT); // set this pin as output
  myservo.attach(servoPin);
}

int value;
void loop()
{
    while( Serial.available())
    {
        char ch = Serial.read();
        if(ch >= '0' && ch <= '9' && ch != 'C') // is this an ascii digit between 0 and 9?
        {
          value = (value * 10) + (ch - '0'); // yes, accumulate the value
        }
        else if (ch == 'C') // is the character the newline character
        {
           serial_input = value; // set serial_input to the accumulated value
            Serial.print("->");
            Serial.println(serial_input);
            value = 0; // reset val to 0 ready for the next sequence of digits
          setServo(serial_input);        
        }
        
    }
}

void setServo(int temp) 
{
// 0   - 200 = - 200 = - 20.0 °C 
// 500 - 200 =   300 = + 30.0 °C
   float temp_dec = (((float) temp - 200) / 10);
  Serial.print(temp_dec);
Serial.println("C");  
  
int servo_val = map(temp, 0, 500, 179, 0); // -20 - +30 °C
    myservo.write(servo_val);                  // sets the servo position according to the scaled value 
  delay(500); 
  
}

PHP:

<?php

    //Load the serial port class
    require("php_serial.class.php");

    //Initialize the class
  
$serial = new phpSerial();
$serial->deviceSet("COM3");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();

        $serial->sendMessage("300C");

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

Die PHP-Klasse “php_serial.class.php” hab ich hier her:
http://www.phpclasses.org/browse/file/17926.html

Für hilfe wäre ich euch dankbar :wink:

PS: Falls ihr euch fragt was ich vor habe:
Ich will durch den Aufruf des PHP-Skripts am PC später eine Temperatur aus dem Internet einlesen, diese dann per Serieller schnittstelle an Arduino weiterleiten und den Servo mit einem “zeiger” auf die Temperatur auf einer Skala zeigen lassen.

Gruß

kduin

Es kann sein daß der IDE oder das Terminal die COM Schnittstelle blockiert und PHP darum nicht darauf zugreifen kann. Versuch mal den IDE zu schließen und das LED 13 anzumachen um eine empfangene Anforderung zu signalisieren. Grüße Uwe

Hi uwefed.

gute idee, habe nach dem while-statement folgenden Code eingefügt:

digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
            delay(500);

LED leuchtet 4x auf
Verbindung besteht also.

Hallo

so vom Thema her finde ich das (ungetestet) recht gut:

http://www.mikrocontroller.net/articles/Ports_benutzen_(PHP)

So schön Klassen sein mögen, aber um technische Funktionalität zu testen würde ich das obige Beispiel benutzen, da ist weniger Interaktion möglich.

Php und seriell ist auf windows irgendwie immer buggy. alternative waere ein seriell tcp proxy. im forum bzw playground suche nach serproxy.

Gute Idee mit dem Serproxy!
Aber ich finde leider nur tutorials in denen beschrieben wird, wie man das mit Flash nutzt, nichts mit php zu finden…

SerProxy hat nichts mit Flash oder PHP zu tun - es ist ein eigenständiges (Windows-) Programm und "splittet" lediglich den vorhandenen seriellen Port, so dass mehrere Programme gleichzeitig darauf zugreifen können. Ohne seriellen Proxy ist der Port immer belegt, wenn z.B. die Konsole der Arduino-IDE läuft und andere Programme können sich nicht verbinden.

Also das serproxy welches ich meine leitet Daten von einem seriellen Port zu einem TCP/IP Socket weiter und zurück.

Anwendung in PHP in etwa:

<?php
  $pSocket = fsockopen('localhost', 42);   // serproxy auf port 42
  fputs($pSocket, "daten");
  echo fread($pSocket, 255);
  fclose($pSocket);

Ja das stimmt schon - dennoch splittet er den Port, da er sonst generell belegt wäre.

Danke!
Mit serproxy und dem codeschnipsel von sui (allerdings mit port 5333 (für COM3) statt 42, wie in serproxy.cnf) klappt es!

Hallo kduin,
php_serial.class.php funktioniert prinzipiell schon. Ich habe heute mal ein altes Beispiel rausgekramt.
Ich habe mal eine Kopplung von einem AVR, damals mit einem Cisco NSLU2, auf dem unter Debian ein Webserver läuft, laufen gehabt.
Nachdem ich das Beispiel heute auf den Arduino Mega adaptiert hatte, stellte ich aber fest, dass bei jedem Zugriff (deviceset oder sendMessage) der Mega ein Reset über DTS (Autoreset) bekommt.
Nachdem ich einen Kondensator mit 4,7uF zwischen RESET und GND eingbracht hatte, funktionierte die Kommunikation.
Hier mal mein PHP Beispiel mit einigen Ausgabe zum Troubleshooten.

<?php
$tstr = $_POST["tstr"];
if (!isset($_POST['submit'])) 
{ // if page is not submitted to itself echo the form
?>
<html>
<head>
<title>Form Ex</title>
</head>
<body>
<form method="post" action="<?php echo $PHP_SELF;?>">
Transfer String:     <input type="text" size="40" maxlength="80" name="tstr">

<input type="submit" value="senden" name="submit">
<input type="reset" value="loeschen" name="reset">
</form>
<?php
} 
else 
{
include "php_serial.class.php";
$rate = 9600;
$parity = "none";
$int = 8;
$length = 1;
$mode = "avr";
// Let's start the class
$serial = new phpSerial;
echo "Start the class
";
echo "Sript is running with user ";
$ping=`whoami`;
echo "$ping.
";
// First we must specify the device. This works on both linux and windows (if
// your linux serial device is /dev/ttyS0 for COM1, etc)
$serial->deviceSet("/dev/ttyACM0");
echo date("F j, Y, H:i:s");
echo "
";
echo "Specify the device
";
// Set the interface parameter
$serial->confBaudRate($rate);
$serial->confParity ($parity);
$serial->confCharacterLength ($int);
$serial->confStopBits ($length);
$serial->confFlowControl ($mode);
// Then we need to open it
$serial->deviceOpen();
echo "Device open
";
// To write into
$serial->sendMessage($tstr);
// Or to read from
usleep(100000);
$read = $serial->readPort(0);
echo "read_data ##- ".$read." -##
";
// }
// If you want to change the configuration, the device must be closed
$serial->deviceClose();
}
?>

Ich hatte damals die php.class angepasst (siehe mode: avr). Ob das immer noch notwendig ist, weiß ich nicht, funktioniert aber nur bei Linux.
Probiere mal den Autoreset auszuschalten. Siehe auch http://www.arduino.cc/playground/Main/DisablingAutoResetOnSerialConnection
Die Lösung mit 120R funktionierte beim Mega nicht.
Gruß
Reinhard