Arduino and C# Serial Port "Crash" - c#

I am trying to create a communication between an Arduino Leonardo and C#.
Just now, the Arduino's software sends a simple message (in loop) on the serial port:
void setup() {
Serial.begin(9600);
analogReference(INTERNAL);
}
void loop() {
Serial.println("test");
delay(500);
}
C# try only to read these messages and print them on the shell:
public class Program
{
private SerialPort mySerialPort;
static void Main(string[] args)
{
Program p = new Program();
Console.WriteLine("PORTS: " + String.Join(" ", p.getSerialPortsList())+ ", enter to start.");
Console.Read();
p.SerialRead("COM6");
}
public String[] getSerialPortsList()
{
string[] ports = SerialPort.GetPortNames();
return ports;
}
public void SerialRead(String com)
{
mySerialPort = new SerialPort(com, 9600, Parity.None, 8, StopBits.One);
Console.Read();
Console.WriteLine("Incoming Data:");
SerialRead sr = new SerialRead();
Thread rs = new Thread(sr.StartRead);
sr.SetMySerialPort(mySerialPort);
rs.Start();
while (!rs.IsAlive);
Console.Read();
sr.SetSuspendThread(true);
rs.Join();
}
}
public class SerialRead
{
private Boolean suspendThread = false;
SerialPort mySerialPort;
public void StartRead()
{
mySerialPort.Open();
Thread.Sleep(500);
int i = 0;
while (!suspendThread)
{
i++;
Console.WriteLine(i + ": " + mySerialPort.ReadLine());
Thread.Sleep(500);
}
}
public void SetMySerialPort(SerialPort mysp){ mySerialPort = mysp; }
public void SetSuspendThread(Boolean a){ suspendThread = a; }
}
The output of this C# software depends. If I use the serial monitor on the Arduino IDE, then I receive the string's stream correctly (one each 500ms).
Otherwise, the C# software freezes. Sometimes, I receive a couple of strings as we can see this figure; but almost all time, the software does not give any string, as we can see here. After that the software freezes (thus, if I press enter the shell does not response).
Can you suggest a solution in order to get a fluent flow of string, and -as a consequence- read each message sent by Arduino on the serial port?
I am using Window 10 x64 as OS and the COM6 (it is an USB 2.0).

I found the solution and I share it in order to help people with the same problem.
C# does not activate as default the RTS and the DTR serial port.
Thus, adding
mySerialPort.DtrEnable = true;
mySerialPort.RtsEnable = true;
after the serial port declaration, everything works fine.

This is a really good example:
Serial Port Polling and Data handling
The Serial Port got an event called DataRecived, so you dont have to sleep your thread.
Something like this:
serialPort.DataReceived +=SerialPortDataReceived;
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine(serialPort.ReadLine());
}

Related

Unable to connect Bluetooth device using c#

