94 Comentários

Comunicação Serial com C# e Arduino – Parte 1

serial
Este post faz parte da série Comunicação Serial com C# e Arduino. Leia também os outros posts da série:

Uma interface entre o arduino e um computador muitas vezes é importante durante o desenvolvimento de projeto ou para controle de dispositivos através de uma interface gráfica. Pode-se usar uma aplicação no computador para Aquisição e exibição de dados em forma de gráfico durante algum experimento em laboratório ou estudo. Como já foi visto aqui no artigo sobre o Arduino Uno e sobre comunicação Serial com Arduino, a comunicação entre a placa e o computador é feira através de uma porta serial emulada através do driver da USB. Já foi exibido aqui uma aplicação de comunicação serial desenvolvida com a plataforma JAVA. Neste artigo vamos ensinar como desenvolver uma aplicação para Windows usando a plataforma .Net usando o ambiente Visual Studio da Microsoft, com a linguagem C#. Será desenvolvido um terminal simples, onde se poderá enviar e receber caracteres através de uma interface gráfica. Esse artigo também servirá de base para desenvolvermos uma aplicação envolvendo botões e outros elementos visuais.

Você pode baixar a versão express dessa ferramenta diretamente no site da plataforma. Selecione a opção Express 2013 for Windows Desktop. Após o download faça a instalação, que é um processo bem simples porém um pouco demorado, basta seguir os passos de instalação.

Ao Iniciar o Visual Studio será exibida sua tela inicial e para iniciar um novo projeto deve-se acessar o menu FILE > New Project. Como vamos trabalhar com a linguagem C#, deve-se selecionar a opção Visual C# no menu lateral. Agora vamos iniciar o passo a passo pra criar nossa aplicação:

comunicação-serial-c-newproject
Figura 2 - Iniciando um novo projeto

Primeiro passo é iniciar um novo projeto Windows Forms Application em C#:

comunicação-serial-c-config-novo-projeto
Figura 2 - Configurando um novo projeto

Agora vamos inserir os componentes no Form. O primeiro a ser inserido será um botão e deve-se mudar a sua propriedade Name para “btConectar” e a sua propriedade Text para “Conectar”, conforme exibido a seguir:

Serial botão conectar
Figura 3 - Inserindo um botão para conexão

Inserir um comboBox logo a frente do botão btConectar, inserido anteriormente:

comunicação-serial-c-combobox
Figura 4 - Inserindo uma comboBox

Inserir outro botão, logo abaixo do btConectar, e mudar a sua propriedade Text para “Enviar” e Name para btEnviar:

comunicação-serial-c-btEnviar
Figura 5 - Inserindo um botão para envio de dados

Agora vamos inserir um textBox, que receberá os dados a serem enviados. Após ser inserido, mudar a sua propriedade Name para “textBoxEnviar”:

comunicação-serial-c-textBoxEnviar-660x337
Figura 6 - Inserindo um textbox para inserir dados para envio

Agora vamos inserir um textBox maior, que exibirá os dados recebidos. Mudar as propriedades Name para “textBoxReceber”, Multiline para “True” e ScrollBar para “Vertical”. A aparência do Form ficará da seguinte forma:

comunicação-serial-c-textBobReceber
Figura 7 - Textbox para recpção de dados

Próximo passo é inserir um componente timer que será responsável pela atualização das portas COM disponíveis no PC. Selecione o componente timer e clique dentro do Form. Será exibido logo abaixo o componente timer1. Troque a propriedade Name para “timerCOM” e Interval para 1000, conforme exibido a seguir:

comunicação-serial-c-timerCOM
Figura 8 - timer para atualização de COMs disponíveis

Por último vamos inserir o componente de comunicação serial, o SerialPort. Selecione o componente SerialPort e depois clique dentro do Form. Será exibido este componente ao lado do timerCOM:

comunicação-serial-c-serialPort
Figura 9 - Inserindo o componente SerialPort responsável pela comunicação serial

Com os componentes inseridos no Form, vamos para a codificação.

Antes de conectar a porta Serial, é necessário verificar as portas COMs disponíveis para uso, e qual a porta o usuário deseja conectar. Para isso vamos atualizar a cada segundo a ComboBox com as portas disponíveis. Vamos criar um método privado dentro da classe Form1, que será chamado de atualizaListaCOMs. Clique com o botão direito no Form e selecione a opção View code. Insira o método atualizaListaCOMs(), conforme exibido no código a seguir:

