Forum: PC-Programmierung Per PHP COM Schnittstelle ansprechen


von He K. (mr_sol)


Lesenswert?

Hallo

Vielleich hat jemand von euch eine Idee oder Hinweis.

Problembeschreibung: Soll über COM2 (USB/UART) Daten aus MC Board 
lesen/schreiben. Über Terminal klappt es wunderbar, über PHP gibts ein 
Problem.

1
<?php
2
$fp=`mode com2: BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
3
echo $fp; 
4
if (!$fp = fopen ("com2:", "w+")) 
5
{ 
6
echo "<br>";
7
echo ' Anschluss konnte nicht geoeffnet werden!!!'; 
8
} 
9
?>

Liefert mir "COM2 ist momentan nicht verfügbar" und
Warning: fopen(com2:) [function.fopen]: failed to open stream: 
Permission denied

Danke für eine Hinweis in voraus.

: Verschoben durch Moderator
von Peter II (Gast)


Lesenswert?

Helmut Kn schrieb:
> Permission denied
was wird da wohl das Problem sein?

Ich finde  es eine blöde idee aus php auf die com schnittstelle 
zuzugreifen, weil php durch mehre Benutzer gleichzeigt aufgerufen werden 
kann. Die schnittstelle kann aber immer nur von einem Prozess verwendet 
werden.
Sotwas macht man über einen Serverprozess der die zugriffe regelt.

von He K. (mr_sol)


Lesenswert?

Zugriff verweigert-Meldungen vom Server...mir ist nicht klar wo ich zum 
Suchen anfangen soll.

Peter II:
Serverprozess der die zugriffe regelt...wie genau?

von Peter II (Gast)


Lesenswert?

Helmut Kn schrieb:
> Zugriff verweigert-Meldungen vom Server...mir ist nicht klar wo ich zum
> Suchen anfangen soll.
der apache/php user  hat keine rechte auf com2

> Peter II:
> Serverprozess der die zugriffe regelt...wie genau?
man man für sotwas ein Prozess (ein eingene Programm z.b. mit 
Perl/C/sonstetwas) der die Com-Schnittstelle öffnet und dort mit dem MC 
Board redet. dann kannst du von php z.b. per namespipe auf den Prozess 
zugreifen. (ja das ist am ende etwas komplizierter aber technisch 
besser)

von He K. (mr_sol)


Lesenswert?

Ich verstehe.

Vielen Dank für dein Bemühen

von He K. (mr_sol)


Lesenswert?

Wo/Wie müsste ich die Rechte im Apache einstellen?

von Peter II (Gast)


Lesenswert?

Helmut Kn schrieb:
> Wo/Wie müsste ich Rechte im Apache einstellen.
dort überhaupt nicht.

Geht es eigentlich um Linux oder Windows?

Linux:
du musst dir die rechte von /dev/ttyS0 (oder wie auch immer es bei dir 
heist) ansehen und dann eventuell den apache user in die passende gruppe 
eintragen.

Windows:
da müssten die Recht eigentlich immer stimmem, weil jeder nutzer darauf 
zugreifen kann.

Bist du eigentlich sicher mit

 fopen ("com2:", "w+")) ?

denn unter windows kenn ich das nur ohne den ":" und unter linux sollte 
es doch dev... sein.

von Keiner (Gast)


Lesenswert?


von He K. (mr_sol)


Lesenswert?

Langsam komme ich der Sache näher. Der Hinweis mit com2: war gut.

Die COM unter Windows - wird schon mal angesprochen.
1
<?php
2
/**
3
* EIN/AUSGABE ueber COM
4
*
5
* Einfache Ein/Ausgabe ueber COM Schnittstelle
6
*
7
* @V0.1      2011.06.13 Schnittstelle angesprochen
8
*/
9
10
11
/**
12
* Set serial port parameters. Laut Doku: 9600 8-N-1
13
* Baud rate: 9600
14
* Parity (das "N" in "8-N-1") - Datenblock auf korrekten Inhalt zu überprüfen
15
* data - Character length (die "8" in "8-N-1")
16
* Stop bits (die  "1" in "8-N-1") 
17
* DTR - Data Terminal Ready 
18
* RTS - Request to Send [Sendeanforderung]
19
*/
20
$fp=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
21
22
echo $fp; 
23
24
if (!$fp = fopen ("com2", "r+")) 
25
{ 
26
echo "<br>";
27
echo ' Anschluss konnte nicht geoeffnet werden!!!'; 
28
} 
29
 
30
while (!feof($fp))
31
{
32
$line=fgets($fp, 512);
33
echo $line."<br/>";
34
}
35
fclose($fp);
36
37
38
?>

Ich suche eine besser Lösung zum Datenlesen - Die Schleife habe ich 
übernommen nur fehlt das Verständnis für 512.

Eine Idee.....?

von g457 (Gast)


Lesenswert?

> $line=fgets($fp, 512);
[..]
> nur fehlt das Verständnis für 512

Das kannst Du im Datenplatt^W^Hn der Doku finden. Evtl. wär auch 
stream_get_line() (ebenfalls in der Doku dokumentiert) was für Dich.

HTH

von He K. (mr_sol)


Lesenswert?

Danke - was ist ^W^Hn ?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Steuerzeichen für Texteditoren, die das vorangehende Wort löschen. Wird 
manchmal bewusst als Stilmittel eingesetzt, wie hier auch.

von He K. (mr_sol)


Lesenswert?

:) danke - wieder was gelernt.
Wo gibts eine gute Dokumentation bzw Datenblatt?

von g457 (Gast)


Lesenswert?

> Wo gibts eine gute Dokumentation bzw Datenblatt?

API-Doku: [1], darin dann [2] und [3] für obige Funktionen.

HTH

[1] http://php.net/docs.php
[2] http://de2.php.net/manual/en/function.fgets.php
[3] http://de2.php.net/manual/en/function.stream-get-line.php

von He K. (mr_sol)


Lesenswert?

Danke für die Links 512 ist die Blockgrösse

von He K. (mr_sol)


Lesenswert?

Bin ein Stück weiter

Habe auf MC Board ein kleiner File gelade. Aufgabe eingehende Zeichen 
zurückzuschicken. Klappt über Terminal perfekt.

Leider bekomme ich über PHP kein Ergebnis:

OUTPUT:
Status von Ger„t COM2: ----------------------

Baudrate: 9600 Parit„t: None Datenbits: 8 Stoppbits: 1 Zeitlimit: OFF 
XON/XOFF: OFF CTS-Handshaking: OFF DSR-Handshaking: OFF DSR-Prfung: OFF 
DTR-Signal: OFF RTS-Signal: OFF

Status von Ger„t COM2: ---------------------- Baudrate: 9600 Parit„t: 
None Datenbits: 8 Stoppbits: 1 Zeitlimit: OFF XON/XOFF: OFF 
CTS-Handshaking: OFF DSR-Handshaking: OFF DSR-Prfung: OFF DTR-Signal: 
OFF RTS-Signal: OFF

Ergebnis:

Leider leeres Ergebnis

1
<?php
2
/**
3
* EIN/AUSGABE ueber COM
4
*
5
* Einfache Ein/Ausgabe ueber COM Schnittstelle unter Windows
6
*
7
* @V0.1      2011.06.13 Schnittstelle angesprochen
8
*/
9
10
11
/**
12
* Set serial port parameters. Laut Doku: 9600 8-N-1
13
* Baud rate: 9600
14
* Parity (das "N" in "8-N-1") - Datenblock auf korrekten Inhalt zu überprüfen
15
* data - Character length (die "8" in "8-N-1")
16
* Stop bits (die  "1" in "8-N-1") 
17
* DTR - Data Terminal Ready 
18
* RTS - Request to Send [Sendeanforderung]
19
*/
20
$fp=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
21
$fp2=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
22
23
echo $fp; 
24
echo $fp2;
25
26
 
27
function senden($comport,$zeichen)
28
{
29
  $fp = fopen ("$comport", "w+");
30
  if (!$fp){
31
     echo "Port zum Schreiben nicht geöffnet!";
32
     }
33
     else {
34
     fputs ($fp, $zeichen);
35
     fclose ($fp);
36
     }
37
}
38
39
function lesen($comport2,$sekunden)
40
{
41
  $buffer = "";
42
  $fp2 = fopen ("$comport2", "r+");
43
  if (!$fp2){
44
   echo "Port zum lesen nicht geöffnet";
45
   }
46
   else{
47
     sleep($sekunden);
48
     $buffer .= fgets($fp2, 4096);
49
   }
50
   return $buffer;
51
   fclose ($fp2);
52
}
53
 
54
senden("COM2","X"); // den Text X senden
55
$lese = lesen("COM2","2"); // 2 Sekunden lang Daten von COM2
56
echo "Ergebnis:".$lese;
57
 
58
?>


Hat jemand eine Idee?

von g457 (Gast)


Lesenswert?

So ausm Bauch raus würd ich sagen nimm nur ∗einen∗ Stream (das was fopen 
zurückliefert). Gut möglich dass beim zweite Öffnen (in lesen()) schon 
alles vorbei ist. Zum Testen also sowas wie
[pseudocode]
1
fp = fopen(..);
2
fputs(fp, ..);
3
echo fgets(fp, ..);
4
fclose(fp);
[/pseudocode]

Fehlerbehandlung natürlich nicht unterschlagen.

HTH

von He K. (mr_sol)


Lesenswert?

Danke für den Hinweis.


Habe jetzt alles in einen

* oCOM (OOP) sauber verpackt
* mit einen Errorlogger versehen
* ein HTML Formular zum einfachen Testen angehängt


Senden klappt perfekt / Empfang hängt sich PHP auf (Endlosschleife)


Dank für jeden Hinweis


1
<?php
2
/**
3
* EIN/AUSGABE ueber COM
4
*
5
* Einfache Ein/Ausgabe ueber COM Schnittstelle unter Windows
6
*
7
* @V0.1 2011.06.12 Schnittstelle angesprochen
8
* @V0.2 2011.06.13 Lesen, Schreiben , OOP, Error
9
* @V0.3 2011.06.14 HTML Ein/Ausgabe
10
*/
11
12
13
/**
14
* Error Message Stack
15
*/
16
class errorMsg {
17
 static private $aMsg = array();
18
 static public function setError($p_sMsg = null) {self::$aMsg[] = $p_sMsg;}
19
 static public function getError() {return self::$aMsg;} 
20
 static public function isError() {return count(self::$aMsg) ? true : false;}  
21
}
22
23
24
25
/**
26
* I/O uber Schnittstelle
27
*/
28
class oCOM{ 
29
30
31
/**
32
* Konstruktor
33
*
34
* Set serial port parameters. Laut Doku: 9600 8-N-1
35
* Baud rate: 9600
36
* Parity (das "N" in "8-N-1") - Datenblock auf korrekten Inhalt zu überprüfen
37
* data - Character length (die "8" in "8-N-1")
38
* Stop bits (die  "1" in "8-N-1") 
39
* DTR - Data Terminal Ready 
40
* RTS - Request to Send [Sendeanforderung]
41
*
42
*/
43
 public function __construct()   {
44
 
45
$fp1=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
46
$fp2=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
47
errorMsg::setError($fp1);
48
errorMsg::setError($fp2);
49
}
50
51
52
/**
53
* Klasse wird zerstört
54
*
55
*/
56
 public function __destruct() {
57
 }
58
59
60
/**
61
* Senden der Daten ueber UART
62
*/
63
public function send($comport,$zeichen) {
64
  $this->fp1 = fopen ("$comport", "w+");
65
  if (!$this->fp1){
66
   errorMsg::setError("Port zum Schreiben nicht geöffnet!");  
67
     }
68
     else {
69
     fputs ($this->fp1, $zeichen);
70
     fclose ($this->fp1);
71
     }
72
}
73
74
75
/**
76
* Lesen der Daten ueber UART
77
*/
78
public function read($comport2,$sekunde) {
79
  $buffer = "";
80
  $this->fp2 = fopen ("$comport2", "r+");
81
  if (!$this->fp2){
82
   errorMsg::setError("Port zum lesen nicht geöffnet");  
83
   }
84
   else{
85
     sleep($sekunden);
86
     $buffer .= fgets($this->fp2, 4096);echo $buffer;echo "x";
87
   }
88
   return $buffer;
89
   fclose ($this->fp2);
90
}
91
} //END io
92
93
94
/**
95
* 
96
*/
97
98
$com="COM2";
99
$input="1";
100
101
if(isset($_GET["com"]))$com=$_GET["com"];
102
if(isset($_GET["input"]))$input=$_GET["input"];
103
104
$oCOM = new oCOM;
105
$oCOM->send($com,$input);                   // den Ziffer 2 senden
106
$lese = $oCOM->read($com,"3");       // 2 Sekunden lang Daten von COM2 abfragen
107
108
?>
109
110
111
112
113
114
115
116
117
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
118
     "http://www.w3.org/TR/html4/loose.dtd">
119
<html>
120
<head>
121
<title>IO Test</title>
122
</head>
123
<body>
124
<h3>Senden auf COM</h3>
125
<p>
126
127
  <form action="com_schnittstelle.php" method="get" enctype="MIME-Typ">
128
     <label>Schnittstelle: </label>
129
    <input name="com"type="text" value="COM2">
130
    <label>Sende Ziffer 0- 9: </label>
131
    <input name="input"type="text" value="1">
132
  <input type="submit" value="senden">
133
  </form>
134
135
136
<h3>Empfangen von COM</h3>
137
<code style="white-space:pre-wrap !important;">
138
<?php
139
echo "Ergebnis:".$lese;
140
?>
141
</code>
142
<h3>Error/Log</h3>
143
<p>
144
<?php
145
/**
146
* wenn Fehlermeldungen existieren, diese ausgeben
147
*/
148
if (errorMsg::isError()) {
149
 var_dump(errorMsg::getError());
150
}
151
?>
152
</p>
153
</body>
154
</html>

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Probier mal die "direct-io"-Funktionen aus: 
http://de.php.net/manual/de/ref.dio.php

von He K. (mr_sol)


Lesenswert?

Gibts dafür eine Demo oder Beispiel zum Nachvollziehen?

von He K. (mr_sol)


Lesenswert?

Habe jetzt eine minimal Version geschrieben.
1
<?php
2
3
$fp=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
4
5
$comport="COM2";
6
$zeichen="3";
7
8
$fp = fopen ("$comport", "w+");
9
if (!$fp){
10
     echo "Port zum Schreiben nicht geöffnet!";
11
     }
12
     else {
13
     fputs ($fp, $zeichen);
14
     fclose ($fp);
15
}
16
17
18
19
20
$fp2=`mode com2 BAUD=9600 PARITY=N data=8 stop=1 DTR=off  RTS=off`; 
21
22
$buffer = "";
23
$sekunden=1;
24
$fp2 = fopen ("$comport", "r+");
25
if (!$fp2){
26
   echo "Port zum lesen nicht geöffnet";
27
   }
28
   else{
29
     sleep($sekunden);
30
     $buffer .= fgets($fp2, 4096);
31
}
32
fclose ($fp2);
33
34
echo "Ergebnis:".$buffer;
35
 
36
?>



Funktioniert bei jeden zweiten Start.....seltsam und unstabil.

von He K. (mr_sol)


Lesenswert?

Erstmal vielen Dank für eure Unterstützung.

Konklusion:
Per PHP COM Schnittstelle ansprechen kann man mit JAEIN beantworten.

Anscheinend ist PHP nicht geeignet, stabile Ergebnisse zu liefern. 
Senden klappt einwandfrei, der Empfang ist ein Problem.

In der Demo klappt er nicht.
1
<?php
2
/**
3
* EIN/AUSGABE ueber COM
4
*
5
* Einfache Ein/Ausgabe ueber COM Schnittstelle unter Windows
6
*
7
* @V0.1 2011.06.12 Schnittstelle angesprochen
8
* @V0.2 2011.06.13 Lesen, Schreiben , OOP, Error
9
* @V0.3 2011.06.14 HTML Ein/Ausgabe
10
*/
11
12
13
/**
14
* Error Message Stack
15
*/
16
class errorMsg {
17
 static private $aMsg = array();
18
 static public function setError($p_sMsg = null) {self::$aMsg[] = $p_sMsg;}
19
 static public function getError() {return self::$aMsg;} 
20
 static public function isError() {return count(self::$aMsg) ? true : false;}  
21
}
22
23
24
25
/**
26
* I/O uber Schnittstelle
27
*/
28
class oCOM{ 
29
30
31
/**
32
* Konstruktor
33
*
34
* Set serial port parameters. Laut Doku: 9600 8-N-1
35
* Baud rate: 9600
36
* Parity (das "N" in "8-N-1") - Datenblock auf korrekten Inhalt zu überprüfen
37
* data - Character length (die "8" in "8-N-1")
38
* Stop bits (die  "1" in "8-N-1") 
39
* DTR - Data Terminal Ready 
40
* RTS - Request to Send [Sendeanforderung]
41
*
42
*/
43
 public function __construct(){}
44
 public function __destruct(){}
45
46
 
47
/**
48
* Senden der Daten ueber UART
49
*/
50
public function send($comport,$zeichen) { 
51
  `mode com2: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