I'm using 32 feet library to develop Bluetooth communication WPF app, and able to pair the device but not working to connect it and ended up with an exception like below.
Note: I've tried to connect the devices like my mobile and my PC, but both are giving the same errors as explained below.
I've seen somewhere about this issue and they mentioned like, this issue may be because of 32 feet library is not compatible with the Bluetooth device that I've in my PC.
But actually, I've tested this in some other PC's which are running with Windows 7 OS - 64 bit and getting the same error message.
Anyone help me out. Thank you.
Error Message: The requested address is not valid in its context ECD09F51114A:0000110100001000800000805f9b34fb
My code sample:
Guid uId = new Guid("0000110E-0000-1000-8000-00805f9b34fb");
bool receiverStarted = false;
private List<BluetoothDeviceInfo> deviceList;
private List<string> deviceNames;
private BluetoothDeviceInfo deviceInfo;
private string myPin = "1234";
private BluetoothClient sender;
private void BtnScan_Click(object sender, RoutedEventArgs e)
{
ScanAvailableDevices();
}
private void ScanAvailableDevices()
{
lstAvailableDevices.ItemsSource = null;
lstAvailableDevices.Items.Clear();
deviceList.Clear();
deviceNames.Clear();
Thread senderThread = new Thread(new ThreadStart(Scan));
senderThread.Start();
}
private void Scan()
{
UpdateStatus("Starting scan...");
sender = new BluetoothClient();
availableDevices = sender.DiscoverDevicesInRange();
UpdateStatus("Scan completed.");
UpdateStatus(availableDevices.Length.ToString() + " device(s) discovered");
foreach(BluetoothDeviceInfo device in availableDevices)
{
deviceList.Add(device);
deviceNames.Add(device.DeviceName);
}
UpdateAvailableDevices();
}
private void UpdateAvailableDevices()
{
Func<int> devicesDelegate = delegate ()
{
lstAvailableDevices.ItemsSource = deviceNames;
return 0;
};
Dispatcher.BeginInvoke((Action)(() =>
{
devicesDelegate.Invoke();
}));
}
private void PairDevice()
{
deviceInfo = deviceList[lstAvailableDevices.SelectedIndex];
if (CanPair())
{
UpdateStatus("Device paired..");
UpdateStatus("Starting to connect the device");
Thread senderThread = new Thread(new ThreadStart(SenderConnectThread));
senderThread.Start();
}
}
private bool CanPair()
{
if(!deviceInfo.Authenticated)
{
if(!BluetoothSecurity.PairRequest(deviceInfo.DeviceAddress,myPin))
{
return false;
}
}
return true;
}
private void LstAvailableDevices_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
deviceInfo = deviceList[lstAvailableDevices.SelectedIndex];
UpdateStatus(deviceInfo.DeviceName + " was selected, attempting connect");
if (CanPair())
{
UpdateStatus("Device paired..");
UpdateStatus("Starting connect thread");
Thread senderThread = new Thread(new ThreadStart(ClientConnectThread));
senderThread.Start();
}
else
{
UpdateStatus("Pair failed");
}
}
private void ClientConnectThread()
{
BluetoothClient sender = new BluetoothClient();
BluetoothAddress address = deviceInfo.DeviceAddress;
//sender.SetPin(deviceInfo.DeviceAddress, myPin);
var endPoint = new BluetoothEndPoint(address, uId);
sender.Connect(endPoint);
//Another way that I've tried
BluetoothClient client = new BluetoothClient();
UpdateStatus("Attempting connect");
//client.Connect(deviceInfo.DeviceAddress, uId);
client.BeginConnect(deviceInfo.DeviceAddress, uId, this.BluetoothClientConnectCallback, client);
}
void BluetoothClientConnectCallback(IAsyncResult result)
{
BluetoothClient senderE = (BluetoothClient)result.AsyncState;
senderE.EndConnect(result);
Stream stream = senderE.GetStream();
while (true)
{
while (!ready) ;
byte[] message = Encoding.ASCII.GetBytes(txtSenderMessage.Text);
stream.Write(message, 0, message.Length);
}
}
There are libraries in UWP where you can easily make a connection between your desktop and other devices , you can easily handle the Bluetooth Adapter.
There are multiple downloads for 32 feet
Try these
Downloading
https://github.com/inthehand/32feet
Downloads are available here on the Downloads tab. Packages are also available at NuGet:-
InTheHand.Devices.Bluetooth - Modern (v4.x) - Preview NuGet version
32feet.NET - Legacy (v3.x) NuGet version
32feet.NET.Phone - Windows Phone NuGet version
InTheHand.Devices.Enumeration (Windows 8 / Windows Phone Device Pickers) NuGet version
Folks, I'm able to pair and connect it using the same application running in different PC and acting it as a server. Earlier I've tried this without having the same application running in the target PC and thus it's giving the error that I mentioned above.
Thanks guys for your time and support.

SerialDataReceivedEventHandler not working c#

