How to receive data from the serial port?
Question
Saturday, February 13, 2016 11:54 AM
Hello friends:
With Visual Studio Community 2015 I created a Visual C ++ CLR form. I added a RichTextBox and SERIALPORT. I have the version Visual C # and Visual Basic 2015 made this interface. I want to do the same example for Visual C ++ CLR.
You can download the project here to better you see the codes.
Visual C#:
Visual Basic 2015:
Can somebody help me?
At least the part of receiving data from the serial port and display it in the RichTextBox.
Best regards.
http://electronica-pic.blogspot.com
All replies (15)
Sunday, February 14, 2016 6:40 AM ✅Answered
I haven't download your sample, pleases check below code if it helps:
private void Actualizar(System::Object^ sender, System::EventArgs^ e)
Monday, February 15, 2016 7:09 PM ✅Answered
Hello,
you don't need think my Words bad, I think if you need Exchange lots of data in relative high speed with big frames, only set high speed communication isn't right way. With this I was fighting also, when I was preparing my communication years ago. If your system is enough for functionality you need, no problem. That's only my recommendation. With that images I was only use string, depended to that your Led directory, where you leave that PNG files. So if you want use only Run from your Studio and pictures are in that Led directory, in my system working this:
pictureBox1->Load("Led\Led_rojo_encendido.png");
But if you create in Debug your .exe file, want working there, put that png files also to that Debug directory and use previous system:
pictureBox1->Load("Led_rojo_encendido.png");
I recommend to you that 2-nd system. Why? Everytime you can change that Picture of your choice. If you got it precompiled with your requirements (resource), you simply can't. You have only EXE :)
With regards...
Duris_I
Saturday, February 13, 2016 1:05 PM
Hello,
I think you can implement in C++ like your C# project. Create GUI and all components. In this case of .NET library same object SerialPort is using in C++ In case of receiving data from Arduino via Serial port, I've include part of my code, which give you better understanding implement C++ objects. Code of C# and C++ are very similiar, so I think you'll make it right :) This part is only receive state and include conversion to some important codings to TextBox object, can be implemented similiar to reachtext object. Hope it will be helpfull to you.
if (serialPort1->BytesToRead>0)
label3->Text="0";
if (serialPort1->BytesToRead>0 && RX_Bytes==serialPort1->BytesToRead)
{
label3->Text=RX_Bytes.ToString();
textBox2->Text="";
textBox5->Text="";
textBox10->Text="";
pictureBox2->BackColor=Color::LightGray;
RX_Message=gcnew array<unsigned char>(RX_Bytes);
unsigned short i=0;
unsigned char CRC=0;
unsigned short Count=serialPort1->Read(RX_Message,0,RX_Bytes);
for (i=0;i<Count;i++)
{
textBox2->Text=textBox2->Text+(wchar_t)RX_Message[i]; //Char
textBox5->Text=textBox5->Text+String::Format("{0:X2}",RX_Message[i]); //Hex
textBox10->Text=textBox10->Text+RX_Message[i]; //Dec
//Count CRC (2nd to Last-2, we expect CRC on Last-1 position)
if (i>0 && i<(Count-2))
CRC=CRC^RX_Message[i];
}
//Check CRC, show status on LED
if (CRC==RX_Message[i-2])
pictureBox2->BackColor=Color::Green;
else
pictureBox2->BackColor=Color::Red;
RX_Bytes=0;
delete RX_Message; //Explicitlly delete managed array
}
else //On begin, read n. of bytes in recv. buffer
RX_Bytes=serialPort1->BytesToRead;
With regards...
Duris_I
Saturday, February 13, 2016 1:43 PM
At all you should not use C++ CLR anymore with Forms. C++ CLR does not have the IDE Forms support anymore since VS2010 if I remember correctly.
Than you should Keep in mind C++ and C++ CLR are two completely different Things!
If you want to make the same in C++ you can use plain C++ with Windows API, C++ with QT or C++ with MFC. MFC is part of VS2015 Professional and Community Edition. QT must be downloaded separately.
Best regards
Bordon
Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.
Saturday, February 13, 2016 2:16 PM
Hello,
no problem to import clear VS2010 CLR Form prj (created with clear Form) and update to f.ex. VS2012? VS2015? All ToolBox things are there :)
Yes you're right with another solution via API, but I'm not sure if user can solve this because he need help with same .NET platform in other language...
Saturday, February 13, 2016 4:33 PM
good:
For now I want to do the program with Visual C ++ CLR when work ends and all, I will make another project with Visual C ++ MFC.
Here is a document in Spanish how to create CLR projects with Visual Studio 2015 Community from page 12.
http://www.slideshare.net/Metaconta2/formulario-windows-con-visual-c
You can create a Visual C ++ project from scratch with Visual CLI 2015.
Here I leave the project created in Visual C ++ CLR, a template made to program more comfortable and achieve what I want as I did in C #.
View video in C#.
http://electronica-pic.blogspot.com
Saturday, February 13, 2016 4:58 PM
Hello,
ok and what you want from us?
Sunday, February 14, 2016 2:35 AM
Hi there:
C # code I tried to adapt it to C ++.
C#:
public partial class Form1 : Form
{
// Utilizaremos un string como buffer de recepción.
string Recibidos;
public Form1()
{
InitializeComponent();
if (!serialPort1.IsOpen)
{
try
{
serialPort1.Open();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
serialPort1.DataReceived += new SerialDataReceivedEventHandler(Recepcion);
}
}
// Al recibir datos.
private void Recepcion(object sender, SerialDataReceivedEventArgs e)
{
// Acumula los caracteres recibidos a nuestro 'buffer' (string).
Recibidos += serialPort1.ReadExisting();
// Invocar o llamar al proceso de tramas.
Invoke(new EventHandler(Actualizar));
}
// Procesar los datos recibidos en el bufer y extraer tramas completas.
private void Actualizar(object sender, EventArgs e)
{
// Asignar el valor de la trama al richTextBox.
richTextBox1.Text += Recibidos;
// Selecciona la posición final para leer los mensajes entrantes.
richTextBox1.SelectionStart = richTextBox1.Text.Length;
// Mantiene el scroll en la entrada de cada mensaje.
richTextBox1.ScrollToCaret();
char[] Delimitador = { ' ', '\r', '\n' };
string[] Palabras = Recibidos.Split(Delimitador);
foreach (string Comandos in Palabras)
{
switch (Comandos)
{
case "1=ON":
pictureBox1.Image = Properties.Resources.Led_rojo_encendido;
Recibidos = "";
break;
case "1=OFF":
pictureBox1.Image = Properties.Resources.Led_rojo_apagado;
Recibidos = "";
break;
case "2=ON":
pictureBox2.Image = Properties.Resources.Led_rojo_encendido;
Recibidos = "";
break;
case "2=OFF":
pictureBox2.Image = Properties.Resources.Led_rojo_apagado;
Recibidos = "";
break;
case "3=ON":
pictureBox3.Image = Properties.Resources.Led_rojo_encendido;
Recibidos = "";
break;
case "3=OFF":
pictureBox3.Image = Properties.Resources.Led_rojo_apagado;
Recibidos = "";
break;
case "4=ON":
pictureBox4.Image = Properties.Resources.Led_rojo_encendido;
Recibidos = "";
break;
case "4=OFF":
pictureBox4.Image = Properties.Resources.Led_rojo_apagado;
Recibidos = "";
break;
}
}
richTextBox1.Text += " " + DateTime.Now.ToString() + "\r";
}
C++:
// Use a string as a receive buffer.
String^ Recibidos;
Form_Principal(void)
{
InitializeComponent();
if (!serialPort1->IsOpen)
{
try
{
serialPort1->Open();
}
catch (Exception^ ex)
{
MessageBox::Show(ex->ToString());
}
serialPort1->DataReceived += gcnew SerialDataReceivedEventHandler(Recepcion);
}
}
// When receiving data.
private void Recepcion(object sender, SerialDataReceivedEventArgs e)
{
// Accumulate characters received our 'buffer' (string).
Recibidos += serialPort1->ReadExisting();
// Invoke or call the process frames.
Invoke(gcnew EventHandler(Actualizar));
}
// Processing the received data in the buffer and extract complete frames.
private void Actualizar(object sender, EventArgs e)
{
// Assign the value of the frame to the RichTextBox.
richTextBox1->Text += Recibidos;
// Select the final position to read incoming messages.
richTextBox1->SelectionStart = richTextBox1->Text->Length;
// Keeps the scroll at the entrance of each message.
richTextBox1->ScrollToCaret();
array<Char^>^ Delimitador = gcnew array<Char^> { L" ", L"\r", L"\n" };
array<String^>^ Palabras = Recibidos->Split(Delimitador);
for each (String^ Comandos in Palabras)
{
switch (Comandos)
{
case "1=ON":
pictureBox1->Image = Properties->Resources->Led_rojo_encendido;
Recibidos = "";
break;
case "1=OFF":
pictureBox1->Image = Properties->Resources->Led_rojo_apagado;
Recibidos = "";
break;
case "2=ON":
pictureBox2->Image = Properties->Resources->Led_rojo_encendido;
Recibidos = "";
break;
case "2=OFF":
pictureBox2->Image = Properties->Resources->Led_rojo_apagado;
Recibidos = "";
break;
case "3=ON":
pictureBox3->Image = Properties->Resources->Led_rojo_encendido;
Recibidos = "";
break;
case "3=OFF":
pictureBox3->Image = Properties->Resources->Led_rojo_apagado;
Recibidos = "";
break;
case "4=ON":
pictureBox4->Image = Properties->Resources->Led_rojo_encendido;
Recibidos = "";
break;
case "4=OFF":
pictureBox4->Image = Properties->Resources->Led_rojo_apagado;
Recibidos = "";
break;
}
}
richTextBox1->Text += " " + DateTime::Now->ToString() + "\r";
}
I have reduced a lot of mistakes so far has 27 errors at this time.
Any suggestions for correcting errors?
;)
http://electronica-pic.blogspot.com
Sunday, February 14, 2016 4:28 PM
Here you got it :) pls only one change, case need integral type, used simple if..else if conditions. Pls consider change path in load image string, now it needs location where all sources are located (that .h .cpp). Check and give pls info.
public ref class Form_Principal : public System::Windows::Forms::Form
{
public:
// Use a string as a receive buffer.
String^ Recibidos;
Form_Principal()
{
InitializeComponent();
if (!serialPort1->IsOpen)
{
try
{
serialPort1->Open();
}
catch (Exception^ ex)
{
MessageBox::Show(ex->ToString());
}
serialPort1->DataReceived += gcnew System::IO::Ports::SerialDataReceivedEventHandler(this,&Entrada_Arduino_CPP_CLR_3::Form_Principal::Recepcion);
}
}
// When receiving data.
private: System::Void Recepcion(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e)
{
// Accumulate characters received our 'buffer' (string).
Recibidos += serialPort1->ReadExisting();
// Invoke or call the process frames.
Invoke(gcnew EventHandler(this,&Entrada_Arduino_CPP_CLR_3::Form_Principal::Actualizar));
}
// Processing the received data in the buffer and extract complete frames.
private: System::Void Actualizar(System::Object^ sender, System::EventArgs^ e)
{
// Assign the value of the frame to the RichTextBox.
richTextBox1->Text += Recibidos;
// Select the final position to read incoming messages.
richTextBox1->SelectionStart = richTextBox1->Text->Length;
// Keeps the scroll at the entrance of each message.
richTextBox1->ScrollToCaret();
//array<Char>^ Delimitador = {(Char)" ", (Char)"\r", (Char)"\n" };
array<wchar_t,1>^ Delimitador = {' ','\r','\n'};
//array<String^>^ Palabras = Recibidos->Split(Delimitador);
array<String^>^ Palabras = Recibidos->Split(Delimitador);
for each (String^ Comandos in Palabras)
{
if (Comandos=="1=ON")
pictureBox1->Load("Led_rojo_encendido.png");
else if (Comandos=="1=OFF")
pictureBox1->Load("Led_rojo_apagado.png");
else if (Comandos=="2=ON")
pictureBox2->Load("Led_rojo_encendido.png");
else if (Comandos=="2=OFF")
pictureBox2->Load("Led_rojo_apagado.png");
else if (Comandos=="3=ON")
pictureBox3->Load("Led_rojo_encendido.png");
else if (Comandos=="3=OFF")
pictureBox3->Load("Led_rojo_apagado.png");
else if (Comandos=="4=ON")
pictureBox4->Load("Led_rojo_encendido.png");
else if (Comandos=="4=OFF")
pictureBox4->Load("Led_rojo_apagado.png"); Recibidos = "";
}
richTextBox1->Text += " " + DateTime::Now.ToString() + "\r";
}
Update: funcionality I was tested with my serial application between 2 serial ports converters (one port was your app second my app simulated Arduino), everytime passing 1 command to your app (1=ON). I got also Arduinos but I don't have time to create oposite frame serving to PC :) Enjoy.
If you discover some my misunderstanding to your idea of functionality, give answer pls.
With regard...
Duris_I
Monday, February 15, 2016 2:50 AM
Hi there:
Run the program, it fails because it can not find the image file.
An unhandled exception of type 'System.IO.FileNotFoundException' in System.Windows.Forms.dll but was not handled in user code
Additional information: Could not find the 'C: \ Users \ Meta \ Documents \ Visual Studio 2015 \ Projects \ Entrada_Arduino_CPP_CLR_3 \ Entrada_Arduino_CPP_CLR_3 \ Led_rojo_apagado.png'** file.
If a driver for this exception,** the program can continue safely.
I like to use the "switch" if posibe. The images I have in resources.
I have simplified parts of the code C ++.
#pragma once
namespace Entrada_Arduino_CPP_CLR_3 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::IO::Ports; // Do not forget.
/// <summary>
/// Resumen de Form_Principal
/// </summary>
public ref class Form_Principal : public Form
{
public:
// Use a string as a receive buffer.
String^ Recibidos;
Form_Principal(void)
{
InitializeComponent();
if (!serialPort1->IsOpen)
{
try
{
serialPort1->Open();
}
catch (Exception^ ex)
{
MessageBox::Show(ex->ToString());
}
serialPort1->DataReceived += gcnew SerialDataReceivedEventHandler(this, &Form_Principal::Recepcion);
}
}
// When receiving data.
private: Void Recepcion(Object^ sender, SerialDataReceivedEventArgs^ e)
{
// Accumulate characters received our 'buffer' (string).
Recibidos += serialPort1->ReadExisting();
// Invoke or call the process frames.
Invoke(gcnew EventHandler(this, &Form_Principal::Actualizar));
}
// Processing the received data in the buffer and extract complete frames.
private: Void Actualizar(Object^ sender, EventArgs^ e)
{
// Assign the value of the frame to the RichTextBox.
richTextBox1->Text += Recibidos;
// Select the final position to read incoming messages.
richTextBox1->SelectionStart = richTextBox1->Text->Length;
// Keeps the scroll at the entrance of each message.
richTextBox1->ScrollToCaret();
//array<Char>^ Delimitador = {(Char)" ", (Char)"\r", (Char)"\n" };
array<wchar_t, 1>^ Delimitador = { ' ','\r','\n' };
array<String^>^ Palabras = Recibidos->Split(Delimitador);
for each (String^ Comandos in Palabras)
{
if (Comandos == "1=ON")
pictureBox1->Load("Led_rojo_encendido.png");
else if (Comandos == "1=OFF")
pictureBox1->Load("Led_rojo_apagado.png");
else if (Comandos == "2=ON")
pictureBox2->Load("Led_rojo_encendido.png");
else if (Comandos == "2=OFF")
pictureBox2->Load("Led_rojo_apagado.png");
else if (Comandos == "3=ON")
pictureBox3->Load("Led_rojo_encendido.png");
else if (Comandos == "3=OFF")
pictureBox3->Load("Led_rojo_apagado.png");
else if (Comandos == "4=ON")
pictureBox4->Load("Led_rojo_encendido.png");
else if (Comandos == "4=OFF")
pictureBox4->Load("Led_rojo_apagado.png");
Recibidos = "";
}
richTextBox1->Text += " " + DateTime::Now.ToString() + "\r";
}
Leave Arduino code for onlookers.
byte estadoBoton1,
estadoBoton2,
estadoBoton3,
estadoBoton4;
byte estadoBotonAnt1,
estadoBotonAnt2,
estadoBotonAnt3,
estadoBotonAnt4;
char buffer[36];
char caracter;
String comando;
void setup()
{
pinMode(13,OUTPUT); // Donde está el Led 13.
pinMode(12,OUTPUT);
pinMode(11,OUTPUT);
pinMode(10,OUTPUT);
pinMode(8,INPUT); // Entrada digital 8.
pinMode(7,INPUT);
pinMode(6,INPUT);
pinMode(5,INPUT);
Serial.begin(115200);
leeEstado();
printEstado();
}
void loop() {
leeEstado();
if ((estadoBoton1 != estadoBotonAnt1) ||
(estadoBoton2 != estadoBotonAnt2) ||
(estadoBoton3 != estadoBotonAnt3) ||
(estadoBoton4 != estadoBotonAnt4))
{
printEstado();
delay(100);
}
while (Serial.available() > 0)
{
caracter= Serial.read();
comando.concat(caracter);
delay(10);
}
if (comando.equals("ACTUALIZAR") == true)
{
printEstado();
}
// Limpiamos la cadena para volver a recibir el siguiente comando.
comando="";
}
// Funciones.
void leeEstado()
{
estadoBoton1 = digitalRead(8);
estadoBoton2 = digitalRead(7);
estadoBoton3 = digitalRead(6);
estadoBoton4 = digitalRead(5);
}
void printEstado(void)
{
digitalWrite(13,estadoBoton1);
digitalWrite(12,estadoBoton2);
digitalWrite(11,estadoBoton3);
digitalWrite(10,estadoBoton4);
sprintf(buffer,"%s %s %s %s",
estadoBoton1?"1=ON":"1=OFF",
estadoBoton2?"2=ON":"2=OFF",
estadoBoton3?"3=ON":"3=OFF",
estadoBoton4?"4=ON":"4=OFF");
Serial.print(buffer);
estadoBotonAnt1 = estadoBoton1;
estadoBotonAnt2 = estadoBoton2;
estadoBotonAnt3 = estadoBoton3;
estadoBotonAnt4 = estadoBoton4;
}
Gradually is coming out Visual C ++ CLR.
Download Poryecto C++ r3.
;)
http://electronica-pic.blogspot.com
Monday, February 15, 2016 6:35 AM | 1 vote
Hello,
pls consider that I don't have VS2015, I must create prj from scratch in my VS2010 Pro. Pls did you read my previous post??? I wrote about needed Pictures location for test functionality. Same for switch, C++ doesn't know implement String in switch only integrals, so if you need switch you can discover by your own. I got my Home simulator connected to Arduinos and my applications to simulate some devices like in real aircraft (collect data from simulator, f.ex. wet compass via stepper motor), so Exchange data between Arduinos and C++ are simple things for me. I think on other side that your implementation of Exchange data between your app and Arduino is not reliable via event in my opinion. I'm using better system as I have described in my first post, never use that register of rising event to something check. I think that you'll make finish in this app by your own.
With regard...
Duris_I
Monday, February 15, 2016 6:28 PM
Hi there:
If your C ++ system is better, I'll shut up.
Still, I need only load the image resource when it comes to touch the switch Arduino.
Greeting.
http://electronica-pic.blogspot.com
Monday, February 15, 2016 8:49 PM
#pragma once
namespace Entrada_Arduino_CPP_CLR_3 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::IO::Ports; // Do not forget.
using namespace System::Text;
/// <summary>
/// Resumen de Form_Principal
/// </summary>
public ref class Form_Principal : public Form
{
public:
// Use a string as a receive buffer.
String^ Recibidos;
Form_Principal(void)
{
InitializeComponent();
if (!serialPort1->IsOpen)
{
try
{
serialPort1->Open();
}
catch (Exception^ ex)
{
MessageBox::Show(ex->ToString());
}
serialPort1->DataReceived += gcnew SerialDataReceivedEventHandler(this, &Form_Principal::Recepcion);
}
}
// When receiving data.
private: Void Recepcion(Object^ sender, SerialDataReceivedEventArgs^ e)
{
// Accumulate characters received our 'buffer' (string).
Recibidos += serialPort1->ReadExisting();
// Invoke or call the process frames.
Invoke(gcnew EventHandler(this, &Form_Principal::Actualizar));
}
// Processing the received data in the buffer and extract complete frames.
private: Void Actualizar(Object^ sender, EventArgs^ e)
{
// Assign the value of the frame to the RichTextBox.
richTextBox1->Text += Recibidos;
// Select the final position to read incoming messages.
richTextBox1->SelectionStart = richTextBox1->Text->Length;
// Keeps the scroll at the entrance of each message.
richTextBox1->ScrollToCaret();
//array<Char>^ Delimitador = {(Char)" ", (Char)"\r", (Char)"\n" };
array<wchar_t, 1>^ Delimitador = { ' ','\r','\n' };
array<String^>^ Palabras = Recibidos->Split(Delimitador);
for each (String^ Comandos in Palabras)
{
if (Comandos == "1=ON")
pictureBox1->Load("Led\\Led_rojo_encendido.png");
else if (Comandos == "1=OFF")
pictureBox1->Load("Led\\Led_rojo_apagado.png");
else if (Comandos == "2=ON")
pictureBox2->Load("Led\\Led_rojo_encendido.png");
else if (Comandos == "2=OFF")
pictureBox2->Load("Led\\Led_rojo_apagado.png");
else if (Comandos == "3=ON")
pictureBox3->Load("Led\\Led_rojo_encendido.png");
else if (Comandos == "3=OFF")
pictureBox3->Load("Led\\Led_rojo_apagado.png");
else if (Comandos == "4=ON")
pictureBox4->Load("Led\\Led_rojo_encendido.png");
else if (Comandos == "4=OFF")
pictureBox4->Load("Led\\Led_rojo_apagado.png");
Recibidos = "";
}
richTextBox1->Text += " " + DateTime::Now.ToString() + "\r";
}
It works the entire code.
Thank you very much to all.
http://electronica-pic.blogspot.com
Sunday, February 21, 2016 3:10 AM | 2 votes
Thanks to you I've completed the tutorial on controlling the series with Visual C ++ CLR Arduino port.
It's in Spanish, but in the future will be in English.
Greetings.
http://electronica-pic.blogspot.com
Sunday, February 21, 2016 8:16 AM
Nice...