I recently purchased a modem, which attaches via USB and appears to the operating system as a serial port device: COM19
To ensure the modem was OK, I first tried using PuTTY in serial mode. From there, I have no problem issuing AT commands and receiving responses from the modem. According to PuTTY configuration, my default options for controlling local serial lines are (at the time):
Speed (baud): 9600
Data bits: 8
Stop bits: 1
Parity: None
Flow control: XON/XOFF
Here's what I see in PuTTY (when I type the AT command):
AT
OK
^BOOT:30645964,0,0,0,75
However, when I try to access the same COM port from .NET (not at the same time as running PuTTY) I never receive the "OK" responses. I do still receive (what appears to be) echo, and the occasional unsolicited message from the modem, so I can see that I'm connected to the correct device. Sometimes the modem will respond to a malformed command with "ERROR", but never "OK". Here's the C# snippet where I initialize the COM port:
var commandPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
commandPort.DataReceived += CommandPort_DataReceived;
commandPort.Handshake = Handshake.XOnXOff;
commandPort.Open();
commandPort.Write("AT\n");
for (var i = 0; i < 30; i++)
{
Thread.Sleep(1000);
}
And this is the event handler:
private static void CommandPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.Write(((SerialPort)sender).ReadExisting());
}
This is what's printed back to the console of the C# application (note that I'm not explicitly writing the command to the console, it's added by the CommandPort_DataReceived event handler):
AT
^BOOT:30645964,0,0,0,75
None of the AT commands issued by the .NET application perform any action, though their equivalents in PuTTY are able to query modem state, place calls, etc. What am I doing wrong?
Use the SerialPort class's NewLine property. By default it's set to "\n". This needs to be "\r", then you can use the WriteLine(...) method to send AT commands.
commandPort.NewLine = "\r";
commandPort.Open();
commandPort.WriteLine("AT");
Related
I'm using C# and .NET 4.5, with the Visual Studio 2012 compiler/IDE to open and interact with a serial port. My code is designed to connect to the QSB quadrature-to-USB converter from US Digital.
Here is the code that I'm using to open the port and connect.
this.Port = new SerialPort();
this.Port.BaudRate = 230400;
this.Port.PortName = "COM9";
this.Port.Parity = Parity.None;
this.Port.Handshake = Handshake.None;
this.Port.DataBits = 8;
this.Port.StopBits = StopBits.One;
this.Port.Open();
Setting a breakpoint immediately after this.Port.Open() allows me to verify that the serial port is indeed connected. In another section of code, the following is called in response to a button push:
this.Port.WriteLine("W168");
This command *should cause my hardware to spin a motor, and in fact it does if I send the command using Putty, or using a Python script that I wrote (both using exactly the same settings as the C# code does). Yet nothing happens. I can open the port in Putty or Python and execute the command with the expected results, and then run my C# code and nothing happens.
Am I missing something C# specific that prevents this from working?
For what it's worth, here is my working Python code:
ser = serial.Serial("COM9", 230400, timeout=1)
ser.write(b"W168\n")
Link to pySerial documentation: http://pyserial.sourceforge.net/pyserial_api.html#classes
Default values for fields mentioned in the C# code but not mentioned in the python call above are:
bytesize = 8
parity = none
stopbits = one
xonxoff = false
rtscts = false
dsrdtr = false
When working with Serial Ports in C# there is one thing to always remember when establishing a connection. If you set the handshake value to none like this:
this.Port.Handshake = Handshake.None;
Then you need to set a few more parameters as well for the connection to be completed, and they are:
this.Port.DtrEnable = true;
this.Port.RtsEnable = true;
The reaso is because the Dtrenable means this:
Data Terminal Ready (DTR) signal
MSDN explains what DTR means as this:
Data Terminal Ready (DTR) is typically enabled during XON/XOFF software handshaking and Request to Send/Clear to Send (RTS/CTS) hardware handshaking, and modem communications.
Rtsenable means this:
Request to Send (RTS) signal
MSDN explains what RTS means as this:
The Request to Transmit (RTS) signal is typically used in Request to Send/Clear to Send (RTS/CTS) hardware handshaking.
Together these two parameters handle the handshaking of the serial port communications without you having to define it between the master and slave.
Hi I am using TCPCLient and TCPlitner to transmit data but i am getting error not to connect
below is my Code
private void button1_Click(object sender, EventArgs e)
{
TcpClient tcpc = new TcpClient("192.168.21.46", 10);
NetworkStream nts = tcpc.GetStream();
if (nts.CanWrite)
{
Byte[] sends = System.Text.Encoding.ASCII.GetBytes(textBox1.Text.ToCharArray());
nts.Write(sends, 0, sends.Length);
nts.Flush();
}
}
private void button2_Click(object sender, EventArgs e)
{
TcpListener myListener = new TcpListener(10);
myListener.Start();
while (true)
{
//Accept a new connection
Socket mySocket = myListener.AcceptSocket();
if (mySocket.Connected)
{
//make a byte array and receive data from the client
Byte[] receive = new Byte[64];
int i = mySocket.Receive(receive, receive.Length, 0);
char[] unwanted = { ' ', ' ', ' ' };
string rece = System.Text.Encoding.ASCII.GetString(receive);
label1.Text = rece.TrimEnd(unwanted);
}
}
}
this two buttons i have added in the same form and Ip apddress which is mentioned is my systems IP Address. Can anyone tell me why this Happen. Even I remove firewall setting also.
First of all your UI will hang on button 2 click because it's stuck on the while(true) loop so use BeginAcceptSocket(IAsyncResult r, Object state) for async.
Second you must use the loopback address or otherwise the firewall should block the port 10 assuming that it's not open. Also the TcpListener(int port) is obsolote and its better to use the TcpListener(IPAddress localddr, int port) and use both the loopback address.
I'm assuming you have two different programs and one is listening while the other is sending. If you don't, separate them out. I'm thinking you have a networking issue but can't say precisely why it's blocked.
You're using port 10, which generally is too low for arbitrary application uses even if it's not currently occupied. If you're building a custom protocol, try to listen on a port above approximately 1000 (more a rule of thumb). You can look here http://technet.microsoft.com/en-us/library/cc959828.aspx or google for "tcp well known ports" for more details and to ensure you don't have a collision.
Try running your TCP listener, then open a command prompt and typing the following
telnet localhost 10
or use the port number you change 10 to. I tried your code and was able to connect to port 10 without issue. If you don't have the "telnet" program you can turn the feature on in your Windows. (search "feature" and choose "turn windows feature on or off" then turn "Telnet Client" on)
If the telnet program connects, you'll know that the issue isn't connectivity related. If the telnet program fails to connect then you'll know something is still blocking that port. Try a different port and re-test connectivity. Once telnet connects, you can then focus on the TCP client portion of your program.
I have a piece of hardware that I'm connecting to using the .NET SerialPort class over RS232.
According to its documentation it doesn't support any type of flow control.
I can write queries and commands to the device, for the queries it'll respond immediately to a read, and if echo is on for the device and I have to do a read after writing a command then the command writes work fine too. The commands and responses are a maximum of 7 characters.
However if echo is off and I write 2 commands in quick succession the second one isn't carried out, unless I put in a Thread.Sleep(15) between the writes, presumably replicating the time it takes to do the ReadLine when echo is on.
I can't necessarily guarantee that echo will be on, and explicitly turning it on isn't really an option either, so I basically need to handle the behaviour as I find it.
The SerialPort is set up as follows:
SerialPort _serialPort = new SerialPort
{
PortName = "COM1",
BaudRate = 9600,
Parity = Parity.None,
DataBits = 8,
ReadTimeout = 5000,
WriteTimeout = 5000,
NewLine = "\x0D"
};
And I'm using WriteLine and ReadLine to communicate with it.
Sleeping the thread feels like a hack, and I haven't found an alternative with all my googling.
So, have I missed something, is there some way I can check when the next command write to a serialport can be carried out or is Thread.Sleep pretty much my lot?
http://msmvps.com/blogs/coad/archive/2005/03/23/SerialPort-_2800_RS_2D00_232-Serial-COM-Port_2900_-in-C_2300_-.NET.aspx
Set handshake property to RTSCTS and handle the PinChanged event when CTS becomes true?
Lines marked ‘Output’ in the table can be set by the serial port to a high or low state (True or > > False) and the ‘Input’ lines can be read as high or low. You can use the PinChanged event to be > > notified when one of the input pins changes. The Handshake property can be set to use RTS/CTS > > > (uses hardware control lines) or XON/XOFF (uses software) or both.
Control Line Name DB9 Pin SerialPort Property I/O
DTR Data Terminal Ready 4 DtrEnable Output
RTS Request to Send 7 RtsEnable Output
CTS Clear to Send 8 CtsHolding Input
DSR Data Set Ready 6 DsrHolding Input
CD (or DCD) Data Carrier Detect 1 CDHolding Input
Unfortunately due to the lack of support in my system for flow control Thread.Sleep seems to be the solution.
I've set up my code so that it checks to see if echo is on and then if it is it just uses the ReadLine, and if it's off then it uses a Thread.Sleep(15).
It feels nasty, but it works reliably, so I'm just having to go with that.
I was just having a similar problem. Using a low baud rate I was attempting to write commands to the port too fast (apparently the "write" command returns before the write is finished).
I solved this by modifying the "Serial Port Ready?" function I call before each command. I added a while loop to sleep for 5ms while the "BytesToWrite" property was greater than zero. Worked fine after that.
The objectve is to find which Serial port is phyisically connected to other machine. I want to Search my system to find the available serial ports and send a test message using all the ports and wait for the response. And get the port numbers of Which ever ports get a response is connected to the other machine. How to do?? Thanks.
The SerialPort.GetPortNames() method returns an array of the COM port names of all available serial ports. You could iterate it and try to Open() them. Expect failure, the port might already be opened by another program.
You don't want to send something to a device that doesn't expect it. Using the DsrHolding property is a reasonable test to see if a device is attached that's powered up.
Your ultimate nemesis is going to be the Baudrate property. You cannot guess the proper value. Serial ports are way too primitive to support plug-and-play style device discovery. Avoid using something that cannot work reliably, allow you user to configure your program with the settings you need. It is the normal practice.
Use System.IO.Ports.
public static void OnSerialDataReceived(object sender,
SerialDataReceivedEventArgs args)
{
string data = ComPort.ReadExisting();
Console.Write(data.Replace("\r", "\n"));
}
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.Handshake = Handshake.None;
ComPort.DataReceived += OnSerialDataReceived;
ComPort.Open();
}
more on Mark Michaelis' blog
SerialPort.GetPortNames() method is static methods for SerialPort .Do you sure communication between them have flow control?
I'm trying to send a sms via a Nokia phone over serial which is easy enough via putty. The commands from the nokia documentation works fine.
However, trying to send the same commands from a c# application fails miserably. I've run Sysinternals PortMon and can see the commands come through OK, the only difference I can see is in the way it connects but I am having trouble finding the commands that would iron out those differences.
The code I'm running looks a little bit like this
using (SerialPort port = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One))
{
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
//port.ReceivedBytesThreshold = 1;
port.DtrEnable = true;
port.RtsEnable = true;
port.ReadTimeout = 1;
port.Handshake = Handshake.XOnXOff;
try
{
port.Open();
port.WriteLine("AT");
port.WriteLine("AT+CMGF=1");
port.WriteLine("AT+CMGS=\"" + number + "\"");
port.WriteLine(message);
port.Write(new byte[] { (byte)26 }, 0, 1);
}
finally
{
if (port.IsOpen)
{
port.Close();
}
}
The differences I'm seeing in the trace from the serial port are
At the start
0.00001844 aspnet_wp.exe IOCTL_SERIAL_SET_HANDFLOW USBSER001 SUCCESS Shake:1 Replace:43 XonLimit:4096 XoffLimit:4096
And at the very end
0.00061153 aspnet_wp.exe IOCTL_SERIAL_PURGE USBSER001 SUCCESS Purge: RXABORT RXCLEAR
0.00004442 aspnet_wp.exe IOCTL_SERIAL_PURGE USBSER001 SUCCESS Purge: TXABORT TXCLEAR
Has anyone got any tips on how to iron out these issues? I also notice that the phone is not responding back to the application with any acknowledgement when I issue a command so I suspect the problem is with the connection, not those messages at the end.
Try to see if you can read out the serial communication from the phone. After you send 'AT', the phone should respond with 'OK'. It might be a good idea to verify that the serial communication is working before taking on the SMS bit.
From what I remember, I think that after AT+CMGS the message should be entered and followed by ctrl-z, and no newline is needed. Could you try changing the WriteLine(message) to Write(message)?
Hope this helps!
You need to wait for the ">" before writing out the message. Also, don't terminate the message with a CR/LF (WriteLine).