-1
The application (C# .Net Framework 4.7.2 in Visual Studio 2019) I’m doing sends a command to Arduino via serial and Arduino sends 'n' sensor data. However, the first time I run the program, nothing happens. If I restart the execution, it starts receiving the data as expected, but stops sending before arriving at the word "End" that I used to indicate the end of the sending and freezes there, without error messages. Why does this happen? What I did wrong?
I was able to simulate the problem with the codes below: Visual C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
namespace TesteSerial1
{
public partial class Form1 : Form
{
List<string> dados = new List<string>(); //Listas de manipulacao de dados
string strRec;
public Form1()
{
InitializeComponent();
string[] baudRates = { "4800", "9600", "19200", "38400", "57600", "115200", "230400" };
string[] portas = SerialPort.GetPortNames();
while (portas.Length == 0)
{
MessageBox.Show("Ligue o aparelho a uma porta USB", "Aparelho não encontrado", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
portas = SerialPort.GetPortNames();
}
foreach (string porta in portas)
{
cmbPorta.Items.Add(porta);
}
foreach (string baudRate in baudRates)
{
cmbVelocidade.Items.Add(baudRate);
}
cmbPorta.SelectedIndex = 0;
serialPort1.PortName = portas[0];
cmbVelocidade.SelectedItem = "9600";
serialPort1.BaudRate = int.Parse((string)cmbVelocidade.SelectedItem);
}
private void btnLer_Click(object sender, EventArgs e)
{
dados.Clear();
Form1.ActiveForm.Enabled = false;
if (!serialPort1.IsOpen)
{
serialPort1.Open();
serialPort1.WriteLine("a"); //Envia o comando pro Arduino
serialPort1.DataReceived += DadoRecebido; //Recebe os dados
}
}
private void DadoRecebido(object sender, SerialDataReceivedEventArgs e)
{
try
{
strRec = serialPort1.ReadLine();
object[] parametro = new object[1];
parametro[0] = strRec;
DelegacaoSerial delegado = new DelegacaoSerial(MostraDados);
this.BeginInvoke(delegado, parametro);
}
catch (TimeoutException b)
{
MessageBox.Show("Erro no recebimento dos dados: " + b.Message, "ERRO!", MessageBoxButtons.OK, MessageBoxIcon.Error);
btnLer.Text = "Ler";
btnLer.Enabled = true;
}
}
public delegate void DelegacaoSerial(string strRec);
private void MostraDados(string strRecebida)
{
if (strRecebida != "Fim\r") //Enquanto não recebe o comando 'Final' vai adicionando dados
{
dados.Add(strRecebida); //Adiciona a esta lista para depois tratar os dados
}
else
{
MessageBox.Show("Leitura terminada.", "Fim da leitura", MessageBoxButtons.OK, MessageBoxIcon.Information);
Form1.ActiveForm.Enabled = true;
}
foreach (string d in dados) //Trata os dados
{
try
{
string[] dadosSeparados = d.Split('#');
int dadoA = int.Parse(dadosSeparados[0]);
int dadoB = int.Parse(dadosSeparados[1]);
Console.WriteLine(dadoA + " " + dadoB);
}
catch (InvalidCastException e)
{
MessageBox.Show(e.Message, "Erro de leitura", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
catch (InvalidDataException f)
{
MessageBox.Show(f.Message, "Erro de leitura", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
}
}
}
}
Arduino code:
char rc;
long numA;
long numB;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available() > 0) {
rc = Serial.read();
if (rc == 'a') {
for (int i = 0; i < 5000; i++) {
numA = random(10);
numB = random(30);
Serial.print(numA);
Serial.print("#");
Serial.println(numB);
}
Serial.println("Fim");
}
}
}
The way out is like this:
It seems almost a serial buffer problem, but I’m not sure, it doesn’t seem to be a problem in Rduino, but in the desktop application, try to put a small delay between the prints of Rduino.
– Christian Beregula
I thought it could be something like this, but since I’m new in the area, I couldn’t imagine how I could solve it. I’ll test it! Thank you! On the other hand, speed is paramount in this project. The faster the data acquisition, the better the result, because it is a chemical reaction. Maybe if I add the collected data to a list and then send it...
– Renato Ianhez
The placement of the delay’s helped a little, but as you yourself suggested, the problem is in the C#application. It seems to me that it removes data from the input buffer at a lower speed than the Arduino puts them there, and there comes a time that there is an accumulation that locks the
ReadLine()
. I imagine using theReadExisting()
I would pull the data faster, but I don’t know how to manipulate it and there’s the possibility that they’ll be truncated.– Renato Ianhez
Another possibility is to resize the buffer using the
ReadBufferSize
. I’ll try that.– Renato Ianhez