Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: PHP obsługuje port COM[x] :)
Forum PHP.pl > Forum > PHP
Widmo
Witam,
potrzebuje dostać się do mojego urzadzenia przez port COM.
Znalazlem DLLke która obsługuje porty COM z poziomu PHP.

( http://www.easyvitools.com/phpserial/php_ser_SMS.html )

Mam manual do urządzenia ale brakuje mi troche doświadczenia z obsługą hardwaru.

http://widmo.biz/tmp/rw_protocol_eng.pdf

Oto moje wypociny winksmiley.jpg

  1. <?php
  2. ser_open('COM1', 9600, 8, 'none', 1, 'none' ); 
  3.  
  4. $str = ser_isopen();
  5. echo "Otwarte: $str<hr>";
  6.  
  7. echo ser_write( "0x02" ); // STX
  8.  
  9. echo ser_readbyte() . '<hr>'; // TU POWINNO BYĆ ACK
  10.  
  11. $seq = '0x00'; // kolejny numer
  12. $cmd = '0x60'; // komenda ( buzzer )
  13. $len = '0x00'; // dlugosc $dat
  14. $dat = '0x00'; // data
  15. $bcc = $seq xor $cmd xor $len xor $dat; // wyliczenie XOR
  16.  
  17. echo 'BCC: ' . $bcc . '<hr>';
  18.  
  19. ser_write( "x00x60x00x00" . $bcc . "x03"); // wyslanie komendy
  20.  
  21.  
  22. echo ser_readbyte() . '<hr>';
  23. ?>


Wynikiem jest to:
  1. Otwarte: COM1 9600 8 None 1 None
  2. ---------
  3. 21
  4. ---------
  5. BCC: 0x00
  6. ---------
  7. 21
  8. ---------


Czy nie znalazł by się ktoś kto pokazał by mi wzorzec jak powinna wyglądać pełna komenda z komentarzami?
Aktualnie w przykładzie wyżej staram się zmusić urzadzenie do wydania dziwięku ( 0x06 )

Wielkie dzięki za wszelką pomoc smile.gif
Kicok
  1. <?php
  2.  
  3. // NIE:
  4. echo '0x37';
  5. echo "0x37";
  6. echo 'x37';
  7. echo "x37";
  8. echo 'x37';
  9.  
  10. echo "x37x38x39";
  11.  
  12.  
  13. // TAK:
  14. echo 0x37;  // int
  15. echo "x37"; // ASCII
  16.  
  17. echo "x37x38x39";
  18.  
  19. ?>

Pomocne mogą być też funkcje: pack" title="Zobacz w manualu PHP" target="_manual, unpack" title="Zobacz w manualu PHP" target="_manual


I jeszcze jedno. Bitowy XOR to: ^, a nie: xor
elemek
  1. <?php
  2. /**
  3.  * Klasa do komunikacji z urządzeniem RHMMF1RW
  4.  * @author Lmshad@wp.pl
  5.  */
  6. class RHMMF1RW {
  7. const STX = "x02";
  8. const ETX = "x03";
  9. const ACK = "x06";
  10. const NAK = "x15";
  11.  
  12. /**
  13.  * Creates new connection to RHMMF1RW device using specified communication port.
  14.  *
  15.  * @param string $com communication port ex. COM1
  16.  */
  17. public function __construct() {
  18. ser_open('COM1', 9600, 8, 'none', 1, 'none' );
  19. $str = ser_isopen();
  20. echo "Otwarte: $str";
  21. }
  22.  
  23. /**
  24.  * Send command to RHMMF1RW device.
  25.  *
  26.  * @param int $seq hex sequence number ex. 0x00 
  27.  * @param int $cmd hex command number ex. 0x60
  28.  * @param string $data command data.
  29.  * @return bool|array array of result data or false if failed.
  30.  */
  31. public function command($seq, $cmd, $data = '') {
  32. ser_write(self::STX);
  33. if (($ack = chr(ser_readbyte())) != self::ACK) {
  34. return false;
  35. }
  36. $bcc = 0x00;
  37. $block = chr($seq) . chr($cmd) . chr(strlen($data)) . $data;
  38. foreach (str_split($block) as $byte) {
  39. $bcc ^= ord($byte);
  40. }
  41. $block .= chr($bcc) . self::ETX;
  42. echo ser_write($block);
  43.  
  44. if (($ack = chr(ser_readbyte())) != self::STX) {
  45. return false;
  46. }
  47.  
  48. echo ser_write(self::ACK);
  49.  
  50. $result['data'] = '';
  51. $result['seq'] = ser_readbyte();
  52. $result['status'] = ser_readbyte();
  53. $len = ser_readbyte();
  54. while ($len-- > 0) {
  55. $result['data'] .= chr(ser_readbyte());
  56. }
  57. $bcc = ser_readbyte();
  58. $etx = ser_readbyte();
  59. return $result;
  60. }
  61.  
  62. }
  63.  
  64. $dev = new RHMMF1RW();
  65. $dev -> command(0x00, 0x60);
  66. ?>
Widmo
  1. <?php
  2. // TAK:
  3. echo 0x37;  // int
  4. echo "x37"; // ASCII
  5.  
  6. echo "x37x38x39";
  7. ?>


tego mi było trzeba smile.gif

elemek - jesteś mistrzem - dziękuję bardzo.

Jednak są małe problemy:


  1. <?php
  2. public function __construct($com) {
  3. if (($this -> handle = fopen(".$com", 'w+b')  ) === false) {
  4. throw new Exception("Unable to open device $com.");
  5. }
  6. }
  7. ?>


zwraca:

  1. Warning: fopen(\\.\com1) [function.fopen]: failed to open stream: Invalid argument in C:\wamp\www\serial\example.php on line 20
  2.  
  3. Fatal error: Uncaught exception 'Exception' with message 'Unable to open device com1.' in C:\wamp\www\serial\example.php:21 Stack trace: #0 C:\wamp\www\serial\example.php(68): RHMMF1RW->__construct('com1') #1 {main} thrown in C:\wamp\www\serial\example.php on line 21


Poogooglałem więc trochę, zamieniłem to na:

  1. <?php
  2. public function __construct($com) {
  3. if (($this -> handle = fopen("$com:", 'w+b')  ) === false) {
  4. throw new Exception("Unable to open device $com.");
  5. }
  6. }
  7. ?>


Jest lepiej. bo działa, ale nie do końca, bo wywala TIMEOUTa w linii 46
  1. <?php
  2. if (($ack = fgetc($this -> handle) != self::STX)) { //46
  3. return ord($ack); //47
  4. }
  5. ?>


Zdaje sobie sprawe, ze pisanie na sucho bez urzadzenia jest trudne, ale może coś ktoś poradzi winksmiley.jpg

Widmo
elemek
Hmm faktycznie wcześniej otwierało mi '\\.\com1' ale nie zauważyłem ze tak naprawdę \\ w '' zmieniają się na jeden \ wiec fizycznie powstawał plik w katalogu głównym dysku smile.gif

Trzeba skorzystać z dllki którą znalazłeś.

Zmieniłem kod z wcześniejszego posta, wypróbuj.
Widmo
Działa, ale zwraca E2:

  1. <?php
  2. if (($ack = chr(ser_readbyte())) != self::STX) {
  3. return 'E2';
  4. }
  5. ?>


Czyli urzadzenie nie odpowiada...

Może warto na próbę zrobić polecenie na sztywno, żeby zobaczyć czy ta DLLka dziala?
elemek
hmm z tego co teraz czytam w dokumentacji buzzer wymaga 4 bajtow danych, sprobuj tak:

  1. <?php
  2. $dev->command(0x00, 0x60, "x00x20x20x03");
  3. ?>


co powinno dac efekt 3 beepow.
Widmo
niestety, komenda sie wysyla ale beepa nie ma.

sprobowalem jeszcze zmienic kolor LEDa:

  1. <?php
  2. echo $dev -> command(0x00, 0x50);
  3. ?>



zero reakcji.


  1. <?php
  2. if (($ack = chr(ser_readbyte())) != self::STX) {
  3. return 'E2:' . $ack;
  4. }
  5. ?>


zwraca

  1. <?php
  2. E2:˙
  3. ?>


zamienilem (zakomentowalem returna) :
  1. <?php
  2. if (($ack = chr(ser_readbyte())) != self::STX) {
  3. //return 'E2:' . $ack;
  4. }
  5. ?>


oraz: 

  1. <?php
  2. $bcc = ser_readbyte();
  3. $etx = ser_readbyte();
  4. print_r($result);
  5. ?>


zwraca:
  1. Array (
  2. [data] =>
  3. [seq] => -1
  4. [status] => -1
  5. )


trzech beepów brak.
elemek
  1. <?php
  2. //  stx seq cmd len rsv 480ms  3x bxx etx
  3. ser_write("x02");
  4. echo ser_readbyte() ."\n";
  5. ser_write("x00x60x04x00x20x20x03x67x03");
  6. echo ser_readbyte() ."\n";
  7. echo ser_readbyte() ."\n";
  8. echo ser_readbyte() ."\n";
  9. ?>


sztywna komenda beepa ;]

