ÍNDICE DE CONTEÚDO
- Comunicação Serial com C# e Arduino – Parte 1
- Comunicação Serial com C# e Arduino – Parte 2
Na primeira parte dessa série, Comunicação serial com C# e Arduino, foi exibido como criar um terminal simples usando o Visual Studio com a linguagem C#. Foi explicado passo a passo como inserir os componentes e a programação da aplicação para funcionar parecida com o terminal serial que vem no programa Arduino.
Neste artigo vamos construir uma aplicação de comunicação serial para ligar/desligar um LED no Arduino através de um botão e exibir o valor da tensão presente no pino analógico (A0). Para facilitar o desenvolvimento vamos aproveitar a estrutura desenvolvida na parte 1 desta série.
O primeiro passo é retirar o textBoxEnviar e o textBoxReceber, deixando a interface da seguinte forma:
Agora vamos aproveitar o btEnviar para servir como o botão que ligará e desligará o LED na placa Arduino. Vamos trocar a propriedade Name para btLigar e Text para Ligar, e deverá ficar conforme figura abaixo:
Para exibir a tensão na entrada analógica do Arduino vamos inserir um label logo abaixo do botão Ligar. Trocar a propriedade Name para lbValor e em Text inserir Tensão: 0,0 V. Para ficar mais visível pode-se trocar a fonte e aumentar o seu tamanho. No nosso exemplo foi escolhida a fonte Arial com tamanho 16, conforme exibido na figura abaixo:
Para ficar melhor a disposição das informações no Form, vamos alinhar os componentes ao centro, conforme figura abaixo:
Note que foi adicionado um label, logo acima do btLigar, com a propriedade Text igual a LED, que servirá para indicar que o botão acionará o LED.
Esse layout servirá para nossa aplicação, para ser lida a tensão no pino analógico do Arduino. Vamos inserir um componente Timer que será responsável para enviar o dado de leitura do valor analógico em tempo em tempos. Deve ser alterada a propriedade Name para timerLeitura e Interval para 500, conforme exibido a seguir:
Programação para aplicação de comunicação serial
Com os componentes inseridos podemos passar para a codificação da nossa aplicação. Deve ser criado o evento do botão Ligar, e para isso basta dar um duplo clique no botão. Insira o seguinte código neste evento:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private void btLigar_Click(object sender, EventArgs e) { if(serialPort1.IsOpen == true) { serialPort1.Write("A"); if(btLigar.Text== "Ligar") { btLigar.Text = "Desligar"; } else { btLigar.Text = "Ligar"; } } } |
Para enviar o comando de leitura para o arduino é necessário criar o evento tick do timerLeitura, e para isso basta dar duplo clique no timer na aba Design. No evento deve ser inserido o seguinte código:
1 2 3 4 5 |
private void timerLeitura_Tick(object sender, EventArgs e) { if(serialPort1.IsOpen == true) serialPort1.Write("T"); } |
Sempre que enviado o caractere ‘T’ o Arduino retornará o valor lido no pino analógico A0 convertido para digital. O código com a formatação do valor a ser exibido, assim como todo o código da aplicação, é exibido a seguir:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; // necessário para ter acesso as portas namespace interfaceArduinoVS2013 { public partial class Form1 : Form { string RxString; public Form1() { InitializeComponent(); timerCOM.Enabled = true; } private void atualizaListaCOMs() { int i; bool quantDiferente; //flag para sinalizar que a quantidade de portas mudou i = 0; quantDiferente = false; //se a quantidade de portas mudou if (comboBox1.Items.Count == SerialPort.GetPortNames().Length) { foreach (string s in SerialPort.GetPortNames()) { if (comboBox1.Items[i++].Equals(s) == false) { quantDiferente = true; } } } else { quantDiferente = true; } //Se não foi detectado diferença if (quantDiferente == false) { return; //retorna } //limpa comboBox comboBox1.Items.Clear(); //adiciona todas as COM diponíveis na lista foreach (string s in SerialPort.GetPortNames()) { comboBox1.Items.Add(s); } //seleciona a primeira posição da lista comboBox1.SelectedIndex = 0; } private void timerCOM_Tick(object sender, EventArgs e) { atualizaListaCOMs(); } private void btConectar_Click(object sender, EventArgs e) { if (serialPort1.IsOpen == false) { try { serialPort1.PortName = comboBox1.Items[comboBox1.SelectedIndex].ToString(); serialPort1.Open(); } catch { return; } if (serialPort1.IsOpen) { btConectar.Text = "Desconectar"; comboBox1.Enabled = false; } } else { try { serialPort1.Close(); comboBox1.Enabled = true; btConectar.Text = "Conectar"; } catch { return; } } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { if(serialPort1.IsOpen == true) // se porta aberta serialPort1.Close(); //fecha a porta } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { RxString = serialPort1.ReadLine(); //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) { Double tensao = Convert.ToDouble(RxString)*5/1023; lbValor.Text = "Tensão: " + Convert.ToString(Math.Round(tensao, 1)) + " V"; } private void btLigar_Click(object sender, EventArgs e) { if(serialPort1.IsOpen == true) { serialPort1.Write("A"); if(btLigar.Text== "Ligar") { btLigar.Text = "Desligar"; } else { btLigar.Text = "Ligar"; } } } private void timerLeitura_Tick(object sender, EventArgs e) { if(serialPort1.IsOpen == true) serialPort1.Write("T"); } } } |
O código para o upload no Arduino é exibido a seguir:
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 31 32 33 34 35 36 37 |
const int LED = 13; int valor_AD = 0; int valor_leituras = 0; byte i = 0; void setup() { Serial.begin(9600); //configura comunicação serial com 9600 bps pinMode(LED,OUTPUT); //configura pino do led como saída } void loop() { if (Serial.available()) //se byte pronto para leitura { switch(Serial.read()) //verifica qual caracter recebido { case 'A': //caso 'A' digitalWrite(LED,!digitalRead(LED)); //inverte estado do LED break; case 'T': Serial.println(valor_AD); break; } } //MEDIA DE LEITURAS valor_leituras += analogRead(A0); i++; if(i==16) { i = 0; valor_AD = valor_leituras>>4; valor_leituras = 0; } } |
Note no código acima que foi feita uma média de 16 leituras do sinal analógico.
Depois de feito o upload para o Arduino e iniciada a aplicação, com a correta conexão com o Arduino o resultado vai ser bem semelhante ao da imagem a seguir:
Variando o valor da entrada analógica com um potenciômetro, será exibido o valor da tensão presente no pino. Caso o botão Ligar seja pressionado, o LED no pino 13 será ligado e, se pressionado novamente, será desligado.
O Download desta aplicação junto com o programa Arduino pode ser feita através do link:
interfaceArduinoVS2013-parte2.zip
62.46 KBLembre-se, você deve ser registrado e estar logado no site para fazer o download.
Conclusão
Desenvolver uma interface gráfica para comunicação serial e controle com Arduino é bem simples utilizando a plataforma .Net. Você pode criar botões e indicadores e facilmente interagir com Arduino. A partir do exemplo apresentado você poderá desenvolver interfaces para controlar o seu Arduino e exibir valores no seu computador de uma forma fácil e rápida.
Aproveite o exemplo, crie novos botões para ligar/desligar dispositivos em outros pinos e leia as outras entradas analógicas.
Espero que este artigo possa ser a porta de entrada para suas aplicações gráficas interagindo com o Arduino. Conte para nós as suas experiências com essa plataforma.
Oi Fábio,
Obrigado por disponibilizar conhecimentos úteis e efetivos desse mundo de embarcados. Pode nos dizer como colocar esse programa na bandeja do Windows (acho que é o SystemTray), ali ao lado do relógio para monitorar a comunicação que chega pela porta serial?
muito bom amigo, só que
Olá, não é necessário configurar o baudRate?
Sim Vinicius, é necessário que o baudrate seja o mesmo em ambos os lados. Na primeira parte são exibidas as configurações da comunicação: https://embarcados.com.br/comunicacao-serial-c-arduino-parte-1/
Olá, fiz um programa parecido que necessita de envios constantes (alta frequencia) e embora eu tenha aumentado o baundRate o intervalo de amostragem continua em 45ms aproximadamente. Existe uma forma de diminuir este intervalo?
como faço para quando estiver acusando que a porta analógica esta acionada 5 = on e quando não estiver 0 = off teria como fazer com imagens ou até mesmo como escrita ?? ficaria grato por essa ajuda , e outra duvida o serial não funciona direto fazendo comunicação não era pra ficar direto ?? alguém disposto em me ajudar estou fazendo um trabalho e só falta isso !!
Ótima explicação Fábio! Apos a comunicação entre o arduino e C#, gostaria de plotar um gráfico de acordo com as informações vindas do arduino, como se fosse um osciloscópio digital. Como devo prosseguir?
Oi Mariana, tenho um projeto pronto usando o WPF para receber dados vindos do SerialPort e plotar gráfico. Qualquer coisa entre em contato por e-mail.
[email protected]
podes me enviar este projecto
[email protected]
Eu queria uma ajuda a respeito do Sensor , em vez de medir tensão eu queria medir um valor do UTRASONIC tem como me ajudar ??? estou com dificuldades , eu só queria ler o valor do sensor em uma Label !!
// VA EM EVENTOS DO SERIALPORT E CHAME ESSE EVENTO
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
RxString = serialPort1.ReadExisting(); //LE O DADO DISPONÍVEL NA SERIAL PORTA..
this.Invoke(new EventHandler(tratadoRecebido)); //CHAMA OUTRA THREAD PARA ESCREVER O DADO NO LABEL)
}
catch (Exception ERRO)
{
MessageBox.Show(ERRO.Message);
}
}
//METODO TRATA OS DADOS RECEBE ENVIA …
private void tratadoRecebido(object sender, EventArgs e)
{
txtultrassonico.AppendText(RxString);
}
//ESCREVA ESSE CODIGO NO LOAD DO FORM
if (serialPort1.IsOpen == true) // PORTA ESTÁ ABERTA
serialPort1.Write(“distance”);
obrigado me ajudou muito , agora eu precisava de outra ajuda , como faço para quando estiver acusando que a porta analógica esta acionada 5 = on e quando não estiver 0 = off teria como fazer com imagens ou até mesmo como escrita ?? ficaria grato por essa ajuda , e outra duvida o serial não funciona direto fazendo comunicação não era pra ficar direto ??
ao executar o programa ele não lista as portas seriais, já coloquei portas virtuais, conectei o arduino e nada. o que pode ser?
Anderson, pode ser a função de atualização das portas COM. Verifique se está chamando essa função.
olá Fabio e todos os leitores do site. gostaria de saber se alguém pode me indicar um tutorial de como enviar os arquivos .hex para o microcontrolador usando o visual. agradeço desde já!
Victor, esse tutorial pode te ajudar: https://www.instructables.com/id/Use-Visual-Studio-2010-to-Compile-AVR-Hex-Files/
depois conta pra nós de funcionou.
Olá Victor, conseguiu fazer essa aplicação?
Depois conta pra nós!
Abraços
Olá Fábio, muito obrigado pelo tutorial. Eu segui todos os passos do segundo, mas a parte que exibe a tensão não funciona no meu. Eu testei com o download que vc disponibilzou e o arduino funciona direitinho. O que pode estar errado?
Marcio, faça uma depuração e veja se as variáveis estão atualizando durante o funcionamento.