When i read the serial port using c# in a console application, this is the output i get.
Does anyone know how i should read this data so it's readable by a human.
The data that should be received is like : 6025 1045 1806 116 0000000 and GPS coördinates.
I know its a bit vague, but i am new to serial port programming and would like to know how to move on.This is the code i have so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Diagnostics;
using System.Threading;
using System.IO;
namespace ClarityListener
{
class Program
{
static void Main(string[] args)
{
ClarityWarning("Starting communication...");
SerialPort Dave = new SerialPort("COM1");
Dave.BaudRate = 9600;
Dave.Parity = Parity.Odd;
Dave.DataBits = 8;
Dave.StopBits = StopBits.One;
Dave.Handshake = Handshake.None;
Dave.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
try
{
Dave.Open();
ClarityMssg("Connected!\n");
}
catch
{
ClarityError("Problem!\n");
}
ClarityWarning("Press any key to shutdown program");
Console.WriteLine();
Console.ReadKey();
Dave.Close();
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
ClarityWarning("Data received : ");
ClarityWarning(indata.ToString() + "\n");
}
private static void ClarityMssg(string message)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.White;
}
private static void ClarityError(string message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.White;
}
private static void ClarityWarning(string message)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.White;
}
}
}
Data received over a channel is a stream of bytes, being it over tcp/ip or serial or read from a file. Programming against a serial port is not that different/difficult as there is no hitech black magic involved.
Just dumping the received bytes to the console assuming that it is ascii is not the way to go. Although it can give you a head-start in determining what's send.
First check the parameters set on the receiving serial-port. Most devices are using 9600 baud, no parity, 8, 1 stopbit. If there is a mismatch data gets mangled. Check the specs from the manual of the device.
Do you know in what format the data is send? Are numbers converted to ascii literals before sending or are they send as int32 in 4 bytes?
What is the flow control of the source?
Are there control/command bytes in or between the messages?
In short: know the protocol used by the sender. Check the documentation and as a last resort call the vendor / distributor.
First things that come to mind :
make sure the parity, stop bits and baud rate of your serial port reader are configured to match the requirements of the device sending the data.
Also make sure your serial device is indeed sending ASCII encoded text.
(this is the standard for NMEA, a protocol mostly used for devices like this, but there is no guarantee your device adheres the the standard 100%)
Related
I am using C# Console app to interact with firmware on sas Expander card.
It was connected by RS232 Serial Port.
Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Threading;
namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
[STAThread]
static void Main()
{
SerialPort mySerialPort = new SerialPort("COM5");
mySerialPort.BaudRate = 115200;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DtrEnable = true;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 1000;
mySerialPort.Open();
if(mySerialPort.IsOpen)
{
mySerialPort.Write("\r");
}
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
while (true)
{
string userResponse = Console.ReadLine();
if (userResponse == "sys")
{
mySerialPort.Write("sys\r");
}
else if (userResponse == "counters")
{
mySerialPort.Write("counters\r");
}
else if (userResponse == "phyinfo")
{
mySerialPort.Write("phyinfo\r");
}
else if (userResponse == "? -a")
{
mySerialPort.Write("? -a\r");
}
else
{
mySerialPort.Write("\r");
}
}
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.Write(indata);
}
}
}
What the app execute command counters result:
Using PuTTy by sending command counters result:
You can see counters will show up on the app page
and counters won't show up in PuTTY's page.
What should I do to let my code result just like PuTTY does?
How to hide some return data from Serial Port?
My C# Console app is using .Net Framwork 4.7.2.
.....................................................
Update:
After I add mySerialPort.ReadChar(); in code,
the code looks like:
string userResponse = Console.ReadLine();
if (userResponse == "sys")
{
mySerialPort.Write("sys\r");
mySerialPort.ReadChar();
mySerialPort.ReadChar();
mySerialPort.ReadChar();
}
and the result is:
I am not satisfied with this result
because there are at least twenty command in firmware.
I don't want keep adding mySerialPort.ReadChar() in every condition.
Is there another way to fullfill my goal?
.......................................................
Update Part2:
After adding string echocancel = sp.ReadLine(); in DataReceivedHandler,
the code looks like:
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string echocancel = sp.ReadLine();
string indata = sp.ReadExisting();
Console.Write(indata);
}
and the result looks like:
After product identity :'s word should have default
and between product Identity and <<Alarm status>>
should have space, it should show up.
At least, sys , this three character won't show up again.
Did someone has some solution about it?
Seems like a situation of double echo of keyboard input.
By default the typical terminal emulation program (e.g. minicom) disables local echo for keyboard input; apparent putty does the same.
So when the attached device does echo the typed input, you only see one copy of the input displayed.
(Because of this default mode, you will not see what you type when the attached device also has its echo inhibited.)
With your program, characters typed as input on keyboard are echoed locally to your display, and when transmitted that line is echoed by the attached device and then displayed (by your program) as part of the response.
You can verify this hypothesis by changing your code to accept a foo command instead of counters:
...
else if (userResponse == "foo")
{
mySerialPort.Write("counters\r");
}
...
The expected display should then be something like
bp1 >foo
counters
...
Possible solutions are:
a. disable echo from the device (preferred), or
b. disable local echo, or
c. echo cancellation.
Echo cancellation can be simplified in your program because each command transmitted seems to be a line terminated by a carriage return. So instead of absorbing individual characters as you did for an individual command, you only need a single read of a line to absorb the echoed line:
while (true)
{
string userResponse = Console.ReadLine();
if (userResponse == "sys")
...
else
{
mySerialPort.Write("\r");
}
/*
* might need a delay here allow serial output to drain/complete
* and give device time to respond
*/
string echocancel = mySerialPort.Readline();
}
However such echo cancellation would also require proper setting of the line-terminator character, i.e. mySerialPort.NewLine = "\r";
See
https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.newline?redirectedfrom=MSDN&view=dotnet-plat-ext-5.0#System_IO_Ports_SerialPort_NewLine
Note that disabling echo from the device is the standard mode for (serial) communication with a device by software (i.e. machine to machine). This simply reduces the amount of data transferred. Echo is only enabled for the convenience of humans.
What is the local echo in my code? Console.ReadLine()?
For Linux, minicom disables local echo by configuring termios flags for stdin (aka the keyboard).
Seems like you're using Windows, so I don't know the equivalent operation.
Yes, the local echo should be occurring during the Console.ReadLine().
Addendum in response to Update Part2
My suggestion for echo cancellation guarantees that only one line of input would be discarded per command sent.
Your modification differs from my suggestion in order to keep all serial port reads within a single procedure/handler.
However that could introduce a synchronization issue, because now you have to ensure that DataReceivedHandler() is performed only once per iteration of the while loop that receives userResponse.
But there seems to be absolutely nothing in that while loop that could enforce any synchronization with DataReceivedHandler().
Prior to this echo cancellation modification, your program really didn't have to rely on any synchronization. Since DataReceivedHandler() simply displayed whatever it received, this data transfer seems flawless, and you weren't concerned about how indata aligned with the text of the response.
To test this synchronization hypothesis, report the line(s) that is/are being discarded for echo cancellation, e.g.
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string echocancel = sp.ReadLine();
Console.WriteLine($"DEBUG: {echocancel}");
string indata = sp.ReadExisting();
Console.Write(indata);
}
In practice echo cancellation is probably the method of last choice in comparison to simply avoiding the generation of the echo. Some schemes validate the received data prior to discarding (e.g. using a FIFO of expected echo data) to ensure the cancellation is accurate.
I have this Arduino code just for testing purpose:
int num=0;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(num);
num+=1;
delay(800);
}
Now it prints an integer and increments its value by one. When I open up Serial Monitor it prints as expected every 800ms.
My Arduino is connected on PORT-6
Now if I try to access the port, it says it is in use, I'm trying to access that from a .NET application. How can I do so?
c# code, collected from the internet, modified a little:
using System;
using System.IO.Ports;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static SerialPort _serialPort;
public static void Main()
{
_serialPort = new SerialPort();
_serialPort.PortName = "COM6";//Set your board COM
_serialPort.BaudRate = 9600;
_serialPort.Open();
while (true)
{
string a = _serialPort.ReadExisting();
Console.WriteLine(a);
}
}
}
}
How can I sniff data from that serial port ? [Educational Purpose]
You can't open a serial port twice.
If what you want is to get to see what is going through the bus (sniffing), you can use virtual ports and port forwarding, see here for a complete example.
Nothing will stop you from replacing any of the tools discussed in the link with your own code (.NET or other), in case they don't suit your needs or if you have enough determination to reinvent the wheel.
I'm working on a C# program that is basically a char sequence's listener in a SerialPortwhich is connected to a FT2232H.
The sequence should start with an arbitrary char and has an arbitrary lenght.
The problem is not that I don't have the correct pattern I expected, the problem is that I don't have the chars I passed into the chip at all, and sometimes they're mixed with other bytes I'm sure to not have passed to the chip!
Even coding this char by char reader didn't help me to understand what happens inside.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms;
namespace FTDI_VCP
{
class SerialPortProgram
{
int _test_counter = 0;
private string _buffer;
private SerialPort port = new SerialPort("COM11",
9600, Parity.Even, 8, StopBits.Two);
[STAThread]
static void Main(string[] args)
{
new SerialPortProgram();
}
private SerialPortProgram()
{
Console.WriteLine("incoming chars:");
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
Application.Run();
}
private void port_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
if(port.BytesToRead != 0)
{
do {
int byte2read = port.ReadChar();
if(byte2read == 0xFF) //this is my arbitrary char value
{
Console.WriteLine();
}
else
{
Console.Write((char)port.ReadChar());
}
} while (true);
}
}
}
This is the output:
Suppositions:
I think that using a VCP through a FTDI in UART-RS232 mode I am listening directly on the UART buffer however I fear that there are remote possibilities that I'm reading a something else instead of simple chars. Maybe RS232 packets? Maybe another pattern? I don't know. Can anyone help me to understand what happens inside a UART buffer when I'm using a COM port?
Things I've already checked that seems to be okay
Baud rate mismatching
Other devices interferring
FTDI in right mode, I used FT_Prog like this
Thanks for the attention payed. I'm waiting for a FTDI GURU to help me (:
I'm trying to send a string from my arduino(leonardo) to a C# program.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
SerialPort mySerialPort = new SerialPort("COM7");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
mySerialPort.Open();
Console.WriteLine("Press any key to continue...");
Console.WriteLine();
Console.ReadKey();
mySerialPort.Close();
}
static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
}
}
This is my code wich I copied from the msdn example to try and understand what it does.
My arduino code below just sends hello world over te com port with a delay of 1000.
void setup ()
{
Serial.begin(9600);
}
void loop(){
Serial.println("Hello World");
delay(1000);
}
My arduino is using the COM7 like I defined in the C# program. When I run bot programs, The C# program never comes within the datareceived event handler. So no data is received. I really want tis to work :)
Kind regards
I Switched the code to a windows form application, it still was not working. Then i found a topic about serial communication with C# about arduino leonardo
here
I had to do this:
serial.DtrEnable = true;
serial.RtsEnable = true;
I consider my problem as solved.
Console applications do not have a message loop so naturally they don't respond to events. You have one thread and it will be stuck blocking at Console.ReadKey(). Either use synchronous reads from the serial port or, if you wish to stick to an event-based model, move this code to a windows-based applications.
For a synchronous example, see this MSDN example :
while (_continue)
{
try
{
string message = _serialPort.ReadLine();
Console.WriteLine(message);
}
catch (TimeoutException) { }
}
The above is only an excerpt - the full example demonstrates setting up the timeout values, etc.
I am new to netduino so I have a simple question (or, it should be simple).
What I want to do is to send an integer (string) via rs232 from my winform app to my netduino plus 2, and then, my netduino should read that integer and blink an onboard led that many times.
I have read online tutorial on that topic and found some examples that should provide communication between my PC and Netduino.
Yes, I did got an echo from it. I am getting an echo even if I disconnect my netduino and hide it in my pocket :).
So much for my understanding of that gadget.
How can I send an info to my Netduino via rs232 cabel that he can read, understand and act accordingly?
There is a code straight from the the web:
For NETDUINO:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using System.IO.Ports;
namespace NetduinoApplication1
{
public class Program
{
static SerialPort serial;
public static void Main()
{
// initialize the serial port for COM1 (using D0 & D1)
serial = new SerialPort(SerialPorts.COM1, 9600, Parity.None, 8, StopBits.One);
// open the serial-port, so we can send & receive data
serial.Open();
// add an event-handler for handling incoming data
serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);
OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
for (int i = 0; i < 3; i++)
{
led.Write(true); // turn on the LED
Thread.Sleep(250); // sleep for 250ms
led.Write(false); // turn off the LED
Thread.Sleep(250); // sleep for 250ms
}
// wait forever...
Thread.Sleep(Timeout.Infinite);
}
static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// create a single byte array
byte[] bytes = new byte[1];
// as long as there is data waiting to be read
while (serial.BytesToRead > 0)
{
// read a single byte
serial.Read(bytes, 0, bytes.Length);
// send the same byte back
serial.Write(bytes, 0, bytes.Length);
OutputPort led1 = new OutputPort(Pins.ONBOARD_LED, false);
led1.Write(true); // turn on the LED
Thread.Sleep(250); // sleep for 250ms
led1.Write(false); // turn off the LED
Thread.Sleep(250); // sleep for 250ms
}
}
}
}
And the code for my console:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
namespace ConsoleRSS
{
class Program
{
static SerialPort serial;
static void Main(string[] args)
{
// provide some usage information
System.Console.WriteLine("enter some text and hit ENTER.");
System.Console.WriteLine("enter 'x' and hit ENTER to exit.");
System.Console.WriteLine();
// initialize the serial port for COM3 (could be other port, depends on system)
serial = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
// open the serial-port, so we can send & receive data
serial.Open();
// add an event-handler for handling incoming data
serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);
// this will hold each line entered
string line = string.Empty;
// as long as an x is not entered
while (line.ToLowerInvariant() != "x")
{
// read a single line from the console
line = System.Console.ReadLine();
// convert the line to bytes
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(line);
// send the bytes over the serial-port
serial.Write(utf8Bytes, 0, utf8Bytes.Length);
}
}
static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// wait a little for the buffer to fill
System.Threading.Thread.Sleep(100);
// create an array for the incoming bytes
byte[] bytes = new byte[serial.BytesToRead];
// read the bytes
serial.Read(bytes, 0, bytes.Length);
// convert the bytes into a string
string line = System.Text.Encoding.UTF8.GetString(bytes);
// write the received bytes, as a string, to the console
System.Console.WriteLine("echo: " + line);
System.Console.WriteLine();
}
}
}
I'm not sure what problem you are actually getting with this? Your code at first glance looks correct.
I would try checking your hardware first, so is the usb cable actually set as COM 1 in device manager on your pc? Is the cable connected to the correct ports in the netduino?