Com Schnittstelle unter Linux / php ansprechen (HB628)
ralphi
- php
Hallo Leute,
ich möchte gerne das A/D USB-Modul HB628 unter Linux zum laufen bringen.
Hintergrund ist, dass ich mit dem Raspberry PI die immer beliebter werdende Haus-Automation ausprobieren möchte.
Bislang hab ich damit noch keinen Erfolg, das Modul unter Linux, ansprechen zu können!
Auf dem Raspi ist Debian, LAMP mit php cli (comandzeilen php) installiert. Also ein php Programm über SSH einfach aufzurufen mit
Das modul zeigt sich mit:
/dev/ttyACM0
und
/dev/serial/by-id/usb-H-Tronc_GmbH_HB628_-_USB_I_O_Module-if00
/dev/serial/by-path/platform-bcm2708_usb-usb-0:1.2:1.0
Das Modul will nur einfache ASCII Zeichen (keine ANSI o.a.code)
Unter Win gibt es eine DLL bzw. mit dem Bräy Terminal v1.9b kann man es gut abfragen.
Hyperterminal, MSCOMM1 unter VB6 (ANSI), putty klappt nicht.
Eine Initialisierung oder sonstiges braucht das Modul nicht (Baudrate <= 256000) .
z.B. Auslesen des Eingangs A1:
Senden: c01
Rückgabe: 2Byte -> Wert 1Byte -> Prüfsumme
Sonst nix
Mit minicom bekomme ich auch kein Ergebnis:
Minicom – s serieller Anschluss /dev/ttyACM0
Kann ich tippen was ich will – keine Reaktion
Unter php:
Die Dio- function läuft nicht. Find ich auch nix in der phpinfo() steht auch unter: über dio geschrieben.
Unter meinem test.php kommt er bis zum lesen (pos1) und wartet:
<?php
//mode $com: 'BAUD=$bautrate PARITY=N data=8 stop=1 xon=off`;
echo "start sende c06\n";
$com="/dev/ttyACM0";
$fp = fopen ("$com", "r+");
if (!$fp) {
echo "Port zum lesen nicht geöffnet\n";
}else{
fputs ($fp, "c01"); // schreiben
//sleep($sekunden);
echo "pos1\n";
$lese = fgets($fp, 64); //lesen
echo "pos2\n";
echo "der buffer = " . $lese; //Variable $lese ausgeben
}
fclose ($fp);
exit;
?>
Was mach ich falsch?
Viele Grüße aus LA
Moin Moin!
Mit minicom bekomme ich auch kein Ergebnis:
Minicom – s serieller Anschluss /dev/ttyACM0
Kann ich tippen was ich will – keine Reaktion
Bring erst einmal minicom zum Laufen.
<?php
//mode $com: 'BAUD=$bautrate PARITY=N data=8 stop=1 xon=off`;
?>
Dir ist schon klar, dass die Zeile etwas tun solle, aber nichts tun kann? Das ist erstens auskommentiert, zweitens DOS/Windows-spezifisch und unter Linux garantiert nicht lauffähig, und drittens kann man nicht einfach Shell-Kommandos in ein PHP-Script reinkopieren und hoffen, dass PHP die an die Shell weitergibt.
Finde heraus, welche Kommunikationsparameter (Baud-Rate, Anzahl Daten-Bits, Anzahl Stop-Bits, Parity, Handshake) die Technik haben will. Die mode-Zeile läßt schonmal erahnen, dass ohne Parity, mit 8 Datenbits und einem Stop-Bit gewerkelt wird, und das Software-Handshake (XON/XOFF) nicht genutzt wird. Bleibt also die Baudrate und die Frage, ob und wenn ja, welches Hardware-Handshake (CTS/RTS oder DTR/DSR) benutzt wird.
Das Ganze stellst Du in minicom ein (RTFM) und probierst aus, ob die Technik mit sich reden läßt. Wenn das funktioniert, kannst Du Dich mal über die ioctls schlau machen, die Linux braucht, um eine serielle Schnittstelle passend einzustellen (das [Serial Howto](http://www.tldp.org/HOWTO/Serial-HOWTO.html) könnte dabei hilfreich sein), und wie man PHP dazu bringt, diese ioctls auszulösen.
Hmm, [anscheinend kann PHP keine ioctls](http://de.php.net/manual-lookup.php?pattern=ioctl&scope=quickref). Faszinierend.
Also bleibt Dir kaum etwas anderes übrig, als die Defaults für die serielle Schnittstelle per [stty](http://linux.die.net/man/1/stty) zu verändern, BEVOR du das Device in PHP öffnest. Oder Du benutzt eben etwas anderes als PHP.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
Hi Alex
danke für den tipp - ein kleiner Erfolg ;-)
Also bleibt Dir kaum etwas anderes übrig, als die Defaults für die serielle Schnittstelle per stty zu verändern, BEVOR du das Device in PHP öffnest.
nach dem minicom (noch mal alle einstellungen geprüft/eingestellt 115200 8N1 KEIN Handshake ) immer noch nicht fuzt, hab ich mich noch mal mit linux und dem befehl stty auflistung arg. beschäftigt.
speed 115200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <un
rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread clocal crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echopr
dann stopbit gesetzt und CTS/RTS wech (das war vorher falsch)
aktiviert (weiß nicht ob mans braucht)
Analogeingang A6 eingelesen:
uw
sollten eigentlich 3 Byte sein
alle 8 Analogeingänge eingelesen:
root@raspberry:~# cat /dev/ttyACM0
²sMÚ*h
sollten eigentlich 17 Byte sein
vielleicht ist es ja ein anderer Zeichencode oder nicht sichtbare asciis. - zumindest hab ich schon mal ne reaktion :-)
ich werd mal einen oder zwei eingänge auf masse legen - die floaten so vor sich rum
jetzt gehts ans php
hier bin ich noch nicht weiter - ich kann ja auch schlecht alles exec()en
<?php
//mode $com: 'BAUD=$bautrate PARITY=N data=8 stop=1 xon=off`;
?>
>
> Dir ist schon klar, dass die Zeile etwas tun solle, aber nichts tun kann? Das ist erstens auskommentiert, zweitens DOS/Windows-spezifisch und unter Linux garantiert nicht lauffähig, und drittens kann man nicht einfach Shell-Kommandos in ein PHP-Script reinkopieren und hoffen, dass PHP die an die Shell weitergibt.
>
der komplete code ist von jemanden, der mit purebasic geschrieben hat - bei ihm hats auch nicht funktioniert.
die windows-zeile hab ich nur auskommentiert und nicht gelösch, um sie nur als errinerungsstütze zu behalten, weil ich die einstellungen noch setzen wollte.
> Hmm, [anscheinend kann PHP keine ioctls](http://de.php.net/manual-lookup.php?pattern=ioctl&scope=quickref). Faszinierend.
wie schon erwähnt - phpinfo() zeigt mir das modul nicht
> Oder Du benutzt eben etwas anderes als PHP.
c++ und java bin ich zu doof, pascal ist schon knapp 2 Jahrzehnte her und basic weiß nicht.
bei so vielen php gurus in dem forum, wird sich doch hoffentlich noch einer erbarmen ;-)
Viele Grüße aus LA
--
ralphi
Moin Moin!
Analogeingang A6 eingelesen:
echo "c06" > /dev/ttyACM0
cat /dev/ttyACM0
uw
sollten eigentlich 3 Byte sein
Probier mal
od -t x1 < /dev/ttyACM0
Das sollte dir die Daten hexadezimal, Byte für Byte anzeigen. Mehr dazu in od(1).
alle 8 Analogeingänge eingelesen:
echo "c09" > /dev/ttyACM0
root@raspberry:~# cat /dev/ttyACM0
²sMÚ*h
sollten eigentlich 17 Byte sein
Vielleicht. Auch da hilft od.
jetzt gehts ans php
hier bin ich noch nicht weiter - ich kann ja auch schlecht alles exec()en
exec hilft Dir auch nicht unbedingt weiter, aber du brauchst statt des mode zwingend einen Aufruf von stty, weil PHP wie gesagt für ioctl zu doof ist. Und der Aufruf von stty muß vor dem open auf das Device stattfinden.
//mode $com: 'BAUD=$bautrate PARITY=N data=8 stop=1 xon=off`;
Dir ist schon klar, dass die Zeile etwas tun solle, aber nichts tun kann? Das ist erstens auskommentiert, zweitens DOS/Windows-spezifisch und unter Linux garantiert nicht lauffähig, und drittens kann man nicht einfach Shell-Kommandos in ein PHP-Script reinkopieren und hoffen, dass PHP die an die Shell weitergibt.der komplete code ist von jemanden, der mit purebasic geschrieben hat - bei ihm hats auch nicht funktioniert.
Und warum glaubst Du, dass nicht funktionierender PureBasic-Code in PHP plötzlich funktioniert?
die windows-zeile hab ich nur auskommentiert und nicht gelösch, um sie nur als errinerungsstütze zu behalten, weil ich die einstellungen noch setzen wollte.
So lange Du die serielle Schnittstelle nicht korrekt konfigurierst, wird GAR NICHTS funktionieren.
Hmm, anscheinend kann PHP keine ioctls. Faszinierend.
wie schon erwähnt - phpinfo() zeigt mir das modul nicht
Von welchem Modul redest Du? ioctl ist eine Funktion, die in der libc noch vorhanden ist, von PHP aber nicht weitergereicht wird.
Oder Du benutzt eben etwas anderes als PHP.
c++ und java bin ich zu doof, pascal ist schon knapp 2 Jahrzehnte her und basic weiß nicht.
Klassisches C reicht. Perl kann ioctl und hat fertige Libraries für den Zugriff auf serielle Schnittstellen unter Unix und Windows. Python kann ioctl und hat vermutlich auch Libraries für serielle Schnittstellen. Lua kann man ioctl beibringen. Selbst MUMPS kann mit seriellen Schnittstellen umgehen (auch wenn das alles andere als hübsch aussieht), und das ist mittlerweile 47 Jahre alt.
bei so vielen php gurus in dem forum, wird sich doch hoffentlich noch einer erbarmen ;-)
Klar, wenn Du Dir die Hose unbedingt mit glühenden Kneifzangen anziehen willst, ist das Deine Sache. Ich würde ein Projekt, bei dem ich fast zwingend auf ioctl angewiesen bin, nicht in einer Sprache angehen, die ioctl nicht kann.
Alexander
Hi leute, hi Alex,
So viel ge-googled hab ich noch nie - ich hab’s mit PHP hinbekommen.
Der Fehler war, dass ich nicht ALLE Einstellmöglichkeiten konsequent ein- bzw ausgeschalten habe.
Dh.
root@raspberry:~# stty -F /dev/ttyACM0 -hupcl
root@raspberry:~# stty -F /dev/ttyACM0 ignpar
root@raspberry:~# stty -F /dev/ttyACM0 -opost
root@raspberry:~# stty -F /dev/ttyACM0 -onlcr
root@raspberry:~# stty -F /dev/ttyACM0 -isig
root@raspberry:~# stty -F /dev/ttyACM0 -icanon
root@raspberry:~# stty -F /dev/ttyACM0 -iexten
root@raspberry:~# stty -F /dev/ttyACM0 -echo
root@raspberry:~# stty -F /dev/ttyACM0 -echoe
root@raspberry:~# stty -F /dev/ttyACM0 -echok
root@raspberry:~# stty -F /dev/ttyACM0 –echoctl
Alleine 9600 .. 115200 8N1 als Einstellung reicht nicht aus. (zumindest beim HB628), sonst hat man keine pure IO (Bytes hin, Bytes zurück).
Eine Aufstellung aller Einstellungen unter: Einstellungen
Jetzt hab ich:
root@raspberry:~# stty -a < /dev/ttyACM0
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl cstopb cread clocal -crtscts
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany
-imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl echoke
Als praktisches Modul hab ich die
php_serial.class.php gefunden. Ohne dem, dass extra so was geschrieben wurde, hätte ich auch nicht mehr geglaubt, das es unter php geht.
Mein funktionierendes Prog:
<?php
require "php_serial.class.php";
echo "start\n";
// function zum umwandeln des strings in werte
function strToHex($string)
{
$hex='';
for ($i=0; $i < strlen($string); $i++)
{
$hex .= dechex(ord($string[$i])) . "\n"; // n zum bessern zählen der bytes
}
return $hex;
}
// Let's start the class
$serial = new phpSerial;
// 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");
// We can change the baud rate, parity, length, stop bits, flow control
// ?? ob es nach der Einstellung mit stty noch nötig ist, weiß ich nicht ??
$serial->confBaudRate(9600); //Baud rate: 9600
$serial->confParity("none"); //Parity (this is the "N" in "8-N-1")
$serial->confCharacterLength(8); //Character length (this is the "8" in "8-N-1")
$serial->confStopBits(1); //Stop bits (this is the "1" in "8-N-1")
// Then we need to open it
$serial->deviceOpen();
// To write into
$serial->sendMessage("c09"); // c09 – alle 8 analogen Eingänge abfragen
// Or to read from
$read = $serial->readPort();
echo $read . "\n";
$data = strToHex($read) ;
echo $data . "\n";
// If you want to change the configuration, the device must be closed
$serial->deviceClose();
?>
root@raspberry:~# php /myprogs/class_ser.php
start
Á{@{[]Ñ
2
c1
2
7b
2
40
2
7b
1
8f
2
5b
1
86
1
5d
d1
17 Bytes sind korrekt ;-)
Alex – ich konnte mich mal wieder davor drücken, was neues zu lernen ;-). Ich Danke Dir für das Aufzeigen der Alternativen – hätte es doch nicht mit php geklappt.
PS die dio Befehle funktionieren nur unter Windows – Lustig, dass es mal andersrum ist.
Viele Grüße aus LA
Moin Moin!
Hi leute, hi Alex,
So viel ge-googled hab ich noch nie - ich hab’s mit PHP hinbekommen.
Der Fehler war, dass ich nicht ALLE Einstellmöglichkeiten konsequent ein- bzw ausgeschalten habe.Dh.
Tja, die kleinen Feinheiten ...
root@raspberry:~# stty -F /dev/ttyACM0 -hupcl
root@raspberry:~# stty -F /dev/ttyACM0 ignpar
root@raspberry:~# stty -F /dev/ttyACM0 -opost
root@raspberry:~# stty -F /dev/ttyACM0 -onlcr
root@raspberry:~# stty -F /dev/ttyACM0 -isig
root@raspberry:~# stty -F /dev/ttyACM0 -icanon
root@raspberry:~# stty -F /dev/ttyACM0 -iexten
root@raspberry:~# stty -F /dev/ttyACM0 -echo
root@raspberry:~# stty -F /dev/ttyACM0 -echoe
root@raspberry:~# stty -F /dev/ttyACM0 -echok
root@raspberry:~# stty -F /dev/ttyACM0 –echoctl
Das geht auch mit EINEM Aufruf von stty, einfach alle Parameter hintereinander nach -F /dev/ttyWhatever angeben.
Als praktisches Modul hab ich die
php_serial.class.php gefunden. Ohne dem, dass extra so was geschrieben wurde, hätte ich auch nicht mehr geglaubt, das es unter php geht.
Unter Linux macht das Modul auch nichts anderes als massenhaft Aufrufe von stty zu produzieren. Unter Windows werden entsprechende mode-Aufrufe generiert. Und auf allen anderen Unix-artigen Systemen funktioniert gar nichts, auch wenn stty vorhanden ist.
Alex – ich konnte mich mal wieder davor drücken, was neues zu lernen ;-).
Ich hab gerade bei PHP-Code oft den Eindruck, dass das das generelle Motto der PHP-Coder ist. Leider.
Ich Danke Dir für das Aufzeigen der Alternativen – hätte es doch nicht mit php geklappt.
PS die dio Befehle funktionieren nur unter Windows – Lustig, dass es mal andersrum ist.
Es gibt vieles, was nur unter Windoof funktioniert.
Zum Beispiel ein automatischer und absolut zuverlässiger Crash des Betriebssystems, sobald die Uptime versehentlich mal 49,7 Tage erreicht. ;-)
Im Ernst, alles was über File-I/O hinausgeht, ist selten über alle Betriebssystemgrenzen hinweg portabel. Innerhalb der Unix-Familie kommt man mit POSIX oft weiter, selbst unter NT und Nachfolgern gibt es eine kleine POSIX-API. Das hilft überhaupt nicht, wenn man sich mit GUIs oder Netzwerken rumschlagen muß.
Normalerweise erschlagen Hochsprachen oberhalb von C (Java, Ruby, Perl) die kleinen und größeren Unterschiede zwischen den Betriebssystemen durch einen Layer oberhalb von C/libc. Oft nutzt mal auch Libraries für Dinge, die zwar auf den meisten Systemen vorhanden, aber sehr unterschiedlich implementiert sind. So hat man ein gemeinsames Interface für die verschiedenen Betriebssysteme.
Das PHP da "mal wieder" hinterher hinkt, wundert mich nicht (1, 2, 3, 4).
Und weil wir schon weit vom Thema weg sind: Ja, auch andere Sprachen haben ihre häßlichen Ecken. Java muß alles mindestens drei mal neu erfinden. Perl schleppt Altlasten aus einem Vierteljahrhunder mit sich rum und braucht erstmal 10 Zeilen Code, um überhaupt benutzbar zu sein. Ruby ist ein Perl-Clone mit PHP-Ansprüchen und reichlich Sicherheitslücken. MUMPS - significant white space, Lochkarten-Look, und nicht mehr dezenter Pathologie-Duft. Python hat significant white space zur Kunstform erhoben.
Aber außer PHP hat kaum eine andere Sprache dermaßen viele Macken. Inkonsequent bis zum bitteren Ende, kein Plan, kein Konzept, kein Ansatz, den alten Mist mal aufzuräumen. Stattdessen immer mehr Gefrickel. Das kenne ich in der Form nur noch von Nischenprodukten, deren Nutzerbasis locker an zehn Fingern abgezählt werden kann (notfalls binär).
Alexander