Sending data through RS232 using C# [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have a device that can communicate trough RS232. and it comes with the communication protocol to access the data.
I'm writing a simple c# program to connect and get the status from the device and Im not quite sure whether Im on the right path.
Below is the sample they have given.
Command 50: status request
The status request command is used to request the register response package, without later actions that may alter the status of the system.
0 1 2 3 4 5 6 7 8 9 10 11 12 13
STX ADDR ADDR CMOD "5" "0" "0" "3" TKN1 TKN0 TYPE CHKL CHKH 0X0D
STX = Start byte of the frame (0x02)
ADDR = TE550 logical address [2 bytes]

CMOD = CMOD to refer [1 byte]
TKN1/0 = Frame identification bytes [2 bytes]

TYPE = Selection byte for customizable box (RiqA/B)* [1 byte]
CHKH/L = Checksum [2 bytes]
END = End byte of the frame (0x0D)
Example:
status request from PC to TE550 (address 01), CMOD 1, Token 01, Type 1
[0x02]0115003011EE[0x0D]
I can connect to the com port using the serial port.
I am referring to the answer by DesMy "RS232 serial port communication c# win7 .net framework 3.5 sp1"
So far Im not getting any signal once write to the COM port. However I'm not quite sure whether Im sending the correct data to the com port. Currently Im sending data as below
comPort.Write("20115003011EE3");
Any help / sample code etc would be much appreciated.
public void ConnectRS232 ()
{
try
{
SerialPort mySerialPort = new SerialPort("COM1");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 500;
mySerialPort.DtrEnable = true;
mySerialPort.RtsEnable = true;
mySerialPort.Open();
mySerialPort.DataReceived += DataReceivedHandler;
mySerialPort.Write("20115003011EE3");
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
}
public void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
System.Threading.Thread.Sleep(500);
string indata = sp.ReadExisting();
this.BeginInvoke(new SetTextDeleg(DisplayToUI), new object[] { indata });
}
private void DisplayToUI(string displayData)
{
textBox1.Text += displayData.Trim();
}