EDIT: teraz z odczytem ack, to musi w koncu zaczac dzialac smile.gif
Widmo
  1. <?php
  2. ser_open('COM1', 9600, 8, 'none', 1, 'none' );
  3.  echo "Otwarte: " . ser_isopen();
  4.  ser_write("x02x00x60x04x00x20x20x03x67x03");
  5. ?>


niestety dalej nic.

mi sie wydaje że to ta DLLka nawala.

Jak wróce to sprobuje jeszcze na sztywno przez fopen() to wrzucic.

smile.gif
elemek
sproboj przeedytowany kod wyzej, przez fopen nie da sie na pewno. wczesniej umknela mi jedna rzecz i dlatego myslalem ze mozna smile.gif pozatym ta dllka jest dobra bo czyta jednak jakies wartosci i to poprawne jak 21 (0x15) w Twoich poczatkowych zmaganiach.
Widmo
Jak zwykle zmodyfikowałem troche winksmiley.jpg


  1. <?php
  2. ser_open('COM1', 9600, 8, 'none', 1, 'none' );
  3.  echo "Otwarte: " . ser_isopen() . '<hr>';
  4.  
  5.  //  stx seq cmd len rsv 480ms  3x bxx etx
  6. ser_write("x02");
  7. echo '1: ' . ser_readbyte() . "<br>";
  8. ser_write("x00x60x04x00x20x20x03x67x03");
  9. echo '2: ' . ser_readbyte() . "<br>";
  10. echo '3: ' . ser_readbyte() . "<br>";
  11. echo '4: ' . ser_readbyte() . "<br>";
  12. ?>


