hello i have problem with receiving data from serial port in c# in am inserting a new line operator at the end of data buffer. then i send this data buffer on serial port, after this my c# GUI receiver will take this data via Readline() function but it always give me raw data not the actual one how to resolve this problem.
//configuring the serial port this code in c# with problem
serialPort.PortName = "COM1";
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
//opening the serial port
if(!serialPort.IsOpen)
serialPort.Open();
//read 2byte data for msG code from serial port
string strReadData=serialPort.ReadLine();
char[] temp=new char[350];
//strReadData.CopyTo(1, temp, 0, strReadData.Length - 2);
//strReadData = temp.ToString();
//string strReadData = serialPort.ReadExisting();
//strReadData.Replace(' ', '\0');
//strReadData.Replace(' ', '');
byte[] RecievedData = Encoding.ASCII.GetBytes(strReadData);
RecievedDataDecoder(RecievedData);
//close the port
if(serialPort.IsOpen)
serialPort.Close();
but my c++ receiver is working perfectly i dont know what is the problem here is working c++ code
// variables used with the com port
BOOL m_bPortReady;
HANDLE m_hCom;
DCB m_dcb;
COMMTIMEOUTS m_CommTimeouts;
BOOL bWriteRC;
BOOL bReadRC;
DWORD iBytesWritten;
DWORD iBytesRead;
DWORD dwCommEvent;
DWORD dwRead;
char sBuffer[128];
m_hCom = CreateFile("Com1",
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security
OPEN_EXISTING,
0, // no overlapped I/O
NULL); // null template
m_bPortReady = SetupComm(m_hCom, 128, 128); // set buffer sizes
m_bPortReady = GetCommState(m_hCom, &m_dcb);
m_dcb.BaudRate = 9600;
m_dcb.ByteSize = 8;
m_dcb.Parity = NOPARITY;
m_dcb.StopBits = ONESTOPBIT;
m_dcb.fAbortOnError = TRUE;
m_bPortReady = SetCommState(m_hCom, &m_dcb);
m_bPortReady = GetCommTimeouts (m_hCom, &m_CommTimeouts);
m_CommTimeouts.ReadIntervalTimeout = 50;
m_CommTimeouts.ReadTotalTimeoutConstant = 50;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 10;
m_CommTimeouts.WriteTotalTimeoutConstant = 50;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 10;
m_bPortReady = SetCommTimeouts (m_hCom, &m_CommTimeouts);
if (!SetCommMask(m_hCom, EV_RXCHAR))
{
printf("Error in set comm mask");
}
while(1)
{
if (WaitCommEvent(m_hCom, &dwCommEvent, NULL))
{
if (ReadFile(m_hCom, &sBuffer, 128, &iBytesRead, NULL))
printf("");
else
{
printf("Error in reading");
break;
}
}
else
{
printf("Error in Waiting");
break;
}
printf("%s",sBuffer);
strcpy(sBuffer,"");
}
CloseHandle(m_hCom);
getch();
exit(0);
Your question is a bit vague, but the ReadLine() method will return when the port receives a carriage return and line feed byte combination by default on Windows. Or \r\n, or 0x0d 0x0a if you prefer.
If the 'buffer' you are sending in the fist place contains several messages delimited by \r\n, then ReadLine() will only return the first one, then the port will close in the C# code you have posted.
Maybe your code is in a loop, but it is not shown.
Beyond that, after any data that you have received, your are converting it back to an array of bytes, determined by ASCII encoding. Are you sending ASCII in the first place? If not, it is likely that you could be missing information.
Also, if all you do is convert the received string into bytes, you could just receive the data as bytes in the first place.
I think you need to explain in a bit more detail exactly what is in the buffer you are sending, and what exactly do you receive.
Most of my serial port errors are caused by bad baude rate settings. This might be your problem too. (You can set the baude rate in some constructors of the SerialPort class, or with the BaudRate property)
Related
My goal is pretty simple: I wanna read information from my RadioLink R12DS receiver by S-BUS protocol using desktop console application, written on C#.
I use AT9S transmitter blinded together with receiver in 12 channel mode. I tested it on Pixhawk flight controller. Everything was fine there, no any problem with retrieving data.
I designed a console application based on investigated articles. Here is a couple most valuable of them:
http://forum.fpv.kz/topic/303-frsky-x8r-sbus-v-cppm-konverter-na-arduino/ https://github.com/bolderflight/SBUS
My application receiving byte stream from a COM Port, one by one, and tries catch message header "0x0F", but it doesn't appear.
The SBUS protocol uses inverted serial logic with a baud rate of 100000, 8 data bits, even parity bit, and 2 stop bits. The SBUS packet is 25 bytes long consisting of:
Byte[0]: SBUS Header, 0x0F
Byte[1-22]: 16 servo channels, 11 bits per servo channel
Byte[23]:
Bit 7: digital channel 17 (0x80)
Bit 6: digital channel 18 (0x40)
Bit 5: frame lost (0x20)
Bit 4: failsafe activated (0x10)
Bit 0 - 3: n/a
Byte[24]: SBUS End Byte, 0x00
A table mapping bytes[1-22] to servo channels is included.
Here is listing of my code:
static void Main(String[] args)
{
var availablePorts = SerialPort.GetPortNames();
using(var port = new SerialPort(availablePorts[0], 100000, Parity.Even, 8, StopBits.Two))
{
port.DataReceived += PortOnDataReceived;
while(true)
{
if(!port.IsOpen)
TryReconnect(port);
Thread.Sleep(1000);
}
}
}
// HANDLERS ///////////////////////////////////////////////////////////////////////////////
private static void PortOnDataReceived(Object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
var serialPort = (SerialPort)sender;
if(SbusConverter.TryReadMessage(serialPort, out var messageBuffer))
{
var message = SbusConverter.Convert(messageBuffer);
Console.WriteLine(message.ServoChannels[0]);
}
}
public static Boolean TryReadMessage(SerialPort serialPort, out Byte[] messageBuffer)
{
const Int32 messageLength = 25;
const Int32 endOfStream = -1;
const Byte sBusMessageHeader = 0x0f;
const Byte sBusMessageEndByte = 0x00;
messageBuffer = new Byte[messageLength];
if(serialPort.BytesToRead < messageLength)
return false;
do
{
var value = serialPort.ReadByte();
if(value == endOfStream)
return false;
if(value == sBusMessageHeader)
{
messageBuffer[0] = (Byte)value;
for(var i = 1; i < messageLength; i++)
{
messageBuffer[i] = (Byte)serialPort.ReadByte();
}
if(messageBuffer[0] == sBusMessageHeader &&
messageBuffer[24] == sBusMessageEndByte)
return true;
}
} while(serialPort.BytesToRead > 0);
return false;
}
I have thoughts in my head and I want ask one question here.
It's possible, that RadioLink use different, modified or their own S-BUS implementation, than Futaba and I found no proper documentation yet.
Anybody, who experienced in that field, any suggestions please. It seems, I am stuck.
Thank you!
I made some investigations of received data stream and uncovered that RadioLink devices uses "0x1F" as a frame start byte insted of "0x0F". Another connection and message properties are the same.
var availablePorts = SerialPort.GetPortNames();
using(var port = new SerialPort(availablePorts[0], 100000, Parity.None, 8, StopBits.One)
{
Handshake = Handshake.None
})
{
port.DataReceived += PortOnDataReceived;
while(true)
{
if(!port.IsOpen)
OpenPort(port);
Thread.Sleep(1000);
}
}
Two years too late, but I just noticed you have 1 stop bit set, instead of 2, in the code of your answer. That could probably explain 0x1F instead 0x0F and otherwise shifted data.
I am trying to do the same kind of operation, intercepting Sbus signal from a herelink radio controller, so far I discovered a shift in the data and my start byte is recognised with the value of 0x1E. Moreover the data seems super noisy when looked at the oscilloscope, some 1 might be missing because of the poor quality of the signal and the ramp from 0 to 1.
I am new to C# and programming in general.
I am trying to communicate with a ohmmeter which is conneted via usb to my computer.
I am able to configurate the device and even recieve data.
But i can not acces this data. I can just print it on to the console.
(Was inspired by the code on the microsoft site)
Here is the constructer of my "communication"-class where i configurate the port:
public SCPI_Commands()
{
_SerialPort.PortName = SetPortName(_SerialPort.PortName);
_SerialPort.BaudRate = 115200;
_SerialPort.Parity = Parity.None;
_SerialPort.DataBits = 8;
_SerialPort.StopBits = StopBits.One;
_SerialPort.Handshake = Handshake.None;
_SerialPort.ReadTimeout = 500;
_SerialPort.WriteTimeout = 500;
_SerialPort.Open();
_SerialPort.DataReceived += _serialPort_DataReceived;
}
Here is my function which sends a query to the device (The constant Measurment_Value represents a scpi command which is understood by my ohmmeter) :
public void get_measurement()
{
_SerialPort.WriteLine(Measurment_Value);
}
And here is the private function which checks if the device is sending data and printing it on the console (not sure how this function works) :
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.WriteLine(_SerialPort.ReadLine());
}
Unfortunately i am not able to return the data as a string. My goal is to do some calculations with the received data.
Does someone has any ideas ?
Greetings from Germany.
Luke
You can read from buffer to temp byte array and then get it as string, see the below example. Put this in _serialPort_DataReceived
// this the read buffer
byte[] buff = new byte[9600];
int readByteCount = _serialPort.BaseStream.Read(buff, 0, _serialPort.BytesToRead);
// you can specify other encodings, or use default
string response = System.Text.Encoding.UTF8.GetString(buff);
Side Note
If you want to keep your sanity while working with SerialPort, always send and receive as byte array. Then, get the equivalent string using Encoding.
The problem is, that I can trigger scanner using Serial Port software "Hercules" sending command <SYN>T<CR><LF>, in datasheet is said to use command [SYN]T[CR] to trigger scanner, but I cant trigger it (both commands) using my serial port comunication bellow.
I get input when use scanner manually but can't trigger it... What is a problem?
(The port is virtual)
private static SerialPort port;
private static bool _continue = false;
public static void Main(string[] args)
{
port = new SerialPort();
port.PortName = "COM8";
port.BaudRate = 115200;
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Handshake = Handshake.None;
port.RtsEnable = true;
port.DtrEnable = true;
port.ReadTimeout = 500;
port.WriteTimeout = 500;
port.Open();
_continue = true;
Thread thr = new Thread(SerialPortProgram);
thr.Start();
}
private static void SerialPortProgram()
{
Console.WriteLine("Writing to port: <SYN>T<CR><LF>");
string command = "<SYN>T<CR><LF>";
port.WriteLine(command);
while (_continue)
{
try
{
string input = port.ReadLine();
Console.WriteLine("Input is - " + input);
}
catch (TimeoutException) { }
}
}
Python barcode scanner serial trigger is an article that I answered similar Python question.
The contents are shown below.
This happens because you coded the abstract expression written in the document as raw output data.
The document represents 3 bytes of data transmission.
'SYN' and 'CR' are the following hexadecimal numbers.
'SYN' = \x16
'CR' = \x0d or escape sequence \r
'T' is an ordinary ASCII character.
Whitespace and < > [ ] { } are used to delimit the data in the document, not the data to send.
And, even you need to command prefix it.
Also use Write instead of WriteLine as written by #Turbofant.
You should write like this. Please try it.
string command = "\x16M\x0d\x16T\x0d";
port.Write(command);
I guess the problem is, that you are sending the wrong command string.
The <Syn>, <CR> and <LF> stands for the special, non printable ascii characters synchronous idle, Carriage return and line feed.
You need to encode them correctly in the string
Try sending:
string command = "\x16t\r\n";
port.Write(command);
\x16is <Syn> (Because Syn is ascii character 0x16, or 22 in decimal )
\r is <CR>
\n is <LN>
And use port.Write instead of port.WriteLine, because WriteLine automatically adds the \r\n at the end of the string.
I have tried the following:
(This "whatever" is a 4 digit pin asked to enter after sending a AT+STGR=3,1 to the port)
1. this.port.WriteLine("whatever\0x1A");
2. this.port.WriteLine("whatever"+ char.ConvertFromUtf32(26));
3. this.port.WriteLine("whatever\u0001");
4. this.port.WriteLine("whatever"+(char)26);
5. this.port.WriteLine("whatever");
SendKeys.Send("^(z)");
6. this.port.WriteLine("whatever");
this.port.Write(new byte[] { 0x1A }, 0, 1);
7. this.port.WriteLine("whatever");
this.port.Write(new byte[] { 0x26}, 0, 1);
None of them works, but when using putty and entering the code followed by ctrl+z key everything works perfectly, so can anyone tell me exactly how does putty sends this ctrl+z to the serial port? Or if possible give a solution to this problem in c#?
The reply back from the modem every time I try the c# codes given above is:
+CME ERROR: 100
Serial Port Initialization:
port.PortName = "COM3";
port.BaudRate = 115200;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReadTimeout = 300;
port.WriteTimeout = 300;
port.Encoding = Encoding.GetEncoding("iso-8859-1");
port.DataReceived += new SerialDataReceivedEventHandler(this.port_DataReceived);
port.Open();
port.DtrEnable = true;
port.RtsEnable = true;
Find a ASCII map like this for the ctrl codes. Looks like for ctrl Z you need an ASCII 0x26. I would define it something like
char CtrlZ = (char)26;
char CR = (char)13;
serialport1.WriteLine(string.Format("whatever{0}{1}",CtrlZ, CR));
Try "whatever\u001A" or "whatever" Sleep "\u001A".
Also check the whole sequence of commands/responses you're sending/receiving through the connection.
This is an example, to be adapted to your specific case.
//TODO initialize the serialConnection and open it
//TODO specific commands...
serialConnection.WriteLine("AT+CPIN=\"1234\""); // replace according to your real situation
var response = serialConnection.ReadExisting();
Console.WriteLine("pin resp: " + response);
Thread.Sleep(200);
//TODO other specific commands?
serialConnection.Write("whatever");
//Thread.Sleep(200); uncomment this if it helps
serialConnection.Write(new byte[]{26}, 0, 1); // or Write("\u001A")
response = serialConnection.ReadExisting();
Console.WriteLine("ctrl-z resp: {0}", response);
//closing stuff, etc...
I am trying to send a word over to an Arduino running as a server, from a WPF C# application. Every now and again the complete work is not sent.
C# Code
public void send(String message)
{
TcpClient tcpclnt = new TcpClient();
ConState.Content = "Connecting.....";
try
{
tcpclnt.Connect("192.168.0.177", 23);
ConState.Content = "Connected";
String str = message;
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
stm.Write(ba, 0, ba.Length);
tcpclnt.Close();
}
catch (Exception)
{
ConState.Content = "Not Connected";
return;
}
}
How it is sent to the method:
String mes = "back;";
send(mes);
Arduino code:
if (client.available() > 0) {
// Read the bytes incoming from the client:
char thisChar = client.read();
if (thisChar == ';')
{
//Add a space
Serial.println("");
}
else {
//Print because it's not a space
Serial.write(thisChar);
}
}
The Arduino is using the chat server example. I am sending "back;" and "forward;" across. The results on the serial monitor:
back
forwaback
forward
back
forwaforwar
The problem seems to be with this code:
if (client.available() > 0) {
// read the bytes incoming from the client:
char thisChar = client.read();
...
}
What it does is:
Check if we have received data from the client
Read a single byte from the client buffer
Exit, and go on to do other things
As the OP pointed out, this comes direct from Arduino chat server example. In that example, this working correctly in loop() depends on the alreadyConnected flag being set right after a new connection is made: if it isn't, then the buffer is flushed before any data is read. That's one possible landmine.
Nonetheless, there is no reason to change the if block to be a while loop in the OP's case so, in other words instead of
if (client.available() > 0) {
have
while (client.available() > 0) {
The only reason to have an if statement there is to make sure that you frequently do other processing in loop() if you have clients that send a lot of data: If the reading of client data is done from inside a while this loop will not exit until the there is no more data from the client. Since this doesn't seem to be an issue in the asked-about case, the if to while change makes sense.