Para testar a aplicação é necessário clicar no botão Start ou pressionar a tecla F5. Se tiver alguma porta disponível para comunicação, esta será listada dentro da comBox, conforme exibido a seguir:

omunicação-serial-c-testeAtualizaCOM
Figura 10 - Teste de atualização das portas COMs disponíveis

Na imagem acima nota-se que apenas a COM5 estava disponível. Caso uma placa Arduino seja inserida, é necessário que atualize automaticamente a lista. Para isso vamos usar o timerCOM que está configurado para gerar um evento a cada segundo. Inicialmente deve-se habilitar o timer logo após a inicialização do Form e colocar o método de atualização dentro do evento timerCOM_tick, conforme exibido a seguir:

Obs.: Para gerar o evento timerCOM_tick basta dar duplo clique no componente timerCOM na aba design.

Insira outro Arduino ou crie uma porta COM virtual para verificar que é atualizado automaticamente o comboBox:

teste de atualização de porta COM do Arduino e portas virtuais
Figura 11 - teste de atualização de porta COM do Arduino e portas virtuais

No exemplo acima foi criada uma COM virtual com o auxílio do programa VSPE, que pode ser baixado aqui.

Agora já se pode escolher em qual porta a aplicação vai conectar. O evento click do btConectar será usado para  fazer a conexão. Para criar esse evento, selecione a aba de design do Form e dê um duplo clique no botão conectar. Será gerado o evento e agora deve-se  inserir o código para conexão. O botão conectar também servirá para desconectar quando a porta já estiver conectada, confira o código a seguir:

-comunicação-serial-c-testConectar
Figura 12 - Teste de conexão

É necessário colocar uma proteção para que o programa não seja fechado e deixe a porta COM aberta, dessa forma impedindo que outros programas possam usá-la. Para isso vamos fechar a porta dentro do evento Form1_FormClosed:

O processo para conexão e fechamento da porta serial já está feito, e o próximo passo é fazer o programa enviar para o Arduino o que for digitado dentro do textBoxEnviar. Para isso, dentro do evento btEnviar_Click, deve-se inserir o seguinte código:

A recepção de dados requer um pouco mais de atenção. Inicialmente deve-se criar um evento serialPort1_DataReceived e uma variável global do tipo String. O processo de recepção acontece em uma Thread diferente da atualização dos componentes. A atualização do textBoxRebecer deve ser feita fora do evento de recepção da serial. Para isso criamos uma função trataDadoRecebido. Confira como ficará o código completo da aplicação:

Para testar a aplicação junto ao Arduino, vamos fazer o upload do seguinte sketch:

Nesse programa o Arduino simplesmente retornará o dado que ele receber. Dessa forma, quando enviarmos dados pelo programa, estes serão exibidos no computador por meio do textBoxRecebe. A figura abaixo exibe os dados enviados e recebidos pela aplicação:

comunicação-serial-c-testeComunicação
Figura 13 - Teste de envio recebimento de dados do Arduino

Agora que a aplicação está completa, ou seja, já conseguimos enviar e receber dados, vamos a um exemplo funcional. Conforme foi exibido no Artigo sobre comunicação serial no Arduino, vamos aproveitar o exemplo que acenderá o led através do comando vindo pela serial. Carregue o seguinte exemplo no Arduino:

Execute a aplicação, conectando a porta na qual o Arduino está ligado e envie o caractere ‘A’. Verifique o resultado no LED conectado ao pino 13 da placa Arduino:

comunicação-serial-c-testeArduino
Figura 14 - Envio de comando apra o Arduino

O download da aplicação completa pode ser feito através do link: [wpfilebase tag=fileurl path='posts/interfaceArduinoVS2013.zip' linktext='Aplicação C# para interface serial com Arduino' /].

Lembre-se, você deve ser registrado e estar logado no site para fazer o download.

Conclusão sobre a Comunicação Serial C# e Arduino

A ferramenta Visual Studio da Microsoft permite criar facilmente uma interface de comunicação Serial entre o Arduino e um computador (com sistema operacional Windows). A partir do exemplo apresentado, pode-se fazer aplicações para enviar e receber comandos para o Arduino ou outro dispositivo conectado a uma porta serial. No próximo artigo vamos fazer uma aplicação envolvendo botões e outros componentes que deixarão nossa interface mais elegante.