52
  $fp = fopen ("$comport", "w+");
53
  if (!$fp)
54
  {
55
  errorMsg::setError("Port zum Schreiben nicht geöffnet!");
56
  }
57
  else {
58
  fputs ($fp, $zeichen);
59
  fclose ($fp);
60
  }   
61
}
62
63
/**
64
* Lesen der Daten ueber UART
65
*/
66
public function read($comport2,$sekunde) {
67
  `mode com2: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
68
  $buffer = "";
69
  $fp2 = fopen ("$comport2", "r+");
70
  if (!$fp2)
71
  {
72
  echo "Port zum lesen nicht geöffnet";
73
  }
74
  else
75
  {
76
  sleep($sekunden);
77
  $buffer .= fgets($fp2, 4096);
78
  }
79
  return $buffer;
80
  fclose ($fp2);
81
}
82
  
83
  
84
} //END io
85
86
87
/**
88
*  MAIN
89
*/
90
$com="com2";
91
$input="1";
92
$lese = "kein Ergebnis";
93
94
if(isset($_GET["com"]))$com=$_GET["com"];
95
if(isset($_GET["input"]))$input=$_GET["input"];
96
97
$oCOM = new oCOM;
98
$oCOM->send("com2","9"); 
99
$lese = $oCOM->read("com2","2"); 
100
echo $lese;
101
?>
102
103
104
105
106
107
108
109
110
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
111
     "http://www.w3.org/TR/html4/loose.dtd">
112
<html>
113
<head>
114
<title>IO Test</title>
115
</head>
116
<body>
117
<h3>Senden auf COM</h3>
118
<p>
119
120
  <form action="com_schnittstelle.php" method="get" enctype="MIME-Typ">
121
     <label>Schnittstelle: </label>
122
    <input name="com"type="text" value="COM2">
123
    <label>Sende Ziffer 0- 9: </label>
124
    <input name="input"type="text" value="1">
125
  <input type="submit" value="senden">
126
  </form>
127
128
129
<h3>Empfangen von COM</h3>
130
<code style="white-space:pre-wrap !important;">
131
<?php
132
echo $lese;
133
?>
134
</code>
135
<h3>Error/Log</h3>
136
<p>
137
<?php
138
/**
139
* wenn Fehlermeldungen existieren, diese ausgeben
140
*/
141
if (errorMsg::isError()) {
142
 var_dump(errorMsg::getError());
143
}
144
?>
145
</p>
146
</body>
147
</html>


Hier eine Link wo es klappt (aber nicht immer)
Beitrag "RS232 mit PHP"

Nur Senden klappt
http://www.phpclasses.org/package/3679-PHP-Communicate-with-a-serial-port.html#download

Nicht uninteressant
http://www.communitymx.com/content/article.cfm?page=2&cid=8658A


Falls noch jemand noch eine Idee oder Anregung hat bitte mitteilen. 
Danke im voraus.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.