I'm trying to connect to arduino with C# program in windows forms.
I can send data from c# to the arduino but I want to get data from the arduino to the C# program.
I've tried the SerialDataReceivedEventHandler, but I don't get the data after the form is built...
what can I do?
public Form1()
{
InitializeComponent();
Init();
}//end form 1
private void Init()
{
try
{
arduinoPort = new SerialPort();
arduinoPort.BaudRate = 9600;
arduinoPort.PortName = "COM4";
arduinoPort.Handshake = Handshake.None;
arduinoPort.RtsEnable = true;//request to send true
arduinoPort.DtrEnable = true;//arduino can send messages to the c# program
arduinoPort.DataReceived += new SerialDataReceivedEventHandler(GetFromArduino);
arduinoPort.Open();
}//end try
catch (Exception ex) { MessageBox.Show(ex.Message); }
}//end init
private void GetFromArduino(object sender, SerialDataReceivedEventArgs e)
{
//string arduinoInputString = arduinoPort.ReadLine();
//Invoke(new Action(() => label1.Text = arduinoInputString));
MessageBox.Show("does it work?");
}//end get from arduino
MessageBox.Show isn't going to work from the DataReceived event
SerialPort.DataReceived Event
The DataReceived event is raised on a secondary thread when data is
received from the SerialPort object. Because this event is raised on a
secondary thread, and not the main thread, attempting to modify some
elements in the main thread, such as UI elements, could raise a
threading exception. If it is necessary to modify elements in the main
Form or Control, post change requests back using Invoke, which will do
the work on the proper thread
at best you need to do something like this
this.Invoke(new Action(() => { MessageBox.Show(this, "text"); }));
However, if you really want to know if that event is fired, then use a break-point
Using Breakpoints
Lastly, if the event isnt fired, then you will have to consult the documentation for the device for the appropriate configuration of the device and the serial port.
Make some handler method, for example
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort comm = (SerialPort)sender;
string incoming_Data = comm.ReadExisting();
this.BeginInvoke((MethodInvoker)delegate()
{
Console.WriteLine(incoming_Data + "\n");
});
}
Then, make this method to the subscriber of DataRecieved event
arduinoPort.DataReceived += DataReceivedHandler;
Source: https://social.msdn.microsoft.com/Forums/vstudio/en-US/bd8f7ac8-67d5-4eb5-b679-c595f9c7536d/how-to-print-out-text-from-serialport-datareceived-event?forum=netfxbcl
I don't know if it matters, but this what i did and it solved:
1. in the setup function of the arduino program i had a loop that ran on all the pins, now i specified it to the pins i really use.
2. i don't open the port in the form.cs, but in the program.cs and run a while loop that just check if the port is open. then, it gets the data without disturbing the form to run...
**in the Program.cs:**
public static SerialPort arduinoPort { get; set; }
public static string arduinoInputString { get; set; }
[STAThread]
static void Main()
{
arduinoPort = new SerialPort();
try
{
arduinoPort = new SerialPort();
arduinoPort.BaudRate = 250000;
arduinoPort.PortName = "COM4";
//arduinoPort.Handshake = Handshake.None;
//arduinoPort.RtsEnable = true;//request to send true
//arduinoPort.DtrEnable = true;//arduino can send messages to the c# program
////arduinoPort.DataReceived += new SerialDataReceivedEventHandler(GetFromArduino);
arduinoPort.DataReceived += DataReceivedHandler;
arduinoPort.Open();
}//end try
catch (Exception ex) { Console.WriteLine((ex.Message)); }
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
while (arduinoPort.IsOpen)//read data if the port is open
{
}
}//end main
static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort comm = (SerialPort)sender;
arduinoInputString = comm.ReadExisting();
Form1.label1.Text = arduinoInputString;//label to show the input string from arduino
}//end get data from arduino

Serial COM read returns null [duplicate]