Para aprender mais

Arduino - Primeiros Passos

Arduino UNO

Arduino - Entradas Analógicas

Referências

SerialPort Class

Classe SerialPort

Outros artigos da série

Comunicação Serial com C# e Arduino - Parte 2 >>
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Arduino » Comunicação Serial com C# e Arduino - Parte 1
Comentários:
Notificações
Notificar
guest
94 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Bruno Oliveira
30/05/2018 15:09

Muito Bom,

Obrigado pelas dicas, tive que fazer algumas alterações mas tudo 100% agora.

Lara
Lara
03/12/2017 12:18

Olá, a função private void AtualizaListaCOMs() não está sendo chamada no meu código. Coloquei uma MessageBox para teste e ela não aparece. Como posso fazer para o código chamar as funções?

Fabu Dias
Fabu Dias
09/03/2016 15:03

Olá, só tenho Mac... e não rola instalar Visual Studio. Tem alguma outra IDE com ambiente parecido, mas no Mac?

Roberto Ferreira Filho
Roberto Ferreira Filho
27/01/2016 18:05

Ola Fabio, estou com uma dificuldade aqui, meu arduino manda uma série variável de prints. A ideia é receber essa informação no programa e baseado no primeiro código dar split e tratar em um switch. Porem as vezes o programa recebe os dados pela metade, no exemplo
Serial.print("130");
Serial.print(",");
Serial.print(hour);
Serial.print(",");
Serial.print(minute);
Serial.print(",11111");

As vezes ele recebe a string toda, eventualmente ele quebra a string em duas. Como eu posso fazer pra isso nao ocorrer?? De preferencia sem alterar o programa do arduino.

Roberto Ferreira Filho
Roberto Ferreira Filho
Reply to  Roberto Ferreira Filho
27/01/2016 20:55

Atualizando minha propria duvida, eu acabei mudando no arduino para println no ultimo print e mudei no programa para o comando readline 😉 resolvido

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Roberto Ferreira Filho
28/01/2016 08:58

Olá Roberto, desculpe pela demora na resposta. Mas é isso mesmo, colocando o readline você consegue ler a string inteira de uam vez. Abraços

Roberto Ferreira Filho
Roberto Ferreira Filho
Reply to  Fabio_Souza_Embarcados
28/01/2016 13:23

Fábio eu só tenho a agradecer a rápida resposta. se puder me ajudar de novo, quando resolvi o problema mudando pra println arrumei outra dor de cabeça. eu fiz um programa no app inventor 2 pra se comunicar com o mesmo dispositivo. ocorre que ele não tem uma opção pra ler linhas inteiras por bluetooth. pode me ajudar nisso? ??

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Roberto Ferreira Filho
28/01/2016 18:10

Eu não conheço os detalhes do app inventor. Teria que ver como ele recebe os dados e se é possível descartar esses caracteres. Veja como chegam os dados no android. Outra opção seria identificar de alguma forma de está comunicando com o pc ou com o android, aí a formatar a string para cada caso. abraços

Guilherme Zucco
Guilherme Gomes Zucco
04/11/2015 20:58

Oi,

Tem alguma noção de porque quando coloco pra rodar em .Net 2.0 o programa roda mas não lê

desconfiava do lixo que aparece junto do "COM1", até coloquei pra pegar o nome de uma textbox, mas tem alguma coisa com as Threads q n to descobrindo

Obrigado

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Guilherme Gomes Zucco
04/11/2015 22:45

Guilherme, tem que testar o funcionamento do componentes nessa versão. Pode ser feita uma aplicação simples e testar o envio e recebimento. Vou testar e ver ser percebo alguma diferença.
Abraços

Diogo Moraes
Diogo Moraes
28/10/2015 03:25

Olá Fabio!!

Segui os passos porém estou usando o visual c# 2010 e o mesmo não reconhece serialPort1 alguma dica do que pode ser?

Abraços

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Diogo Moraes
28/10/2015 12:59

Olá Diogo, verifique se o componente foi criado corretamente e se foi incluida a linha using System.IO.Ports;

Abraços

Diogo Moraes
Diogo Moraes
Reply to  Diogo Moraes
29/10/2015 01:12

