Ir para conteúdo
Fernando Rafael

Leitura de porta serial (COM ou LPT) com PHP

Recommended Posts

Estou tendo problemas com a leitura de porta serial com PHP, consigo facilmente escrever na mesma, mas sempre que no comando de abertura da porta eu coloco que haverá permissão de leitura o PHP trava e fica carregando infinitamente, e a porta fica bloqueada e só libera quando reiniciado o computador.

 

Segue o cod:

exec('MODE COM1:9600,n,8,1'); //seta configuração na porta COM

$fp=fopen("COM1","r+b");

if(!$fp) {
    echo("Erro ao abrir a porta com1");
    exit;
} else {    
    echo("COM1 aberta <br>");
}

fwrite($fp,Chr(5));  //escrevendo valor na porta

sleep(1); //pausa para retorno dos dados

echo (fgets($fp));

fclose($fp);

já tentei  colocar:

fopen("COM1", "r+b");

fopen("COM1", "r+t");

fopen("COM1", "r");

fopen("COM1", "w+");

fopen("COM1", "r+");

 

para escrever consigo normal, com o fopen("COM1", "w");.  mas já para ler.....

 

Notei que na internet tem muito sobre esse problema, inclusive falaram em permissões de usuário, sendo que nos casos em que conseguiram, estavam usando o Linux.

Eu estou usando o W7 e W10 com PHP 5.2, se for o caso de permissões, como resolvo isso? preciso configurar mais alguma coisa no php.ini?

 

Também já tentei usar uma classe: phpSerial

 

Mas retorna o seguinte erro:

Warning: Reading serial port is not implemented for Windows in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\balanca\php_serial.class.php on line 503

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Testando um pouco mais, reparei que o PHP não trava quando abrimos a porta com permissão de leitura (w+, r, r+ e etc...), mas sim quando tentamos exibir seu retorno, nos seguintes comandos:

 

fread($fp);

ou  

fgets($fp);

 

