Controlando a Arduino com PHP via porta serial
É isso mesmo, o PHP pode escrever ou ler dados da porta serial, e com isso podemos controlar a Arduino.
Você pode ligar o seu ar-condicionado, cafeteira, luz, etc… via Internet, e de uma forma bem simples.
Serialproxy também é uma ótima forma de se conectar a Arduino via Internet, utilizei no projeto Twitter Hardware, mas este post é sobre PHP, então vamos lá.

Vou utilizar o exemplo descrito no post “Controlando Led RGB com Arduino e Processing” (trocando o Processing pelo PHP).
A função fopen do PHP da suporte a escrita na porta serial:
Linha 1) Abre a conexão com a COM2 (porta serial onde a minha Arduino está conectada).
Linha 2) Escreve na porta
Linha 3) Fecha a conexão
Código PHP do exemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?php /** * Arduino + PHP * * @author Bruno Soares * @website www.bsoares.com.br */ $color = $_REQUEST['color']; if (isset($color) && !empty($color)) { $color = hexdec($color); $message = '^' . $color . '$'; // USB Serial Port (COM2) $portAddress = 'COM2'; // Open connection on port $port = fopen($portAddress, 'w'); // Necessary when the Arduino reset after the connection sleep(2); // Send chars fwrite($port, $message); // Close connection fclose($port); } ?> |
Linha 12) Converte a cor de hexadecimal para decimal.
Linha 13) Coloca os caracteres que indicam o inicio e fim da mensagem.
Linha 16) Define a variável com o endereço da porta (no meu caso COM2).
Linha 19) Abre a “conexão” com a porta serial.
Linha 22) Pausa o código por 2 segundo, pois a Arduino costuma reiniciar quando é feita uma conexão a ela.
Linha 25) Escreve a mensagem com a cor na porta serial.
Linha 28) Fecha a “conexão” com a porta serial.
Update 09/07/2009:
Lendo dados:
Tenho recebido diversos e-mails e até alguns comentários de pessoas que precisam ler dados de um sensor, potenciometro, ou qualquer coisa conectada a Arduino, e isso via PHP. Então vamos lá, preparei um código que faz isso de forma fácil.
Acredito que um problema que o pessoal tem tido com esta tarefa é: você deve se dar tempo para a mensagem chegar a Arduino (não que isso seja muito tempo), e também para que a Arduino consiga responder:
Código Arduino:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * Arduino + PHP * * @author Bruno Soares * @website www.bsoares.com.br */ #define ANALOG_PIN 4 void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0) { if (Serial.read() == '1') Serial.print(analogRead(ANALOG_PIN), DEC); } } |
Código PHP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <?php /** * Arduino + PHP * * @author Bruno Soares * @website www.bsoares.com.br */ // Conecta na porta $port = fopen('COM2', 'w+'); // Em alguns casos a Arduino pode reiniciar, por isso // é bom esperar para enviar informação depois de conectar sleep(2); // Envia "1" para o programa na Arduino saber que deve responder fwrite($port, '1'); // Espera para que o dado enviado pelo PHP chegue até a Arduino sleep(1); // Agora que a Arduino "Provavelmente já respondeu", pega // o valor da resposta echo fgets($port); // Fecha a conexão com a porta fclose($port); ?> |
O que esse código faz?
A Arduino fica em loop esperando receber pela porta serial o numero 1, assim que recebido ela lê a voltagem do pino analógico 4 e escreve na porta serial.
O PHP abre a porta serial, escreve “1″, e espera para ler novamente, quando lê novamente encontra o valor do pino analógico 4, assim como a Arduino escreveu.
Bom, espero que este exemplo acabe com as dúvidas do pessoal que precise ler dados da Arduino :)
Observações:
Caso você precise fazer um projeto onde muitos usuário vão acessar o script que escreve na porta serial, você deve implementar uma fila, de forma a não ter um usuário escrevendo na porta ao mesmo tempo que outro, isto geraria um erro.
O código fonte escrito para a Arduino é o mesmo do post Controlando Led RGB com Arduino e Processing
Faça o download do código fonte aqui.
Conteúdo relacionado:
Arduino: http://www.arduino.cc/
Referência: http://www.arduinoprojects.com/?q=node/10
jQuery ColorPicker: http://www.eyecon.ro/colorpicker/
Posts relacionados:
Respondendo a pergunta de Leandro (via contato por e-mail), sim é possível ler dados da porta serial via php. O comando file_get_contents, fread, fgets, e outros podem ler esses dados.
Mas dependendo da aplicação recomendo usar um Serialproxy (como feito no projeto Twitter Hardware). Estou para fazer um post sobre este assunto já faz um bom tempo, só preciso finalizar um outro experimento para utilizar a arduino na montagem de um post sobre o Serialproxy..
Caso seja melhor para o seu projeto ler a porta via PHP, recomendo que você escreva um bit pedindo o dado e prepare a arduino para escrever o valor necessário toda vez que receber esse bit da porta. Você só precisa tomar cuidado que a arduino costuma reiniciar quando é feita uma conexão via porta serial.
De qualquer forma, experimente o Serialproxy ;-)
Could I control the my security cameras with it. debt
Olá jacob, você pode sim, mas aconselho a usar serial proxy! tem uma resposta muito boa.
Dê uma olhada no post http://blog.bsoares.com.br/arduino/twitter-hardware , você pode usar de exemplo. Fiz um programa em Adobe AIR (ActionScript) que se conecta no serialproxy de uma maquina qualquer para enviar comandos para a Arduino.
Ai amigo…sou estudante na area de desenvolvimento…
emulei aqui uma porta serial e tudo funcionou….mas só enviando dados…
o lance agora é ler….
não acho nenhuma documentação…só me resta vc msm amigo.. srsrsrrsrs…
estamos aqui no aguardo…
abraços
Olá Amauri, então o primeiro comentário responde a sua pergunta http://blog.bsoares.com.br/php/controlling-arduino-with-php/comment-page-1#comment-1677
Caso seja melhor para o seu projeto ler a porta via PHP, recomendo que você escreva um bit pedindo o dado e prepare a arduino para escrever o valor necessário toda vez que receber esse bit da porta. Você só precisa tomar cuidado que a arduino costuma reiniciar quando é feita uma conexão via porta serial.
De qualquer forma, experimente o Serialproxy ;-)
Blz amigo….vou dar uma estudada …
Só mais uma coisa acima vc falou que eu poderia fazer a leitura com fread,fgets e por ai vai…..
eu até consigo enviar dados para a serial…mas não ler esses dados…
amigo será q vc poderia mandar um exemplo vc iria estar dando uma força e tanto…
só o trexo de leitura pq enviar dados eu consigo…
abraços e to no aguardo amigo…
Salve Amauri! Acabei achando melhor fazer um Update no meu post explicando melhor a sua dúvida, da um olhada, preparei o código e comentei ele para não ter erro :)
[]‘s
Opá..amigo obrigado pela explicação…
Mas eu quero msm é fazer a troca de dados com relogio de ponto catraca para controle de acesso e tal…e tipo..consigo mandar dados tranquilamente, mas não consigo fazer a leitura..
esse tipo de conexão é realizada de forma diferente ?? ou posso usar da msm forma ??
Amauri, da uma olhada no post na parte “Lendo dados” que tem um exemplo bem bacana. Presta bem atenção no delay que você precisa dar para esperar o dado chegar a porta…
Olá!
é exatamente isso que eu preciso! ler um porta serial ou usb…
só que agora quero saber se a porta serial poderia ser lida do
client ? ou nao tem como?
exemplo o cara vai ter um botão ali que ele clica e pega os dados
da porta que esta na maquina dele, acho que por php nao seria possivel
mas quem sabe por js ou sei la sabe me dizer se tem como?
Então Felipe, é possível sim, assim como mostro no vídeo…
No caso do exemplo deste tutorial estou apenas enviando o RGB para o servidor (via PHP), mas no post tem a explicação de como ler um dado da porta serial via PHP, (Update 09/07/2009: Lendo dados), e como você pode utilizar PHP este dados podem estar em um servidor (ou seja, a máquina que controla a arduino tem PHP e um servidor Apache, IIS.. instalado).
Mas antes de fazer qualquer coisa com PHP dê uma olhada no post http://blog.bsoares.com.br/arduino/twitter-hardware , você pode usar de exemplo. Fiz um programa em Adobe AIR (ActionScript) que se conecta no serialproxy de uma maquina qualquer para enviar comandos para a Arduino.
[]‘s
então bruno…
o que estou precisando é para o uso com um periférico que sera desenvolvido
aqui pelo pessoal do hardware da empresa, não se sabe se será usb ou serial,
mas por exemplo eu vou ate uma lan house qualquer conecto o periférico, faço
um login de acesso restrito a uma pagina e daquela maquina na lan house, que
conectei o periférico que vou ter que ler a porta serial ou usb, não no php server…
não sei se estava sendo tão esclarecedor…
Entendi!, bom dessa forma não da não…
E acredito que você não vai conseguir fazer isso sem ter que instalar um software na maquina, se conseguir da um toque! Bom da uma olhana em processing, pois o export do processing é um Applet, e vc pode usar isso em uma página HTML, mas acredito que acesso a porta COM1, COM2… você não vai ter via internet, mas você pode tentar, se conseguir me da um toque :)
[]‘s
Olá Bruno!Seguinte, eu vou ter que fazer um sistema que envie os dados para um letreiro.Para isso, tem o programa VBPainéis.Ainda não sei se este vai ser acessado na porta serial ou pela USB.Foi me passado o protocolo desse programa e tudo mais, mas a minha dúvida é a seguinte:para eu enviar os dados para esse programa o letreiro tem que estar conectado em alguma porta?
Olá Daniel, imagino que você queira utilizar o PHP para enviar estes dados, bom, vc pode tentar enviar a informação via porta serial sem utilizar o VBPainéis.
Caso este software tenha alguma forma de receber informações de diferentes formas, como um xml salvo em um determinado diretório ou webservices talvez. Você poderia tentar da forma que ele se entegra com software de terceiros.
Boa sorte
Bruno tenho tentado de todas as formas enviar dados ao arduino pela porta serial (usb) via PHP.
Tentei com o fwrite e com fputs, mas nenhum dá certo. O RX do arduino nem pisca.
Mas se eu vou lá no monitor do arduino e digito qualquer valor, o arduino recebe.
Olha o código PHP que eu estou tentanto:
if ($port = fopen(“COM11″, “w”)) //COM11 é minha porta USB.
{
echo “abriu a porta serial “;
if (fwrite($port, ’2′))
{
echo “enviou 2 “;
}
else
{
echo “não enviou “;
}
}
else
{
echo “a porta seral NÃO abriu! “;
}
fclose($port);
Se puder me dar uma força, agradeço muito.
Já tentei em dois PCs rodando WinXP + Apache + PHP e nada até agora.
Abraço
Olá Marcos, da uma olhada agora, fiz uma pequena alteração, me parece que você esta tendo um problema atipico. Dependendo do seu código a Arduino pode reiniciar quando você se conecta a ela, então se você der uma pausa no seu script, ela volta a funcionar e recebe o dado enviado. Tente usar o comando “sleep” antes de enviar os dados e depois de abrir a porta com a Arduino.
if ($port = fopen(”COM11″, “w”)) //COM11 é minha porta USB.
{
echo “abriu a porta serial “;
sleep(2);
if (fwrite($port, ‘2′))
{
echo “enviou 2 “;
}
else
{
echo “não enviou “;
}
}
else
{
echo “a porta serial NÃO abriu! “;
}
fclose($port);
Bruno, achei o problema!!!!
Na verdade o problema não estava em nenhuma das duas programações e sim no Windows.
Veja que eu tava usando COM11 (USB serial), no exemplo que eu passei.
Descobri que o Windows atribui sempre valores acima de 10 para a COM, quando esta for uma USB. Não sei porque cargas d’água essa comunicação serial não aceita dois caracteres numéricos na “COM”, então ela funciona somente da COM1 até a COM9.
Vi no site da Microsoft que portas acima de COM9 tem que declarar diferente nas comunicações seriais: “\\.\COM15″, por exemplo. Mas isso não funcionou tb.
Então a solução foi mudar a porta para uma COM disponível abaixo de 10.
Para fazer isso temos que entrar no Gerenciador de Hardware e mudar a COM usada pela “USB Serial Port”. A minha COM2 estava livre, coloquei nela daí o sistema funcionou de primeira.
Coisas de Windows…. Fazer o que, né?
Bom agora que deu tudo certo, vou ver se organizo essa informação toda e posto no fórum do Arduino, pois deve ter muita gente apanhando disso.
Mesmo assim te agradeço mto.
Marcos
Marcos, Valeu pela dica, fiquei 2 dias quebrando a cabeça por causa disso.
Obrigado. :D
Bruno, sabe se tem um jeito de ler a porta serial um pouco mais rápido. Sem usar o Sleep(2) e Speep(1)?
Pelo que vc falou ela reseta se não usar. É isso mesmo?
Tem como não resetar.
Quanto eu testo pelo Serial Monitor na app do Arduino, consigo fazer praticamente em tempo real. Sei que pelo PHP depende de recarregar a página, mas se ficar um pouco mais rápido já melhora bastante.
Abraço
Ola,. estou com o seguinte problema , meu arduino não esta conseguindo ler o serial, o php nao consegui enviar o sinal para o seria, estou usando um arduino uno na com 2 e win 7
Salve Marcos, da uma olhada no forum da Arduino, tem outras pessoas com o problema la:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213719666/28#28
Não testei mas deve funcionar.
[]‘s
Caro, Amigo
Estou tentando comunicar com PHP a LPT1(porta paralela) acionar bit’s nos pinos de 2-9 isso é possível assim como a com(serial)
Oi Bruno, seria possível que vc postasse uma img do esquemático pra gente visualizar as ligações?
Obrigada.
Oi Lidia, se você quiser ligar um led rgb via php, dê uma olhada neste outro post para saber como ligar o led.
http://blog.bsoares.com.br/processing/controlling-rgb-led-with-arduino-and-processing
Boa sorte
Amauri, da uma olhada no post na parte “Lendo dados” que tem um exemplo bem bacana. Presta bem atenção no delay que você precisa dar para esperar o dado chegar a porta…
Olá,
Poderia dar um exemplo sobre a implementação da fila para conexões de múltiplos usuários. Programo em PHP mas não tenho experiência com este conceito. Grato
Olá, Maximiller, não posso.
Vlw Abraços
Olá Bruno,
Os caracteres que indicam o inicio e fim da mensage colocados por vc na linha 13 do código exemplo são obrigatórios ou foram colocados opcionalmente? Vc faz o tratamento da mensagem no código do Arduino posteriormente?
Grato
Coloquei os dois caracteres para saber quando começa e termina um comando.
hello this is so nice i will translate it to english and post it in arduino forum
thank you
Tive problemas em executar isso no windows.
Procurando, depois de bastante tempo descobri que eram as configurações setadas para a porta que eu estava usando no php.
Resolvi com o seguinte comando.
exec(“mode com3: BAUD=9600 PARITY=n DATA=8 STOP=1 to=on dtr=off rts=off”);
meu windows é o xp.
Este comando configura a porta corretamente, e deve ser colocado antes dela ter sido aberta com fopen.
Valeu a dica Leandro!
meu erro
Warning: fopen(COM1) [function.fopen]: failed to open stream: Permission denied in C:\wamp\www\teste\index.php on line 15
porque??
Bruno!
ta tudo funcionando mas queria pegar o valor que consegui (coloquei um potenciometro no arduino) e transformar esse valor que aparece na pagina numa variavel para jogar numa função if…
Como posso transformar o
fgets ($port);
em uma variavel?
exemplo:
echo fgets ($port);
retorna
510
quero que esse 510 seja a variavel
$numero
Abraço!!!
Cara eu estou querendo fazer em vez de LED, fazer com um controlador de temperatura, queria uma ajuda pois esta dando muito erro ! =S
Funciona do mesmo jeito com o Xampp ou Wamp ????
Sim
Pessoal,
Acesse o site da EMPRETECNET, eles fabricam um KIT com uma placa compatível com arduino duemilanove, uma placa de rele, de potenciômetro, de sensor de luz, de sensor de luminosidade, de buzzer, de botão e demais componentes que podem ser realizados vários experimentos sem a necessidade de solda. Qualidade excelente!!
Prezados… a charada foi resolvida… para portas acima de COM9 e pro reset do arduino.
primeiro use:
exec(“mode com13: BAUD=9600 PARITY=n DATA=8 STOP=1 to=on dtr=off rts=off”); no meu caso foi a COM13
depois use
$port = fopen(‘\\\\.\\COM13′, ‘w+’);
isso mesmo com este tantao de barras ai.. (3 horas lutando pra descobrir este vacilo) rss…
Ai amigos é caixa.. funciona mesmo… é só fazer a escrita esperar 1s e ler o que foi devolvido…
Boa noite..
Preciso de ajuda para ler os dados da porta COM…
Problemas com a função fgets e PIC.
Estou utilizando o PIC 18F4550 no hardware e o cabo USB para conecta-lo ao PC (windows XP).
Meu servidor é o Apache 2.2 e PHP 5. (Sou iniciante em PHP e APACHE).
Seguinte:
Quando envio o comando para ligar um led (letra ‘L’) através do HyperTerminal, o Led acende e obtenho a resposta do PIC na tela do Hyperterminal. (‘L’ – Ligado, ‘D’ – desligado).
O problema é que, quando utilizo pela WEB, a função php responsável por ligar o LED só funciona se eu tiver utilizado o Hyperterminal antes.
Se a função for usada primeiramente, o LED acende, porém, a resposta não é obtida, e a página fica carregando por um bom tempo, segurando a porta COM aberta.
Segue a função php para ligar o LED:
Função corta a execução do código. mesmo usando fget(), fgets()..etc..
}
fclose($fp);
?>
VOLTAR
Alguém teria alguma idéia do que possa ser???
Desconfio que tenha relação com bit menos e mais significativo… o pic envia do LSB e finaliza no MSB. Mas não sei como o PHP trabalha… Li uma vez sobre um problema semelhante, porém, era com JAVA..
Se alguém souber e puder ajudar, agradeço…
Abraços pessoal…
(PARABÉNS PELO POST!!! AJUDOU MUITA GENTE)
Desculpem, o código da função não saiu… deve ter sido interpretado.. (sou iniciante..rsrsr):
-> começa php
$porta=’COM1′;
`mode com1: BAUD=9600 PARITY=n DATA=8 STOP=1 to=on dtr=off rts=off`;
$fp = fopen($porta, ‘r+’);
if(!$fp) {
echo “Não foi possível abrir a porta $porta”;
}
else {
fwrite($fp, ‘L’);
echo “RESPOSTA ” . fread($fp,1); -> Problema está na fread(), fgets();…
}
fclose($fp);
-> termina php
Boa noite.. depois de muito apanhar.. mais muito mesmo… consegui resolver o problema…
utilizei a função dio_open() para abrir a serial… ela trabalha em nível baixo..
ficou assim:
//php começa
$porta=’COM1′;
`mode com1: BAUD=9600 PARITY=n DATA=8 STOP=1 to=on xon=off odsr=off octs=on dtr=on rts=hs idsr=off`;
$fd = dio_open(‘com1′, O_RDWR | O_NOCTTY | O_NONBLOCK);
dio_write($fd,’L');
$RESPOSTA = dio_read($fd,2);
dio_close($fd);
//termina php
No PIC, coloquei para enviar a resposta seguida de “\n”
Valeuss.. abraços…
Valeu por compartilhar Guilherme! :)
Bom dia,
Eu não consegui usar este código para PIC. Parece que a versão do PHP5 3.8.0 não tem mais estas funçoes dio_.
Se vc puder testar nesta versao… Obrigado.
Olá amigo,
Desculpe-me o encomodo, mas como se da permissao em localhost. n
No meu dá o seguinte erro
Warning: fopen(COM3:) [function.fopen]: failed to open stream: Permission denied in C:\xampp\htdocs\arduino\index2.PHP on line 29
Grato pela compreensão.
Vc está usando o Arduino? Verifica se algum outro programa abriu está porta. Utilize outro programa para testar a comunicação, antes de usar o PHP.
Boa tarde Bruno,
Primeiro meus parabéns pelo post, acredito que você tenha ajudado muitas pessoas por esse brasil assim como iluminou bastante a minha visão sobre esse tipo de comunicação.
Porém gostaria de tirar umas dúvidas com você. A minha idéia é de implementar um controle de iluminação via web. De que maneira? A pessoa podendo ligar e/ou desligar 2 leds. Hoje possuo um arduino uno, uma quantidade boa de leds de alta luminosidade, vários resitores de 1 K e o WAMP. Você poderia me sugerir algum material especifico para me ajudar?
Antes de mais nada obrigado pela ajuda e desculpe pelo incômodo.