Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> PHP obsługuje port COM[x] :)
Widmo
post
Post #1





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


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

Ten post edytował Widmo 21.08.2008, 14:58:50


--------------------
Widmo
Go to the top of the page
+Quote Post
Kicok
post
Post #2





Grupa: Zarejestrowani
Postów: 1 033
Pomógł: 125
Dołączył: 17.09.2005
Skąd: Żywiec

Ostrzeżenie: (0%)
-----


  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

Ten post edytował Kicok 21.08.2008, 18:25:50


--------------------
"Sumienie mam czyste, bo nieużywane."
Go to the top of the page
+Quote Post
elemek
post
Post #3





Grupa: Zarejestrowani
Postów: 71
Pomógł: 24
Dołączył: 14.08.2008

Ostrzeżenie: (0%)
-----


  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. ?>


Ten post edytował elemek 22.08.2008, 08:44:51


--------------------
Rzecz trudną rozbijam na kilka łatwiejszych :)
Pomogłem? Kliknij Pomógł.
Go to the top of the page
+Quote Post
Widmo
post
Post #4





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


  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


--------------------
Widmo
Go to the top of the page
+Quote Post
elemek
post
Post #5





Grupa: Zarejestrowani
Postów: 71
Pomógł: 24
Dołączył: 14.08.2008

Ostrzeżenie: (0%)
-----


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.

Ten post edytował elemek 22.08.2008, 08:40:20


--------------------
Rzecz trudną rozbijam na kilka łatwiejszych :)
Pomogłem? Kliknij Pomógł.
Go to the top of the page
+Quote Post
Widmo
post
Post #6





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


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?


--------------------
Widmo
Go to the top of the page
+Quote Post
elemek
post
Post #7





Grupa: Zarejestrowani
Postów: 71
Pomógł: 24
Dołączył: 14.08.2008

Ostrzeżenie: (0%)
-----


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.

Ten post edytował elemek 22.08.2008, 12:21:24


--------------------
Rzecz trudną rozbijam na kilka łatwiejszych :)
Pomogłem? Kliknij Pomógł.
Go to the top of the page
+Quote Post
Widmo
post
Post #8





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


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.

Ten post edytował Widmo 22.08.2008, 12:26:11


--------------------
Widmo
Go to the top of the page
+Quote Post
elemek
post
Post #9





Grupa: Zarejestrowani
Postów: 71
Pomógł: 24
Dołączył: 14.08.2008

Ostrzeżenie: (0%)
-----


  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

Ten post edytował elemek 22.08.2008, 12:58:11


--------------------
Rzecz trudną rozbijam na kilka łatwiejszych :)
Pomogłem? Kliknij Pomógł.
Go to the top of the page
+Quote Post
Widmo
post
Post #10





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


  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


--------------------
Widmo
Go to the top of the page
+Quote Post
elemek
post
Post #11





Grupa: Zarejestrowani
Postów: 71
Pomógł: 24
Dołączył: 14.08.2008

Ostrzeżenie: (0%)
-----


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.


--------------------
Rzecz trudną rozbijam na kilka łatwiejszych :)
Pomogłem? Kliknij Pomógł.
Go to the top of the page
+Quote Post
Widmo
post
Post #12





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


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

Ten post edytował Widmo 22.08.2008, 21:55:53


--------------------
Widmo
Go to the top of the page
+Quote Post
Kicok
post
Post #13





Grupa: Zarejestrowani
Postów: 1 033
Pomógł: 125
Dołączył: 17.09.2005
Skąd: Żywiec

Ostrzeżenie: (0%)
-----


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.

Ten post edytował Kicok 23.08.2008, 10:08:26


--------------------
"Sumienie mam czyste, bo nieużywane."
Go to the top of the page
+Quote Post
elemek
post
Post #14





Grupa: Zarejestrowani
Postów: 71
Pomógł: 24
Dołączył: 14.08.2008

Ostrzeżenie: (0%)
-----


@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ń...


--------------------
Rzecz trudną rozbijam na kilka łatwiejszych :)
Pomogłem? Kliknij Pomógł.
Go to the top of the page
+Quote Post
Widmo
post
Post #15





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


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


--------------------
Widmo
Go to the top of the page
+Quote Post
SirZooro
post
Post #16





Grupa: Zarejestrowani
Postów: 243
Pomógł: 32
Dołączył: 14.06.2007

Ostrzeżenie: (0%)
-----


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.


--------------------
Go to the top of the page
+Quote Post
Widmo
post
Post #17





Grupa: Zarejestrowani
Postów: 136
Pomógł: 0
Dołączył: 25.05.2003

Ostrzeżenie: (0%)
-----


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


--------------------
Widmo
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.08.2025 - 16:42