I'm following this tutorial. The goal is to receive periodic data from the arduino via serial port. I've been struggling with this for a while now. The com port connection is fine as i'm unable to connect with another terminal program to the arduino when my c# app is running ( port is already connected). At this point the SerialListen thread should start but this doesn't happen.
namespace TestReceiveArduino
{
public partial class Form1 : Form
{
//object serialport to listen usb
System.IO.Ports.SerialPort Port;
//variable to check if arduino is connect
bool IsClosed = false;
public Form1()
{
InitializeComponent();
//configuration of arduino, you check if com3 is the port correct,
//in arduino ide you can make it
Port = new System.IO.Ports.SerialPort();
Port.PortName = "COM11";
Port.BaudRate = 9600;
Port.ReadTimeout = 500;
try
{
Port.Open();
Console.WriteLine("open port ");
}
catch { }
}
private void Form1_Load(object sender, EventArgs e)
{
//A Thread to listen forever the serial port
Console.WriteLine("start thread ");
Thread Hilo = new Thread(ListenSerial);
Hilo.Start();
}
private void ListenSerial()
{
Console.WriteLine("start listener");
while (!IsClosed)
{
Console.WriteLine("in while");
try
{
//read to data from arduino
string AString = Port.ReadLine();
//write the data in something textbox
txtSomething.Invoke(new MethodInvoker(
delegate
{
txtSomething.Text = AString;
}
));
}
catch { }
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//when the form will be closed this line close the serial port
IsClosed = true;
if (Port.IsOpen)
Port.Close();
}
}
}
My arduino is sending data, i've checked this with terminal software. I'm also using the correct COM port
I have some experience with c# but i'm new to threads. What could be the reason for this?
OK:
See if these changes help:
namespace TestReceiveArduino
{
public partial class Form1 : Form
{
//object serialport to listen usb
System.IO.Ports.SerialPort Port;
//variable to check if arduino is connect
bool IsClosed = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
// Connect to Arduino
Port = new System.IO.Ports.SerialPort();
Port.PortName = "COM11";
Port.BaudRate = 9600;
Port.ReadTimeout = 500;
Port.Open();
Console.WriteLine("Port successfully opened: Name: {0}, Baud: {1}, ReadTimeout: {2}", Port.PortName, Port.BaudRate, Port.ReadTimeout);
//A Thread to listen forever the serial port
Console.WriteLine("start thread ");
Thread Hilo = new Thread(ListenSerial);
Hilo.Start();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
...
I moved "Open Serial Connection" and "Start Listener Thread" to the same place (Form1_Load), and wrapped both in the same try/catch block. You might even want to move the "try/catch" to a higher level (e.g. so you can display any exceptions in your Windows GUI).
I assume you're using Microsoft VisualStudio (e.g. MSVS Express 2019) as your GUI, correct? Definitely familiarize yourself with your IDE's debugger; definitely get in the habit of stepping through the code as you're developing it.
Your next steps:
Verify the code gets to "Open Serial Connection", and verify that it opens correctly (e.g.prints "Port successfully opened...").
Verify the code then gets to "ListenSerial()", and prints "start listener" and "in while" at least once.
'Hope that helps...
Related
I would like some advice on the structure of my windows form application. My application will allow the user to open a SerialPort in order to read data from a USB device.
Currently, the application will open into the main form, the user would then open another form frmPortConfig in order to configure the port, this form would then be closed and the user would return to the main form. As it stands, the user selects the port, clicks open, the port info is then passed to another port config class and is setup.
How would I then pass this data back to the main form?
Is this the correct/most efficient method of achieving this?
port config form:
public partial class frmPortConfig : Form
{
public frmPortConfig()
{
InitializeComponent();
//center the form
this.CenterToScreen();
//get serial ports
getPorts();
}
public void getPorts()
{
//stop user from editing the combo box text
cmbPortList.DropDownStyle = ComboBoxStyle.DropDownList;
//get the available ports
string[] ports = SerialPort.GetPortNames();
//add the array of ports to the combo box within the
cmbPortList.Items.AddRange(ports);
}
private void btnOpenPort_Click(object sender, EventArgs e)
{
//get name of port
string port = cmbPortList.SelectedItem.ToString();
//if the port string is not null
if (port != null)
{
//if port can be opened (evoke open port code in port class)
if (clsPortConfig.openPort(port))
{
//inform user that port has been opened
lblPortStatus.Text = port + " opened successfully";
}
else
{
//inform user that port could not be opened
lblPortStatus.Text = port + " could not be opened";
}
}
}
private void btnClose_Click(object sender, EventArgs e)
{
//close the form
this.Close();
}
port config class:
class clsPortConfig
{
public static bool openPort(string port)
{
try
{
//create new serial port
SerialPort serialPort = new SerialPort();
//serial port settings
serialPort.PortName = port;
serialPort.BaudRate = 9600;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.Handshake = Handshake.None;
//attempt to open serial port
serialPort.Open();
serialPort.ReadTimeout = 200;
//add data received handle to serial port
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
//if serial port is now open
if (serialPort.IsOpen)
{
return true;
}
else
{
//inform user that the port could not be opened
return false;
}
}
catch
{
return false;
}
}
public static void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//set sender up as serial port
SerialPort serialPort = (SerialPort)sender;
//get data from serial port
string data = serialPort.ReadExisting();
}
}
How should I send the received data back to my main form?
Thanks
how would I then pass this data back to the main form?
Since you catch the data asynchronously from the device via an event. You don't know when it will arrive. So you would need an event which you can fire from the clsPortConfig.
class clsPortConfig
{
public delegate void EventHandler(string s);
public static event EventHandler TransmitEvent;
// all the other stuff
public static void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//set sender up as serial port
SerialPort serialPort = (SerialPort)sender;
//get data from serial port
string data = serialPort.ReadExisting();
if (TransmitEvent != null)
{
TransmitEvent(data);
}
}
}
and register it in the form:
public frmPortConfig()
{
InitializeComponent();
//center the form
this.CenterToScreen();
//get serial ports
getPorts();
clsPortConfig.TransmitEvent += MyTransmitEvent;
}
private void MyTransmitEvent(string s)
{
// in s you will find the data
}
Is this the correct/most efficient method of achieving this?
I would doubt that. There are a lot of ways to do that. You chose a rather convoluted one. The easiest would probably be to have everything in the Form class. Have the SerialPort there, register the DataReceived event also and use the BeginInvoke method to access display controls like TextBox if you want to show the received data. Because it will arrive on a different thread then the control is created in.
I am working with arduino serial monitor. My goal is to connect through serial port, send some data and close the application after it's done.
This is a C# application. Everything works well besides the fact that the application does not close. To solve the issue, I added Application.Exit() call at the end of Form1_Load method. After this change, the application starts and closes without reading the uppercase letter that I'm sending.
Source code:
namespace ForTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
foreach (string port in ports)
{
SerialPort sp = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
try
{
sp.Open();
try
{
sp.WriteLine("Z"); // Send 1 to Arduino
sp.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
catch (Exception ek)
{
System.Diagnostics.Debug.WriteLine(ek.Message);
}
}
Application.Exit();
}
private void label2_Click(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
if I understood properly, you want to send data FROM C# to ARDUINO and then you exit the C# app
you can't just call Application.exit() after the InitializeComponent(), instead to achieve that you need to exit after sending the data
sp.WriteLine("Z"); // Send 1 to Arduino
sp.Close();
Application.Exit(); ///here!!
So, I'm trying to use my Barcode Scanner as a 'Serial' device as opposed to a Keyboard emulator but it is not creating the com port. I have scanned the set-up codes from the manual that set it as a Serial device, that seems to configure the scanner correctly (it stops sending scanned codes to text-box\text editor) but because there is no COM port, I cannot capture the data when I scan a barcode......
Windows installed the driver when it was first plugged in, there wasn't a disk\driver supplied... wondered if anyone else has experienced the same issue.....
Here is my code....
class Program
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("com1", 9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
new Program();
}
private Program()
{
string[] ports = System.IO.Ports.SerialPort.GetPortNames();
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there
// is data waiting in the port's buffer
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
port.Open();
// Enter an application loop to keep this thread alive
Application.Run();
}
private void port_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
I get the error message..... 'The port 'com1' does not exist'..... when I try to open the Port.
When I create a virtual Port (using 3rd party app) the code runs BUT I still don't get the data from the Scanner....
I just newbie, and I was having task - recieve data from BarCode scaner by serial port... I spent a lot of time... and I have next result
using System.IO.Ports;
using System.Timers;
namespace BarCode_manager
{
public partial class MainWindow : Window
{
private static SerialPort currentPort = new SerialPort();
private static System.Timers.Timer aTimer;
private delegate void updateDelegate(string txt);
public MainWindow()
{
InitializeComponent();
currentPort.PortName = "COM6";
currentPort.BaudRate = 9600;
currentPort.ReadTimeout = 1000;
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
if (!currentPort.IsOpen)
{
currentPort.Open();
System.Threading.Thread.Sleep(100); /// for recieve all data from scaner to buffer
currentPort.DiscardInBuffer(); /// clear buffer
}
try
{
string strFromPort = currentPort.ReadExisting();
lblPortData.Dispatcher.BeginInvoke(new updateDelegate(updateTextBox), strFromPort);
}
catch { }
}
private void updateTextBox(string txt)
{
if (txt.Length != 0)
{
aTimer.Stop();
aTimer.Dispose();
txtReceive.Text = Convert.ToString(aTimer.Enabled);
currentPort.Close();
}
lblPortData.Text = txt;
lblCount.Content = txt.Length;
txtReceive.Text = Convert.ToString(aTimer.Enabled);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (currentPort.IsOpen)
currentPort.Close();
}
}
}
you may used below code. I can able to open the COM which I configured in specific port.
SerialPort _serialPort;
// delegate is used to write to a UI control from a non-UI thread
private delegate void SetTextDeleg(string text);
private void Form1_Load(object sender, EventArgs e)
{
// all of the options for a serial device
// can be sent through the constructor of the SerialPort class
// PortName = "COM1", Baud Rate = 19200, Parity = None,
// Data Bits = 8, Stop Bits = One, Handshake = None
//_serialPort = new SerialPort("COM8", 19200, Parity.None, 8, StopBits.One);
_serialPort = new SerialPort("COM8", 19200, Parity.None, 8, StopBits.One);
_serialPort.Handshake = Handshake.None;
_serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
}
I'm in the process of writing my own barcode scripts. My scanner defaults to being a plug-n-play USB-HID...Human Interface Device...as opposed to being a USB-COMn port. I have to scan a barcode to switch it over to serial port mode. You can watch the transformation process in the Device Manager tree...as a "Ports" branch sprouts out, containing your barcode scanner's details. Mine's COM3.
So I'm working in Unity3D, programming in C#, and I heard that one can read data from a Bluetooth adaptor via SerialPort. I have several Bluetooth USB adaptors that I've tried to connect on my PC using this method. However, when I try to open the SerialPort, I get an error message that says port does not exist. I only included the code relevant to the question, but portI is a string ("COM11" or "COM12") and PortIn is of type SerialPort.
void OnGUI() {
GUI.Label(new Rect(btnX, btnY, btnW, btnH), "PortIn = " + portI);
if(!connected) {
for (int i = 0; i<ports.Length; i++) {
if(GUI.Button(new Rect(btnX, btnY + btnH + (btnH * i), btnW, btnH), ports[i])) {
portI = ports[i];
}
}
}
if(GUI.Button(new Rect(btnX + (btnW * 2 + 20), btnY, btnW, btnH), "Connect")) {
portIn = new SerialPort(portI, 9600);
portIn.ReadTimeout = 1000;
if (!portIn.IsOpen) {
portIn.Open();
}
connected = true;
}
}
}
Here is some code I'm working on and it gets data from the bluetooth connection to a standalone pc build (or in the editor) as long as the COM port (in my case COM9) is the same as the bluetooth device when you pair it.
After you pair it go to Bluetooth Settings > COM Ports and see what port is there with the name of your device. It might say COM8 or COM9 or whatever. If the device is paired and the COM Port is the same in the code as it is in your Bluetooth Settings, AND the timeout number and baud rate are the same as in the application you are sending the data from... then you will get something from this code when you run it. This is just meant to help make a connection to the serial over bluetooth connection.
Hope it helps someone. I've gotten a lot of great advice from reading these forums ;)
using System.Collections;
using System.IO.Ports;
public class checker : MonoBehaviour {
public static SerialPort sp = new SerialPort("COM9", 9600, Parity.None, 8, StopBits.One);
public string message, message1;
public string message2;
void Start() {
OpenConnection();
}
void Update() {
message2 = sp.ReadLine();
}
void OnGUI() {
GUI.Label(new Rect(10, 180, 100, 220), "Sensor1: " + message2);
}
public void OpenConnection() {
if (sp != null)
{
if (sp.IsOpen)
{
sp.Close();
message = "Closing port, because it was already open!";
}
else
{
sp.Open();
sp.ReadTimeout = 1000;
message = "Port Opened!";
}
}
else
{
if (sp.IsOpen)
{
print("Port is already open");
}
else
{
print("Port == null");
}
}
}
void OnApplicationQuit() {
sp.Close();
}
}
It should be possible. The bluetooth rfcomm/spp services emulate a serial port. A COM port if it's on Windows. Baudrate doesn't matter in this emulation, it will always go as fast as possible.
You need to have the devices paired and connected though.
To what device are you connecting? Try to make a connection first with Putty or some terminal application.
I'm trying to program the UBW in C# to take a command and give me the input back. For example, when I establish the USB connection in TeraTerm, a input v would give me a output of the current firmware version of the UBW I'm using.
I have the connection established in C#. I think I'm sending the command right, but my datareceived handler is never called in the debugger.
Here is the code to try to write to the port:
private void button1_Click(object sender, EventArgs e)
{
if (port.IsOpen)
{
//write command to port
port.WriteLine(textBox1.Text);
}
else
{
MessageBox.Show("Serial port is closed! Try again!");
}
textBox1.Clear();
}
Here is the code to try to read from it (which is never called from the debugger)
private void port_dataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
port.ReadLine();
}
catch { }
}
Here is the UBW home page to show how it works. http://schmalzhaus.com/UBW/
My comboBox code to set up my port:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string portName = comboBox1.SelectedItem.ToString();
port = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
port.DataReceived += new SerialDataReceivedEventHandler(port_dataReceived);
try
{
port.Open();
//port.DataReceived += new SerialDataReceivedEventHandler(port_dataReceived);
}
catch
{
MessageBox.Show("The selected serial port cannot be opened!");
Application.Exit();
}
}
Go into TeraTerm's COM port properties, and make sure you're using the same properties in your code.
Try using this class (it wraps up a lot of serial stuff to make it easier):
http://code.google.com/p/flux3gui/source/browse/Flux3GUI/SerialCommunication.cs?r=b4a4f8546b936eeabe60b7de32e3027493498dc6