Também tentei limitar o tamanho em bytes da leitura, mas sem sucesso...   : (

 

fread($fp, 1024);

ou  

fgets($fp, 1024);

 

Vi um cara dizendo que conseguiu usando comandos CMD via "exec" do PHP, mas não citou nenhuma fonte ou código....

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi boa tarde EdCesar.

testei a classe indicada por você, mas sem sucesso...

 

Segue o código completo:

<?php

include 'PhpSerial.php';
// 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("COM6");
// We can change the baud rate, parity, length, stop bits, flow control
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
// Then we need to open it
$serial->deviceOpen();
// To write into
$serial->sendMessage("Hello !");
// Or to read from
$read = $serial->readPort();
// If you want to change the configuration, the device must be closed
$serial->deviceClose();
// We can change the baud rate
$serial->confBaudRate(9600);

?>

 

 

Na linha:  $serial->deviceOpen(); ele mostra o seguinte erro no navegador:

 

Warning: Unable to open the device in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\balanca\PhpSerial.php on line 149

 

A classe que testei antes foi essa: https://www.phpclasses.org/browse/file/17926.html

na qual retorna o seguinte erro, também quando se tenta ler algo (Linha: $read=$serial->readPort();):


 

require "php_serial.class.php";
$serial = new phpSerial;
$serial->deviceSet("COM6");
$serial->confBaudRate(9600);

$serial->deviceOpen();
$serial->sendMessage(chr(5));
sleep(7);
$read=$serial->readPort(); //tabém da erro ao executar a leitura
$serial->deviceClose();

Retorno no navegador:

Warning: Reading serial port is not implemented for Windows in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\balanca\php_serial.class.php on line 503

 

A porta funciona, pois consigo comunicar normal com outras aplicações, incluindo simuladores de balança, Serial Port Monitor e etc...

 

 

Spoiler


 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa tarde, continuando as buscas...

 

achei um comando para setar um timeOut no PHP (Colocar "stream_set_timeout($fp, 10);"  depois de abrir a porta), mas não funcionou, continua carregando infinitamente...

 

Achei um equivalente em powerShell, que sem o comando de timeOut fica rodando infinitamente...

segue o cod:

 

$port= new-Object System.IO.Ports.SerialPort COM6,9600,None,8,One

$port.ReadTimeout = 10000

$port.Open()

while($myinput = $port.ReadLine())
{
$myinput
}

$port.Close()

 

Mas não me retornou nada depois que entra em timeOut...

 

Bem, estou usando um simulador de balança (filizola/toledo) juntamente com um simulador de porta serial, testo a conexão com um programa de monitoramento de porta ou com o PC Scale da Filizola, e neles eu tenho retorno....

 

OBS: o simulador de balança tem um botão que envia dados para a porta, sem a necessidade de escrever na porta para que a mesma retorne algo.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vendo em muitos Fóruns, notei que o PHP tem bloqueios para leitura de portas seriais no Windows, sendo necessário configurar ou usar DLL (não encontrei tutoriais do tipo).

 

Bem...  Resolvi da forma mais aceitável diante da situação (ambiente Windows):

Fiz um programa em JAVA (exportado em um arquivo .jar) que recebe os parâmetros da porta serial e efetua a leitura da mesma. Mas fiz de uma forma mais diretamente "ligada" ao PHP. Sabendo que o arquivo .jar pode ser executado pelo CMD passando até mesmo parâmetros por linha de comando, fiz com que o PHP acionasse esse arquivo pelo comando "exec" ou "passthru" e depois tratei o retorno no próprio PHP, acredito que dessa forma é bem melhor do que ficar criando arquivos .txt para ficar lendo depois...

Então, sem mais delongas segue os fontes (JAVA e PHP):

PHP:

$comando_cmd="java -jar ler_serial.jar 9600 8 1 0 COM3 ENQ"; //Arquivo seguido dos parâmetros que serão capturados pelo arquivo .jar (separados por espaços).  OBS: só coloquei parâmetros pois não quis criar um arquivo .jar para cada tipo de porta ou configurações e comandos (ENQ por exemplo serve apenas para saber qual comando será usando no arquivo .jar, deve haver alguma forma de executar os comandos no JAVA que estejam armazenados em uma variável, eliminando assim os "if" e "else" para cada instrução dentro do arquivo .jar).

echo passthru($comando_cmd); //exibe o retorno.

 

JAVA:

import jssc.SerialPort; //Para funcionar é preciso adicionar no projeto uma biblioteca (usei essa: jSSC-2.7.0-Release.zip), vale pesquisar como adicionar, é fácil
import jssc.SerialPortException; //Para funcionar é preciso adicionar no projeto uma biblioteca (usei essa: jSSC-2.7.0-Release.zip), vale pesquisar como adicionar, é fácil

//Fonte sobre essa biblioteca: http://nakalabs.herokuapp.com/articles/arduinoAndJava.html

public class Main {
    
    public static void main(String[] args) throws InterruptedException {
   

         //Parametros estáticos, caso não usem os valores passados por linha de comando
        /*
        int BAUD_RATE =  9600;
        int DATA_BITS = 8;
        int STOP_BITS = 1;
        int PARITY    = 0;
        String SERIAL_PORT = "COM2";
        */
        
        //Armazena os parâmetros nas variáveis
        int BAUD_RATE =  Integer.parseInt(args[0]); //9600
        int DATA_BITS = Integer.parseInt(args[1]); //8
        int STOP_BITS = Integer.parseInt(args[2]); //1
        int PARITY    = Integer.parseInt(args[3]); //0
        String SERIAL_PORT = args[4]; //COM3
        
        String COMANDO ="ENQ"; //Comando inicial, caso nada seja passado como parametro, vai executar um ENQ (muito comum em comunicação serial)
        
        if(args[5].equals("ENQ")){ //Serve apenas para comparar o parâmetro passado e  executar algum comando previamente programado
            
            COMANDO =  ""+(char)5; //Coloquei ""+ (aspas dupla concatenada) só para aceitar como String, pois nem todo comando é do tipo (char) no meu caso
        }
        
        else if(args[5].equals("BEL")){ //Outro comando, e assim vai...
            
            COMANDO =  ""+(char)7+"p";  //Salientando que esses comandos são das minhas necessidades, isso vai depender do comando que o dispositivo esteja aguardando para retornar algo...
        }    
    
        SerialPort serialPort = new SerialPort(SERIAL_PORT);
        
        try {
            //Os comandos "exec" e "passthru" capturam esses retornos, basta exibilos ao seu favor...
            System.out.println("Porta aberta: " + serialPort.openPort());
            System.out.println("Parametros configurados: " + serialPort.setParams(BAUD_RATE, DATA_BITS, STOP_BITS, PARITY));
            System.out.println("Enviado mensagem: " + serialPort.writeString(""+COMANDO+"")); //Aqui ele escreve o comando na porta
            Thread.sleep(1000); //Aguarda 1 segundo para ler a porta
            //System.out.println("Retorno: " + serialPort.readString()); //Retorno da porta em String
            System.out.println("Retorno: " + serialPort.readHexString("")); //Retorno da porta em Hexadecimal, Com "" (aspas dupla) no parâmetro, significa que não haverá espaços entre os valores retornados ou colocando qualquer caractere, servirá como separador.
            System.out.println("Porta fechada: " + serialPort.closePort());
        
        }
        catch (SerialPortException ex){
            System.out.println(ex);
        }
    }
}

Postei essa mesma solução no ACBR, Imaster e Devmedia. nos que suportarem anexos, colocarei também a biblioteca do JAVA zipada.

 

Não sou bom em programação Java, caso alguém tenha melhorias para o código, ficarei muito grato... Vale visitar meu site: www.sisnorg.com (ainda em desenvolvimento, mas funcional para um possível contato comigo).

Abraços a todos que me ajudaram nos mais diversos fóruns... 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Rafael, é possível ler essas portas sem bloqueio desenvolvemos uma aplicação no trablho que envia comando hexadecimais para para um equipamento com porta serial, no caso usamos um cabo conversor de usb para serial.

 

usamos a seguinte codificação:

//Passa os paramentros de acesso para a porta COM, aqui no caso a porta com
exec("mode com5: BAUD=9600 PARITY=n DATA=8 STOP=1 to=off dtr=off rts=off");

//Faz a abertura em modo de escrita
$fp =fopen("com5", "w");

após a abertura você pode enviar o comando:

fwrite($fp, "mensagem a ser enviada"); //Hexa para camera 1
fclose($fp);

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi Icarof, o problema com PHP não era a escrita, mas sim a leitura (em ambiente Windows), o PHP sempre travava na Leitura, minha solução foi deixar o PHP com a escrita, e para os casos em que se faz necessário a leitura o Java entra em ação.

Compartilhar este post


Link para o post
Compartilhar em outros sites

entendo, no caso não faziamos a leitura, os dados eram enviado direto a maquina que recebia os camandos

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Conteúdo Similar

    • Por ILR master
      Fala galera, tudo bem?
       
      Tenho o seguinte codigo:
       
       class Data {
      public static function ExibirTempoDecorrido($date)
      {
          if(empty($date))
          {
              return "Informe a data";
          }
          $periodos = array("segundo", "minuto", "hora", "dia", "semana", "mês", "ano", "década");
          $duracao = array("60","60","24","7","4.35","12","10");
          $agora = time();
          $unix_data = strtotime($date);
          // check validity of date
          if(empty($unix_data))
          {  
              return "Bad date";
          }
          // is it future date or past date
          if($agora > $unix_data) 
          {  
              $diferenca     = $agora - $unix_data;
              $tempo         = "atrás";
          } 
          else 
          {
              $diferenca     = $unix_data - $agora;
              $tempo         = "agora";
          }
          for($j = 0; $diferenca >= $duracao[$j] && $j < count($duracao)-1; $j++) 
          {
              $diferenca /= $duracao[$j];
          }
          $diferenca = round($diferenca);
          if($diferenca != 1) 
          {
              $periodos[$j].= "s";
          }
          return "$diferenca $periodos[$j] {$tempo}";
      }
      }
       
      Funciona redondinho se o valor retornado for de algumas horas, mas...
      Quando passa de dois meses, ele retorna a palavra mess. Deve ser por conta dessa linha
      if($diferenca != 1) 
          {
              $periodos[$j].= "s";
          }
       
      Quero que modre:
       
      2 meses atrás
      e não
      2 mess atrás.
       
      Espero que tenham entendido.
       
      Valeu
    • Por Carlos Web Soluções Web
      Olá...
      Estou tentando fazer o seguinte !!
      Listando dados em tabela !!
      Gostaria que....se na listagem houver 4 linhas...indepedente de seu número de ID, faça a listagem em ID ser em ordem 1 2 3 4 !!
      Exemplo...se tiver uma listagem de dados que está em ID 1 3 3...faça ficar 1 2 3 !!

       
      echo "<table class='tabela_dados' border='1'> <tr> <td>ID</td> <td>Nome Empresa</td> <td>Responsável</td> <td>Telefone 1</td> <td>Telefone 2</td> <td>E-mail 1</td> <td>E-mail 2</td> <td>Endereço</td> <td>CEP</td> <td>Bairro</td> <td>AÇÃO 1</td> <td>AÇÃO 2</td> </tr> "; $sql = "SELECT ID FROM usuarios_dados WHERE Usuario='$usuario'"; $result = $conn->query($sql); $num_rows = $result->num_rows; $Novo_ID = 1; for ($i = 0; $i < $num_rows; $i++) { $registro = $result -> fetch_row(); $sql2 = "UPDATE usuarios_dados SET ID='$Novo_ID' WHERE ID='$Novo_ID'"; $result2 = $conn->query($sql2); $Novo_ID++; } $sql = "SELECT * FROM usuarios_dados"; $result = $conn->query($sql); if ($result->num_rows > 0) { // output data of each row while($row = $result->fetch_assoc()) { echo "<tr> <td>$row[ID]</td> <td>$row[Nome_Empresa]</td> <td>$row[Responsavel]</td> <td>$row[Telefone_1]</td> <td>$row[Telefone_2]</td> <td>$row[Email_1]</td> <td>$row[Email_2]</td> <td>$row[Endereço]</td> <td>$row[CEP]</td> <td>$row[Bairro]</td> <td> <form method='post' action='Editar_Dados.php'> <input type='hidden' name='usuario' value='$usuario'> <input type='hidden' name='senha' value='$senha'> <input type='hidden' name='ID' value='$row[ID]'> <input type='submit' style='padding: 10px;' value='EDITAR'> </form> </td> <td> <form method='post' action='Deletar_Dados.php'> <input type='hidden' name='usuario' value='$usuario'> <input type='hidden' name='senha' value='$senha'> <input type='hidden' name='ID' value='$row[ID]'> <input type='submit' style='padding: 10px;' value='DELETAR'> </form> </td> </tr> "; } } else { echo "0 results"; } $conn->close();  
    • Por ILR master
      Boa tarde pessoal, tudo bem ?
       
      Eu uso o tinymce para cadastro de textos no meu siite, porém, quero fazer um sistema para que os colunistas possam fazer o próprio post.
      O problema do tinymce, é que ele mantém a formatação do texto copiado, como tamanho de fonts, negritos, etc... Quero que o usuário cole o texto e a própria textarea limpe a formatação para que ele formate como quiser.
       
      A pergunta é:
       
      O tinymce tem uma opção para desabilitar a formatação quando um texto é colocado?
      Tem alguma função via java ou php para retirar a formatação assim que o texto é colado?
      Ou é melhor usar um outro editor?
       
      Agradeço deste já.
    • Por Giovanird
      Olá a todos!
      Tenho uma pagina que possui uma DIV onde coloquei uma pagina PHP.
      Uso a função setInterval para atualizar a pagina inclusa dentro da DIV.
      O problema é que ao acessar o site , a DIV só me mostra a pagina inclusa somente quando completo o primeiro minuto.
      Preciso que a pagina inclusa já inicie carregada
       
      Meu código JavaScript e a DIV com a pagina PHP
       
      <script> function atualiza(){ var url = 'direita.php'; $.get(url, function(dataReturn) { $('#direita').html(dataReturn); }); } setInterval("atualiza()",60000); </script> <div> <span id="direita"></span> </div>  
    • Por juliosonic
      Boa noite..
      Estou desenvolvendo um site de https://www.maithunatantra.com.br/ e estou com um duvida sobre o menu de navegação da versão mobile.
      O menu que tem o dropdown "Terapeutas" e "Terapias" quando clico em cima ele expande como deve ser, mas quando clico denovo para recolher os submenus
      nao acontece nada.. segue o trecho do codigo do menu..
      <div class="collapse navbar-collapse" id="navbarsExample09">             <ul class="navbar-nav ml-auto">               <li class="nav-item  active"><a class="nav-link" href="index.html">Home</a></li>               <li class="nav-item  active"><a class="nav-link" href="about-us.html">Quem Somos</a></li>               <li class="nav-item dropdown1">                     <a class="nav-link dropdown-toggle" data-toggle="dropdown1" href="#">Terapeutas</a>                     <ul class="dropdown-menu">                         <li><a class="dropdown-item" href="terapeuta-julio-cezar.html">Julio Cezar</a></li>                         <li><a class="dropdown-item" href="terapeuta-pamela-priscila.html">Pamela Priscila</a></li>                     </ul>                                    </li>               <li class="nav-item dropdown">                     <a class="nav-link dropdown-toggle" data-toggle="dropdown1" href="#">Terapias</a>                     <ul class="dropdown-menu" aria-labelledby="dropdown01">                         <li><a class="dropdown-item" href="o-que-e-reiki.html">O que é Reiki</a></li>                         <li><a class="dropdown-item" href="beneficios-reiki.html">Benefícios do Reiki</a></li>                         <li><a class="dropdown-item" href="principios-reiki.html">Princípios do Reiki</a></li>                         <li><a class="dropdown-item" href="animais-reiki.html">Reiki em Animais</a></li>                         <li><a class="dropdown-item" href="animais-reiki.html">Estudos Sobre Reiki</a></li>                         <li><a class="dropdown-item" href="terapia-massagem-tantrica.html">Terapia Tântrica</a></li>                     </ul>               </li>               <li class="nav-item  active"><a class="nav-link" href="blog.html">Blog</a></li>                <li class="nav-item"><a class="nav-link" href="contato.html">Contato</a></li>             </ul>         </div>  
      Massagem Tantrica em Curitiba
      Tantra Curitiba
      Massagem Tântrica
      Tantra
      Julio Darshan

      Obrigado
      Att
      Julio Cezar
       
       
       
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.