Opa, resolveu!
kkkk
obrigado e parabéns pelo Post
abraços

Edson Xavier
Edson
01/10/2015 20:31

Ola fábio.

Parabéns pelas suas postagem são realmente importantes para nosso desenvolvimento profissional.

Tenho uma pequena dúvida sobre esse post quando for necessário envia dois dados, ou seja, quando houver dois sensores.

Tentei colocar uma letra na frente da string e enviar para o visual studio mas n obtive sucesso.

Poderia me mostrar como fazer isso descrevendo um trecho de código de como ficaria no arduino e no c#?

Desde já agradeço.

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Edson
01/10/2015 22:30

Olá Edison,

Você pode formatar uma string com os valores dos sensores, por exemplo:

123#456

quando receber essa string no c#, você usa o metodo split para separar. O vetor 0 representará o primeiro sensor e o 1 o segundo.

Veja se consegue, caso contrário envie os techos de código para analisarmos.

Abraços

Edson Xavier
Edson
Reply to  Fabio_Souza_Embarcados
01/10/2015 23:46

Ok Fabio fiz dessa forma no C# private void TrataDadosPortaSerial(object sender, EventArgs e) { string[] VetorRecebe; VetorRecebe = RecebeDados.Split(':'); Double Temperatura = Convert.ToDouble(VetorRecebe[0]) * 5 / 1023; textBox5.Text = Convert.ToString(Math.Round(Temperatura, 1)) + "°C"; // textBox6.Text = Convert.ToString(VetorRecebe.Length); Double Temp = Convert.ToDouble(VetorRecebe[1]) * 5 / 1023; textBox6.Text = Convert.ToString(Math.Round(Temp, 1)) + "°C"; } Tem uma linha que ta como comentário que eu usei pra testar qual tamanho da string VetorRecebe e o programa me mostrou 1. Quando executei deu erro ao acessar VetorRecebe[1]. Aquele erro típico quando tenta acessar um ponto no vetor que n existe. Como ficaria o codigo no… Leia mais »

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Edson
02/10/2015 00:28

O problema está no arduino. o Código de leitura está errado. e você só está enviando um valor para o computado. Essa instrução não está certa: valor_leituras += ':';

crie duas variáveis, uma para cada sensor:

int valor_sensor1;

int valor_sensor2;

não se preocupe com média por enquanto.

leia os sensores:

valor_sensor1 = analogRead(A0);

valor_sensor2 = analogRead(A1);

Quando for enviar para o PC, faça da seguinte forma:

Serial.print(valor_sensor1);
Serial.print(":");
Serial.println(valor_sensor2);

Dessa forma vc envia a string: 1023:1023 mais o caractere de nova linha

Ai não dará erro no split.

proximo passo é fazer a rotina de média,

abraços

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Fabio_Souza_Embarcados
02/10/2015 00:32

da uma olhada nos comentários da segunda parte: http://embarcados.com.br/comunicacao-serial-c-arduino-parte-2/

depois me fala o resultado. Abraços

Edson Xavier
Edson
Reply to  Fabio_Souza_Embarcados
02/10/2015 20:51

Sem palavras Fábio, funcionou perfeitamente.
o problema era que no meu código no arduino eu n sabia que devia finalizar o envio com a instrução serial.println().

Agora vamos para as médias. Porque deve fazer as médias quando se trata de arduino? nos microcontroladores não necessita.
Não compreendi o que significa aquela instrução valor_leituras>>4;

Abraço

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Edson
03/10/2015 14:11

A média é para eliminar ruidos presentes no sinal analógico do sensor. Esse tipo de média aritmética funciona como um filtro passa baixa, bem simples. No caso, são feitas 16 amostras, após a leitura das 16 amostras que são somadas em uma variável, o valor é dividido por 16. A instrução valor_leituras>>4, faz a divisão do valor por 16.

Sugiro a leitura do artigo: http://embarcados.com.br/bits-em-linguagem-c/

Nesse artigo são abordados os operadores de deslocamento.

Abraços

Guilherme Zucco
Guilherme Gomes Zucco
29/09/2015 00:45

Olá,

Primeiramente parabéns pelo artigo,

Estou com uma certa dificuldade em separar os dados enviados pelo Arduino para o terminal na parte