zwraca '6' czyli ACK a potem już tylko -1...

  1. 1: 6
  2. 2: -1
  3. 3: -1
  4. 4: -1


To moze jeszcze dodam tyle:

http://thebyteworks.com/articles/ws2300/ws2300_php.html

Gosciu mowi ze napisal obsluge stacji pogodowej, moze to cos naprowadzi:

http://thebyteworks.com/articles/ws2300/ws2300_php.zip
Kicok
Cytat
  1. <?php
  2.  
  3. ser_write("x00x60x04x00x20x20x03x67x03");
  4.  
  5. ?>


A to "\x03" na końcu to skąd się wzieło?

Seq: 0x00
Cmd: 0x60
Len: 0x04
Data: 0x00202003
BCC: 0x67


EDIT
Fakt, nie zauważyłem tego na początku specyfikacji.
elemek
@Kicok: \x03 na koncu to znak konca transmisji (ETX) i jest wymagane.

@Widmo: -1 to 0xff czyli COMM_ERR. To może oznaczać błąd komunikacji. Może to kwestia sprzętowej kontroli przepływu danych heh, kończą mi się pomysły. Pokombinuj jeszcze w ustawieniach portu w menedżerze urządzeń...
Widmo
EXEc ktory byl dolaczony dziala bez prolemu...

to skoro z manualem sie nie da,
a mam od producenta DLLkę i API do urzadzenia - naiwne może pytanie: da sie użyć DLLki i zaimplementować w PHP ? worriedsmiley.gif
SirZooro
Myślę że powinno się dać - poczytaj o rozszerzeniu W32api. Jeżeli czujesz się na siłach możesz też napisać sobie własne rozszerzenie PHP które będzie wołać funkcje z biblioteki DLL którą posiadasz.
Widmo
Po parunastu godzinach siedzenia - stwierdzam - ze ta DLLka nie dziala jak powinna.

Odpaliłem sniffera portu COM i widze ze wyglada to tak

0x02 ( START )

0x06 ( ACK )

------ ( CISZA )

czyli po ack PHP nic nie wysyla do portu :/

zaczynam zabawe z linuxem - moze klasa PHP SERIAL z phpclasses.org bedzie lepsza winksmiley.jpg
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.