I am developing program which need to interact with COM ports.
By learning from this Q&A: .NET SerialPort DataReceived event not firing, I make my code like that.
namespace ConsoleApplication1
{
class Program
{
static SerialPort ComPort;
public static void OnSerialDataReceived(object sender, SerialDataReceivedEventArgs args)
{
string data = ComPort.ReadExisting();
Console.Write(data.Replace("\r", "\n"));
}
static void Main(string[] args)
{
string port = "COM4";
int baud = 9600;
if (args.Length >= 1)
{
port = args[0];
}
if (args.Length >= 2)
{
baud = int.Parse(args[1]);
}
InitializeComPort(port, baud);
string text;
do
{
String[] mystring = System.IO.Ports.SerialPort.GetPortNames();
text = Console.ReadLine();
int STX = 0x2;
int ETX = 0x3;
ComPort.Write(Char.ConvertFromUtf32(STX) + text + Char.ConvertFromUtf32(ETX));
} while (text.ToLower() != "q");
}
private static void InitializeComPort(string port, int baud)
{
ComPort = new SerialPort(port, baud);
ComPort.PortName = port;
ComPort.BaudRate = baud;
ComPort.Parity = Parity.None;
ComPort.StopBits = StopBits.One;
ComPort.DataBits = 8;
ComPort.ReceivedBytesThreshold = 9;
ComPort.RtsEnable = true;
ComPort.DtrEnable = true;
ComPort.Handshake = System.IO.Ports.Handshake.XOnXOff;
ComPort.DataReceived += OnSerialDataReceived;
OpenPort(ComPort);
}
public static void OpenPort(SerialPort ComPort)
{
try
{
if (!ComPort.IsOpen)
{
ComPort.Open();
}
}
catch (Exception e)
{
throw e;
}
}
}
}
My problem is DataReceived event never gets fired.
My program specifications are:
Just .net console programming
I use VSPE from http://www.eterlogic.com
My computer has COM1 and COM2 ports already.
I created COM2 and COM4 by using VSPE.
I get output result from mystring array (COM1, COM2, COM3, COM4)
But I still don't know why DataReceived event is not fired.
Updated
Unfortunately, I still could not make to fire DataReceived event in any way.
So, I created new project by hoping that I will face a way to solve.
At that new project [just console application], I created a class...
public class MyTest
{
public SerialPort SPCOM4;
public MyTest()
{
SPCOM4 = new SerialPort();
if(this.SerialPortOpen(SPCOM4, "4"))
{
this.SendToPort(SPCOM4, "com test...");
}
}
private bool SerialPortOpen(System.IO.Ports.SerialPort objCom, string portName)
{
bool blnOpenStatus = false;
try
{
objCom.PortName = "COM" + portName;
objCom.BaudRate = 9600;
objCom.DataBits = 8;
int SerParity = 2;
int SerStop = 0;
switch (SerParity)
{
case 0:
objCom.Parity = System.IO.Ports.Parity.Even;
break;
case 1:
objCom.Parity = System.IO.Ports.Parity.Odd;
break;
case 2:
objCom.Parity = System.IO.Ports.Parity.None;
break;
case 3:
objCom.Parity = System.IO.Ports.Parity.Mark;
break;
}
switch (SerStop)
{
case 0:
objCom.StopBits = System.IO.Ports.StopBits.One;
break;
case 1:
objCom.StopBits = System.IO.Ports.StopBits.Two;
break;
}
objCom.RtsEnable = false;
objCom.DtrEnable = false;
objCom.Handshake = System.IO.Ports.Handshake.XOnXOff;
objCom.Open();
blnOpenStatus = true;
}
catch (Exception ex)
{
throw ex;
}
return blnOpenStatus;
}
private bool SendToPort(System.IO.Ports.SerialPort objCom, string strText)
{
try
{
int STX = 0x2;
int ETX = 0x3;
if (objCom.IsOpen && strText != "")
{
objCom.Write(Char.ConvertFromUtf32(STX) + strText + Char.ConvertFromUtf32(ETX));
}
}
catch (Exception ex)
{
throw ex;
}
return true;
}
}
I am not sure that I face good luck or bad luck because this new class could make fire DataReceived event which is from older console application that is still running. It is miracle to me which I have no idea how this happen.
Let me tell you more detail so that you could give me suggestion for better way.
Finally I created 2 console projects.
First project is the class which I posted as a question yesterday.
Second project is the class called MyTest which could make fire DataReceived event from First project, at the same time when two of the project is running.
Could anyone give me suggestions on how could I combine these two projects as a single project?
ComPort.Handshake = Handshake.None;
The problem is not that the DataReceived event doesn't fire, the problem is that the serial port isn't receiving any data. There are very, very few serial devices that use no handshaking at all. If you set it to None then the driver won't turn on the DTR (Data Terminal Ready) and RTS (Request To Send) signals. Which a serial port device interprets as "the machine is turned off (DTR)" or "the machine isn't ready to receive data (RTS)". So it won't send anything and your DataReceived event won't fire.
If you really want None then set the DTREnable and RTSEnable properties to true. But it is likely you want HandShake.RequestToSend since the device appears to be paying attention to the handshake signals.
If you still have trouble then use another serial port program like Putty or HyperTerminal to ensure the connection and communication parameters are good and the device is responsive. SysInternals' PortMon utility gives a low-level view of the driver interaction so you can compare good vs bad.
I have never worked with VSPE so I'm not sure if that causes the problem. I have worked with a COM port before and I looked up my code. The only main difference is the way you declare the event. You have:
ComPort.DataReceived += OnSerialDataReceived;
I have it like this:
ComPort.DataReceived += new SerialDataReceivedEventHandler(OnSerialDataReceived);
OnSerialDataReceived is your eventhandler. I'm not sure if this will make any difference, but you can try it. I hope this helps!
I had a quite similar problem. In a graphical application (C# win form) I had a class which encapsulate a SerialPort component. The DataReceived event was firing only one time, but then any following data received didn't fire any event. I solved the problem by calling the Close method in my principal form Closed event function.
No idea of why that changes anything, but now it's working.

Unable to get all characters from serial port

I'm doing a keypad project for 10-digit ID input. For each key press, it will send '1' or '2' or '3' and so on to the serial port. However, after trying to display the content of my id buffer with Console.WriteLine(id[i]), it only display the first keypad value from serial port. I need to display all 10-digit input from the buffer. I cant find where is the error in the code. I'm using System.IO.Ports
static void Main(string[] args)
{
char[] id = new char[10] ;
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
if (port.IsOpen)
{
Console.WriteLine("port is now open");
}
else
{
Console.WriteLine("port not opened correctly");
}
port.Read(id, 0, 10);
for (int i = 0; i < 10; i++)
{
Console.WriteLine(id[i]);
}
Console.ReadLine();
}
First check whether your device is sending any data.
You can use a RS232 terminal for this.
Termite is a free terminal software.
If your hardware is sending data correctly,
Add DataReceive event,
port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
Then use ReadExisting() method for capture received data.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine(port.ReadExisting());
}

Serial Port listening in C#

There are loads of questions about listening of devices on Serial Port using C#.
However I couldn't find something that will be useful for my application and working.
Now this is a code i finally decided to use however I cannot see why it will not output anything:
namespace SerialPorts
{
class Program
{
static void Main(string[] args)
{
SerialPort myPort = new SerialPort();
myPort.DataReceived += MyPortDataReceived;
myPort.PortName = "COM3";
myPort.BaudRate = 19200;
myPort.DataBits = 7;
myPort.Parity = Parity.Even;
myPort.StopBits = StopBits.One;
myPort.Open();
Console.ReadLine();
myPort.Close();
}
static void MyPortDataReceived(object sender,
SerialDataReceivedEventArgs e)
{
var myPort = sender as SerialPort;
Console.WriteLine(myPort.ReadLine());
}
}
}
My device is OCR PASSORT reader.
I expect a string when i swipe a passport. However I get nothing, no output at all.
Can you please help me what can i do to make it output a string at least?
BTW I know the OCR reader is working since there is an app coming with it that outputs its data and when I use apps that test the COM i get data but with this code I get nothing. Any help will be appreciated!
Regards!

Categories