When dealing with low level port I/O, characters are not bytes!
Do not send strings. Create a byte stream containing the correct characters and send that.
[In .NET characters are shorts, not bytes. Doesn't matter. Use bytes.]

Related

C# socket hangs when receive in loop - python as socket server

I'm familiar with C#, and know some python. Recent days I'm learning the book Programming Python, 4th Edition and have run the very basic socket samples: echo-server.py and echo-client.py
They work well on my Windows, python 3.x.
python server:
from socket import *
myHost = 'localhost'
myPort = 50007
sockobj = socket(AF_INET, SOCK_STREAM)
sockobj.bind((myHost, myPort))
sockobj.listen(5)
while True:
connection, address = sockobj.accept()
print('Server connected by', address)
while True:
data = connection.recv(1024)
if not data: break
connection.send(b'Echo=>' + data)
connection.close()
Now I want to learn socket in C# too, so I wrote a C# .net framework 4.5 socket client, expecting to receive and show what echo-client.py does.
I got the C# demo from msdn and made some refactor to reduce code size.
public static void Main(string[] args)
{
string server = "localhost";
int port = 50007;
string request = "GET / HTTP/1.1\r\nHost: " + server +
"\r\nConnection: Close\r\n\r\n";
Byte[] sent = Encoding.ASCII.GetBytes(request);
Byte[] recv = new Byte[256];
IPHostEntry hostEntry = Dns.GetHostEntry(server);
IPEndPoint ipe = new IPEndPoint(hostEntry.AddressList[1], port);
Socket s =
new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
s.Connect(ipe);
s.Send(sent, sent.Length, 0);
int bytes = 0;
string page = "recived:\r\n";
//do
{
bytes = s.Receive(recv, recv.Length, 0);
page = page + Encoding.ASCII.GetString(recv, 0, bytes);
}
//while (bytes > 0);
Console.WriteLine(page);
Console.WriteLine("result");
Console.ReadKey();
}
My test steps:
If I set up a web site using local IIS, such as
http://localhost:801, then above code can show the homepage html
contents, this means my C# code is working.
Run echo-server.py, and change C# code's port to 50007, then run,
nothing output in console, and application does not exit, if I place a break point within the loop, I can see the loop has only run once. The python server did output some log saying C# is connecting.
Comment do while loop(as commented in code), this time the output is exactly same as echo-client.py(expected).
So I'm wondering what's wrong when I'm using do while loop?

Serial Port Request-Response communication using c#

I want to do serial port communication with a machine which uses RS232-USB ports.
I am using serial port class. I am very new to the concept. In my first Machine interfacing I only had to do the serialport.readLine( to get the readings from the machine and there was no need to send ACK /NAK). but for the new machine interface the document says following things:
The following is an example of the RA500 communication:
Computer :<05h 31h 0dh>
RA500 :1st line of information
Computer :<06h 0dh>
RA500 :2nd line of information
Computer :<06h 0dh>
RA500 :”EOF”<0dh>
What i understood from this is i have to write to comport before reading from it. this is what i am doing in my code:
ACK = "06 0d"; NAK = "15 0d"; str = "05 31 0d";
while (count <= 5)
{
rx = ComPortDataReceived(str);
if (!string.IsNullOrEmpty(rx))
{
str = ACK;
returnReading += rx;
}
else if (string.IsNullOrEmpty(rx)) str = NAK;
count++;
}
private string ComPortDataReceived(string str)
{
string Rx = string.Empty;
string exceptionMessage = string.Empty;
try
{
byte[] bytes = str.Split(' ').Select(s => Convert.ToByte(s, 16)).ToArray();
comPort.Write(bytes, 0, bytes.Length);
Rx = comPort.ReadExisting();
PEHRsLibrary.writeTextFile(DateTime.Now + " RxString :" + Rx);
return Rx;
}
catch(Exception e){}
when i use this code i am receiving empty strings as responce. but if i use comPort.ReadExisting() only without using comPort.Write i am receving a string with all the readings but the probblem is it only gives one line of information and dosnt give 2nd or 3rd line readings.
when i try using comPort.ReadLine() after Write() I am getting Timeout exception.
i dont know what i am doing wrong in this case. I am writing ACk after receving 1st line but not receving 2nd line. Next thing i am gonna try is read() as byte and then convert it to string instead of using ReadExisting(). Any other way i can do this?

Serial.WriteLine("My message!"); Appending?

I am trying to send a message from a C# application to my arduino on the serial port.
However it hangs on the WriteLine. It never ends and when I read whats been stored in my buffer on the arduino it's like ive been sending it over and over 100 times.
Code on c# app
public void testSend()
{
if (mySerialPort.IsOpen)
{
//setup
//mySerialPort.Open();
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.WriteTimeout = 500;
try
{
mySerialPort.WriteLine("Sent from my c# app!");
}
catch(TimeoutException)
{
//Console.WriteLine("Timeout while sending data");
}
//mySerialPort.Close();
}
else
{
Console.WriteLine("Port already open!");
}
}
Code on arduino(for reference and clearance )
void setup()
{
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB
}
}
char* buf = malloc(1024);
int ReciveData()
{
if (Serial.available())
{
// read the incoming bytes:
String temp = Serial.readString();
if (temp.length() > 0)
{
temp.toCharArray(buf, temp.length() + 1);
}
}
}
void loop()
{
Serial.print("Sent from arduino!");
Serial.println(buf);
delay(1000);
ReciveData();
}
}
This is how it looks. Here is 4 messages, every send start with "Sent from arduino!". when i read it. You can see on line 1 and 2 everything is good but when I start the c# application and it goes Hawaii
Sent from arduino!Sent from serial terminal!
Sent from arduino!Sent from serial terminal!
Sent from arduino!Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from arduino!Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Sent from my c# app!
Not sure why. But when i tried to add \0 at end of the string it worked.
try
{
mySerialPort.WriteLine("Sent from my c# app! \0");
}
In c \0 is the string terminator character. Without it the read won't know the characher array has ended.
The mySerialPort.WriteLine method would send the string you specified + the mySerialPort.NewLine value, which in your case is the default value - System.Environment.NewLine (which is "\r\n").
Before the usage of WriteLine (and also ReadLine) - specify the protocol EOL character, in your case:
mySerialPort.NewLine = "\0"
And there will be no need to add manually the EOL character on each writing (and to miss the purpose of WriteLine over just Write)

usb to serial not working