private void trataDadoRecebido(object sender, EventArgs e)

{

textBoxReceber.AppendText(RxString);

}

Gostaria de quebrar para varias textbox, como exemplo:

private void trataDadoRecebido(object sender, EventArgs e)

{

if (RxString == "A") // Ou (RxString.Contains("A")) Já usei uns métodos com String.Split

{

textBoxA.AppendText(RxString);

}

if (RxString == "B")

{

textBoxB.AppendText(RxString);

}

}

Só que não estou conseguindo fazer essa filtragem, ou o código tem jogado tudo, ou nada ou as vezes faz outras não....

teria alguma dica sobre isso?

Obrigado

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Guilherme Gomes Zucco
01/10/2015 22:25

Olá Guilherme,

é enviado um caracter por vez?

verifique o tamanho do string recebida e se está lendo corretamente. Você pode colocar breakpoint e testar enviando pelo terminal serial do arduino.

Veja se consegue algum resultado e me retorna aqui.

Abraços

Guilherme Zucco
Guilherme Gomes Zucco
Reply to  Fabio_Souza_Embarcados
02/10/2015 23:11

Pelo Arduino estou enviando com Serial.print("A"); // ja tentei com Serial.println("A"); Serial.println("var1"); //variavel float Pelo Terminal do C# Mantive essa estrutura para teste, no qual funciona perfeitamente private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { RxString = serialPort1.ReadExisting(); //le o dado disponível na serial this.Invoke(new EventHandler(trataDadoRecebido)); //chama outra thread para escrever o dado no text box } private void trataDadoRecebido(object sender, EventArgs e) { textBoxReceber.AppendText(RxString); } No private void trataDadoRecebido fiz essa modificação private void trataDadoRecebido(object sender, EventArgs e) { textBoxReceber.AppendText(RxString); if (RxString == "A") { textBoxR2.AppendText(RxString); } ou essa variação if (RxString.Contains("A")) { textBoxR2.AppendText(RxString); } } Não to entendendo porque… Leia mais »

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Guilherme Gomes Zucco
03/10/2015 14:17

Manda o valor com println e usa no c# o readline. dessa forma vc garante que será lido o valor.

Abraços

Guilherme Zucco
Guilherme Gomes Zucco
Reply to  Fabio_Souza_Embarcados
05/10/2015 22:53

Aham, funcionou

Muito Obrigado, que o Deus do café lhe abençoe =D

Kleber Maia
Kleber Maia
09/08/2015 14:00

Fabio Souza, Boa Tarde.
Seguindo seu ensino, fiz todos os passos da aplicação, o arduíno recebe os dados porém não me retorna os dados para o textBoxReceber. Pode me ajudar?

Fabio_Souza_Embarcados
Fabio_Souza_Embarcados
Reply to  Kleber Maia
09/08/2015 14:12

Olá Kleber, Primeiro certifique que o arduino está enviando os dados. Depois você pode inserir breakpoint e verificar se a aplicação está recebendo o dado e por ultimo verificar se a aplicação está atualizando o dado corretamente. Utilize breakpoints nos eventos de recepção e atualização do dado. Abraços

Cleiton Cavalcanti
Cleiton Cavalcanti
Reply to  Kleber Maia
12/09/2015 23:02

Kleber boa norte! Consegui achar uma solução, basta inserir "serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);" antes de "serialPort1.Open();" no evento btConectar_Click.

Luciano Lopes
Luciano Lopes
26/06/2015 15:41

Eu fiz e funcionou certinho, exatamente como esta no site,no começo estava errando, pois copiava e colava direto todo o texo do artigo no visual c, e não é assim que funciona, em cada botão vc tem que clicar 2 vezes para ele gerar o codigo inicial e copiar e colar apenas o que vai no meio das chaves, inclusive a parte do serial port.

Talvez você goste:

Séries



Outros da Série

Menu

WEBINAR
 
NVIDIA JETSON – A Inteligência Artificial na palma de sua mão

Data: 08/07 às 14:00h Apoio: Arrow | NVIDIA
 
INSCREVA-SE AGORA »



 
close-link

WEBINAR
 
Redes Mesh para Monitoramento
e Controle de Sensores

Data: 15/07 às 14:00h Apoio: Artimar| Microchip| Tecsus
 
INSCREVA-SE AGORA »



 
close-link