I have to write a program that writes on a serial port but sometimes the call to the Write method hangs and the WriteTimeout is never fired so my program hangs indefinitely.
Here is the port creation code:
void DetectX1BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
String[] ports = SerialPort.GetPortNames();
int i = 0;
foreach (string PortName in ports)
{
try
{
Console.WriteLine("Trying to open:" + PortName);
SerialPort port = openSerial(PortName);
Console.WriteLine("Port is open:" + PortName);
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Write("$ST+IMEI=0000\r\n");
if (IMEIFoundEvent.WaitOne(250))
{
Console.WriteLine("IMEI Found:[" + imei + "]");
if (addresses.ContainsKey(imei))
{
((BackgroundWorker)sender).ReportProgress(0, new X1Model(imei, PortName, addresses[imei]));
}
else
Console.WriteLine("imei not in file: " + imei);
}
port.Close();
}
catch (Exception ex)
{
Console.WriteLine("Erreur port " + PortName + ex.Message);
}
finally
{
i++;
((BackgroundWorker)sender).ReportProgress(i * 100 / ports.Length);
}
}
}
private SerialPort openSerial(string PortName)
{
SerialPort port = new SerialPort(PortName);
port.BaudRate = 57600;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReceivedBytesThreshold = 1;
port.Handshake = Handshake.None;
port.DtrEnable = true;
port.RtsEnable = true;
port.WriteTimeout = 5000;
port.ReadTimeout = 5000;
if (!port.IsOpen)
port.Open();
return port;
}
Is there anything I'm missing ?
I don't know if it's relevant but I'm using Serial To USB Adapters.
Edit: I'm using Windows XP with .Net 4.0. The line doesnt't exceed 50 characters and ends by a EOL character.
I know it's an old question, which you've probably solved by now, but there's no accepted answer yet. I was having the same issue yesterday and seem to have fixed it -- were you setting the Write Timeout?
_serialPort.WriteTimeout = 500;
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.writetimeout.aspx
You also need to set the PortName. You can get the list of ports from GetPortNames. This will typically be like COM1 or COM2
Related
I have a Selenium Test Suite (using NUnit) that goes and talks to the web.
I have a port initializer that opens up a USB (Com) port with some external device.
However, when running the port initializer inside of the NUnit framework, it spins out, and I get no response from the test explorer. I doubt the issue is with the code, I suspect it's with how Selenium functions, but I will attach a section of it just in case.
Here's the example:
// Assume I have IO Ports, NUnit, and System initialized.
[TestFixture]
class CartToucher
{
static bool _continue;
static SerialPort _serialPort;
[SetUp]
public static void ComSelection()
{
string name;
string message;
StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;
Thread readThread = new Thread(Read);
// Create a new SerialPort object with default settings.
_serialPort = new SerialPort();
// Allow the user to set the appropriate properties.
string[] ports = SerialPort.GetPortNames();
_serialPort.PortName = SetPortName(_serialPort.PortName);
_serialPort.BaudRate = 115200;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = 8;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
// Set the read/write timeouts
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
_continue = true;
readThread.Start();
Console.Write("Name: ");
name = Console.ReadLine();
Console.WriteLine("Type QUIT to exit");
while (_continue)
{
message = Console.ReadLine();
if (stringComparer.Equals("quit", message))
{
_continue = false;
}
else
{
_serialPort.WriteLine(String.Format("<{0}>: {1}", name, message));
}
}
readThread.Join();
_serialPort.Close();
static void Read()
{
while (_continue)
{
try
{
string message = _serialPort.ReadLine();
Console.WriteLine(message);
}
catch (TimeoutException) { }
}
}
static string SetPortName(string defaultPortName)
{
string portName;
Console.WriteLine("Available Ports:");
foreach (string s in SerialPort.GetPortNames())
{
Console.WriteLine(" {0}", s);
}
Console.Write("Enter COM port value (Default: {0}): ", defaultPortName);
portName = Console.ReadLine();
if (portName == "" || !(portName.ToLower()).StartsWith("com"))
{
portName = defaultPortName;
}
return portName;
}
}
Below this section, I run some 'tests' to select my Com Port using Console.WriteLine("COM15");. However, I never see the terminal screen.
so I wrote a terminal in c# and I need to communicate with a kl25z microprocessor.
the application needs to support the option to choose the number of stop bits, the baud rate and the parity method.
I managed to sort it out with the baud rate but when I try to change the stop bits something goes out of sync and I cant figure out what.
the problem is that the uart is getting jibrish kind of chars instead of what I intended it to get, it does work well when I use one stop bit so I assume I just missed something in my code
I'll add the part of the code that gives me hard time:
this is only the c# part, my terminal I'm pretty sure that the problem is here
and not in the kl25z code
public Form1() {
InitializeComponent(); //init all variables
getAvailablePorts(); //fill the ports combo box with all the ports
}
void getAvailablePorts() {
String[] ports = SerialPort.GetPortNames(); //get the names of all availoable ports
comboBox1.Items.AddRange(ports); //add all the ports names to the combo box
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
try {
SerialPort sp = (SerialPort) sender;
if (serialPort1.IsOpen & sp.IsOpen) {
string indata = sp.ReadLine();
Invoke(new Action(() => textBox1.Text = indata));
if (indata.Equals("new settings been set") ||
indata.Equals("\0new settings been set") ||
indata.Equals("new settings been set??")) {
// baud rate
Invoke(new Action(() => baud = Convert.ToInt32(comboBox3.Text)));
Invoke(new Action(() => serialPort1.BaudRate = baud));
//end bits
Invoke(new Action(() => serialPort1.StopBits = end));
}
}
} catch (System.IO.IOException error) {
return;
} catch (System.InvalidOperationException error) {
return;
}
}
//here i open the port
private void button3_Click(object sender, EventArgs e) { //start port
try { // give the micro processor the info it needs about the settings
serialPort1.Handshake = Handshake.RequestToSendXOnXOff;
serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
serialPort1.PortName = comboBox1.Text; //port
serialPort1.BaudRate = baud; //baud rate current
// serialPort1.Parity= parity;//parity current
serialPort1.StopBits = end; //stopBits current
serialPort1.DataBits = bits; //current
//sort strings to send
String baudString = comboBox3.Text;
String StopString = comboBox6.Text;
String bitsString = comboBox2.Text;
String parityString = comboBox4.Text;
String startString = comboBox5.Text;
serialPort1.Open(); //open port
bitsString = "8";
//send properties to klz
serialPort1.Write("prop" + "$" + baudString + "$" + StopString + "$" + bitsString + "$" + parityString + "$" + startString + "$");
if (Convert.ToInt32(comboBox6.Text) == 1) {
end = StopBits.One;
} else {
end = StopBits.Two;
}
bits = Convert.ToInt32(comboBox2.Text);
} catch (UnauthorizedAccessException) {
textBox1.Text = "Unauthorized Access";
}
try {
progressBar1.Value = 100;
button1.Enabled = true;
button2.Enabled = true;
button3.Enabled = false;
button4.Enabled = true;
textBox2.Enabled = true;
} catch (UnauthorizedAccessException) {
textBox1.Text = "Unauthorized Access";
}
}
I am making an application using Windows IoT Core on the Raspberry Pi 3.
I am trying to communicate with an Arduino using serial communication. I have used most of the methods shown in this example on GitHub for creating the serial device and writing to it: https://github.com/ms-iot/samples/tree/develop/SerialSample/CS.
The program runs fine for the first 130 bytes or so, but then will begin to slow down dramatically after that and crash around the 135th byte or so.
Sometimes it causes the Raspberry Pi to display the Windows 10 "blue screen of death" saying that it needs to restart.
I've tried rewriting the code many ways and using different variations of async, task, and await, but can't seem to get it to work.
Here's the code I use to initialize the serial device:
private async void setup()
{
serialPort = await initializeSerial();
}
private async Task<SerialDevice> initializeSerial()
{
try
{
string aqs = SerialDevice.GetDeviceSelector();
var dis = await DeviceInformation.FindAllAsync(aqs);
for (int i = 0; i < dis.Count; i++)
{
if (dis[i].Name.Contains("Arduino Uno"))
{
var serialPort = await SerialDevice.FromIdAsync(dis[i].Id);
/* Configure serial settings */
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.BaudRate = 9600;
serialPort.Parity = SerialParity.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.DataBits = 8;
serialPort.Handshake = SerialHandshake.None;
// Display configured settings
//Debug.WriteLine("Serial port configured successfully.");
// Create cancellation token object to close I/O operations when closing the device
ReadCancellationTokenSource = new CancellationTokenSource();
return serialPort;
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return null;
}
and here's the code I use to write to the serial device:
private async void sendString(string stringToSend)
{
try
{
if (serialPort != null)
{
// Create the DataWriter object and attach to OutputStream
dataWriteObject = new DataWriter(serialPort.OutputStream);
//Launch the WriteAsync task to perform the write
await WriteAsync(stringToSend);
}
else
{
status.Text = "Select a device and connect";
}
}
catch (Exception ex)
{
status.Text = "sendString: " + ex.Message;
}
finally
{
// Cleanup once complete
if (dataWriteObject != null)
{
dataWriteObject.DetachStream();
dataWriteObject = null;
}
}
}
/// <summary>
/// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream
/// </summary>
/// <returns></returns>
private async Task WriteAsync(string stringToWrite)
{
Task<UInt32> storeAsyncTask;
dataWriteObject.WriteString(stringToWrite);
// Launch an async task to complete the write operation
storeAsyncTask = dataWriteObject.StoreAsync().AsTask();
UInt32 bytesWritten = await storeAsyncTask;
if (bytesWritten > 0)
{
counter++;
status.Text = stringToWrite + ", ";
status.Text += "bytes written successfully! (" + counter + ")";
}
}
Any help/advice would be appreciated.
Update
I rewrote my sendString method as this and simplified it using a using statement:
private async void sendString(string stringToSend)
{
using (DataWriter dataWriter = new DataWriter(serialPort.OutputStream))
{
dataWriter.WriteString(stringToSend);
await dataWriter.StoreAsync();
//await dataWriter.FlushAsync();
dataWriter.DetachStream();
counter++;
status.Text = stringToSend + ", ";
status.Text += "bytes written successfully! (" + counter + ")";
}
}
However, the problem still persists.
I tried using the UART pins instead of the USB cable to write data, and experienced no more issues. Here's the code I used to initialize the UART bus on the Pi and I used the same function to write as I used above:
private async Task<SerialDevice> initializeSerial()
{
try
{
string aqs = SerialDevice.GetDeviceSelector("UART0");
var dis = await DeviceInformation.FindAllAsync(aqs);
SerialDevice serialPort = await SerialDevice.FromIdAsync(dis[0].Id);
/* Configure serial settings */
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.BaudRate = 9600;
serialPort.Parity = SerialParity.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.DataBits = 8;
serialPort.Handshake = SerialHandshake.None;
status.Text = "Serial port configured succesfully.";
return serialPort;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
status.Text = "Serial port not configured successfully. Are you sure a serial device is connected?";
return null;
}
This doesn't exactly answer the problem with sending data over the USB cable, but I'm posting it here in case anyone has a similar problem with using the USB port and would like to try this instead.
I coded a program to dial automatically when phone is connected to the laptop and get the last call duration.I used AT+CLCC command to get current call status..Though it should return the Some string value as .......etc i got nothing like that so far...Here is my code..
_serialPort.BaudRate = 9600;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = 8;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
// Set the read/write timeouts
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
_serialPort.DtrEnable = true;
_serialPort.RtsEnable = true;
string phonenr = "";
// string mesaj;
if (!_serialPort.IsOpen)
{
_serialPort.Open();
}
_serialPort.WriteLine("AT\r");
{
Console.WriteLine("Enter the phone number:", phonenr);
phonenr = Console.ReadLine();
_serialPort.WriteLine("ATD" + phonenr + ";" + "\r");
Console.WriteLine("Ring...");
Thread.Sleep(10000);
_serialPort.WriteLine("AT+CLCC");
_serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
//As a seperate function....
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
What is the wrong with this code????How can i get the response as the format ...etc ???
AT+CLCC command does not provide information about the last call. It provides information during a call (during dialing/ringing/waiting etc). Read this for detailed information
I think you can make the phone to output last call details automatically to the terminal, when the call is disconnected but I'm not sure if it provides call duration. You might have to monitor/record the time manually with your application
I have seen other posts where you have asked similar questions. I would recommend using a simple serial port terminal (putty or terminal etc.) to communicate with the phone and grasp the AT commands concept, before moving on to controlling the phone using your own code.
I'm writing a serialport app to talk to a Bluetooth module over serial port. The first At command I send to the device runs fine and I get a response of the module version. All subsequent commands fail with a response of ERROR.
Part of the code is here:
namespace PhoneApp
{
public partial class Form1 : Form
{
//SerialPort myport = OPenPort.OpenIt();
SerialPort myport = new SerialPort();
public Form1()
{
InitializeComponent();
myport.PortName = "COM3";
myport.BaudRate = 115200;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.NewLine = System.Environment.NewLine;
myport.ReadTimeout = 500;
myport.WriteTimeout = 500;
myport.DtrEnable = false;
myport.RtsEnable = false;
myport.WriteBufferSize = 4096;
myport.ReadBufferSize = 4096;
myport.Handshake = Handshake.None;
myport.Encoding = System.Text.Encoding.ASCII;
if (!myport.IsOpen)
{
myport.Open();
}
calling.Visible = false;
myport.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
mycommand.Text = #"AT+BGVER";
the button which sends the command. The device requires a newline after each comand.
private void button2_Click(object sender, EventArgs e)
{
try
{
myport.WriteLine(mycommand.Text.Trim());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Not sure what I'm missing here.
Thanks for the replies. i found the problem. In fact I had to use myport.Write instead of myport.WriteLine. I deleted the line myport.NewLine and I appended "\r" to every command. Now the device responds as expected. As for DTR and RTS they are not required by the device according to the vendor
Not sure if this solves your problem, but I noticed that you don't have flow control enabled (e.g. myport.RtsEnable = false; myport.DtrEnable = false;).
Have you checked the documentation to make sure that the Bluetooth module doesn't require it? Typically devices with 115kbps and higher need flow control.
Another thing to check is the NewLine constant. You set it to the sys default which is likely Cr+Lf. Make sure that the module expects that.