This is my first time integrating Serial to USB in a C# application, so please pardon me if this sounds like a stupid question.
I have Class IV laser. I am integrating that in to my C# application.
My problem is I can connect to the laser, I can send data to the laser but i don't get any return from the laser.
private void Bt_Start_Click(object sender, EventArgs e)
{
SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
serialPort.Handshake = Handshake.XOnXOff;
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
serialPort.ReadTimeout = 500;
serialPort.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
ConenctToLaser("COM3", serialPort);
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
byte[] buffer = new byte[sp.BytesToRead];
int bytesRead = sp.Read(buffer, 0, buffer.Length);
var message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
MessageBox.Show(message);
}
public void ConenctToLaser(string port, SerialPort serialPort)
{
StreamReader openfile = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\commands.txt");
if (serialPort.IsOpen == false)
{
serialPort.Open();
string command = "";
command = openfile.ReadLine();
while(command!=null)
{
byte[] buffer = Encoding.ASCII.GetBytes(command);
serialPort.Write(buffer, 0, buffer.Length);
command = openfile.ReadLine();
}
}
}
The commands.txt includes my commands. which are
\r
MTT\r
MCM\r
SPR300\r
on different lines
When i send these commands to the laser all i get back is the echo. So in reality when i send ("MTT\r") i should get back the temperature of the hardware. When i test my hardware in putty it works i get return for all the commands above. Here's the definition for one of the commands from the .pdf they have provided.
Laser Temperature Command: MTT\r
Description: The laser actual laser temperature expressed in XX.X degC
After hours of researching I found the answer to my question. From what i read online it seems like the SerialPort class by Microsoft doesn't work very well with all the serial Hardware. So I would need to use a wrapper class to work with Win32 API.
I found this article which explains how to use Win32 class to communicate with the serial device. It also has a wrapper to call the Win32 methods. You can read all about it and download all the code from the below link.
https://msdn.microsoft.com/en-us/magazine/cc301786.aspx
Hope this helps somebody who's having the same problem.

send English SMS with GSM Modems (D-Link DWM-156)

I am developing an application for GSM Modems (D-Link DWM-156) in C#.Net using AT commands. I have a problem sending English SMS.
I try to send "hello", But I receive □□□□ in my phone or ...exept hello.
serialPort1.DataBits = 8;
serialPort1.Parity = Parity.None;
serialPort1.StopBits = StopBits.One;
serialPort1.BaudRate = 9600;
serialPort1.DtrEnable = true;
serialPort1.RtsEnable = true;
serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
serialPort1.WriteLine("AT\r");
Thread.Sleep(2000);
serialPort1.WriteLine("AT+CMGF=1\r");
Thread.Sleep(1000);
serialPort1.WriteLine("AT+CMGS=\"09390149196\"\r")
Thread.Sleep(2000);
serialPort1.WriteLine("hello" + "\x1A");
Thread.Sleep(1000);
Few fixes (maybe more but I don't see full-code).
Do not use WriteLine() but Write() because for \r (alone) is the command line and result code terminator character.
SerialPort.WriteLine() by default writes a usASCII encoded string but your GSM modem expect strings encoded as specified with an AT command. Set SerialPort.Encoding property to a specific encoding and send CSCS command. You can ask supported encodings with CSCS=? AT command. Even if default GSM should apply I'd avoid to rely implicitly on this.
You do not need to wait after each command but you have to wait for modem answer (checking for OK or ERROR strings).
From docs:
A command line is made up of three elements: the prefix, the body, and the termination character. The command line prefix consists of the characters "AT" or "at" [...] The termination character may be selected by a user option (parameter S3), the default being CR.
In pseudo-code:
void SendCommand(string command) {
serialPort.Write(command + "\r");
// Do not put here an arbitrary wait, check modem's response
// Reading from serial port (use timeout).
CheckResponse();
}
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.BaudRate = 9600;
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
serialPort.Encoding = Encoding.GetEncoding("iso-8859-1");
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
SendCommand("AT"); // "Ping"
SendCommand("AT+CMGF=1"); // Message format
SendCommand("AT+CSCS=\"PCCP437\""); // Character set
SendCommand("AT+CMGS=\"123456\"") // Phone number
SendCommand("hello" + "\x1A"); // Message
To check response (absolutely avoid arbitrary waits!) you can start with something like this (raw untested adaption so you may need some debugging, see also this post):
AutoResetEvent _receive;
string ReadResponse(int timeout)
{
string response = string.Empty;
while (true)
{
if (_receive.WaitOne(timeout, false))
{
response += _port.ReadExisting();
}
else
{
if (response.Length > 0)
throw new InvalidOperationException("Incomplete response.");
else
throw new InvalidOperationException("No response.");
}
// Pretty raw implementation, I'm not even sure it covers
// all cases, a better parsing would be appreciated here.
// Also note I am assuming verbose V1 output with both \r and \n.
if (response.EndsWith("\r\nOK\r\n"))
break;
if (response.EndsWith("\r\n> "))
break;
if (response.EndsWith("\r\nERROR\r\n"))
break;
}
return response;
}
Adding _receive.Reset() just before you send your command and of course also adding OnPortDataReceived as handler for SerialPort.DataReceived event:
void OnPortDataReceived(object sender,
SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
_receive.Set();
}
If you have some trouble (but you can connect) you may replace \r with \n. Some modems incorrectly (assuming <CR> has not been mapped to anything else than 13 using S3 parameter) use this character as command line terminator by default (even if it should be present in output only for V1 verbose output). Either change your code or send appropriate S3.

Categories