I have device that can connect to my laptop via blue-tooth as COM5. The device has a Pulse sensor. I want to draw data coming from sensor to graph. However when i connected to COM5 the serialport_Datarecieved event is not triggered. I tried device using matlab. It takes and draws data but i cant get data in c#. I checked the connection status of device and it is ok. I tried to change DtrEnabled and RtsEnapled properties but not worked.
private void Form1_Load(object sender, EventArgs e)
{
cmbPortList.Items.AddRange(SerialPort.GetPortNames());
cmbPortList.Sorted = true;
cmbPortList.SelectedIndex = 0;
this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort1_DataReceived);
}
private void btnOpenPort_Click(object sender, EventArgs e)
{
try
{
serialPort1.PortName = cmbPortList.Text;
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.ReadTimeout = 500;
serialPort1.WriteTimeout = 500;
serialPort1.Handshake = Handshake.None;
if (!serialPort1.IsOpen)
{
btnRun.Enabled = true;
serialPort1.Open();
}
}
catch (Exception ex)
{
serialPort1.Close();
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
while (serialPort1.BytesToRead > 0)
{
Thread.Sleep(50);
byte[] buffer = new byte[serialPort1.BytesToRead];
serialPort1.Read(buffer, 0, buffer.Length);
}
}
I cant read any data in buffer. There is led is flashing while device is not connected with via blue-tooth. So i am absolutely sure i connected to device.
Is problem about Bluetooth or code? Should i use another library to communicate blue tooth device?
I have read links below.
SerialPort fires DataReceived event after close
SerialPort not receiving any data
This may have less to do with the SerialPort and more to do with the way that Winforms threads are interacting with the serial port's background worker threads. See the solution to this for more info.
I think the designer of the circuit requests data from device with 's'. It must be about its protocol or hex code. I have found that code in matlab sample of circuit % Request Data fprintf(s,'s'); That's why i can read data when i use serialport.Write("Blast"); Also i tried all letters. Only 's' char triggers the event.
Related
After a long time i need to program again.
I need to constantly send a command through serial port from a car ecu(? data).
Then i need to receive that data which i will process to be shown on a display(thinking racing display with car parameters like temperature etc).
I need to do this constantly
I wonder before i start whats best way to do this?
1 thread for constantly asking and receiving data
main thread for showing data in screen.
(store data in buffer and save once a minute or so)
anyone has any tips a guide or so how to start on this.
i tested receiving data with terminal and i got data back so config is working.
sent ? data => i got data back.
You could just use the SerialPort class and configure the BaudRate, DataBits etc.. and then just wait for the DataReceived event to fire:
public class SerialPortReader
{
public SerialPortReader(string yourPortName)
{
var serialPort = new SerialPort() {
PortName = yourPortName,
BaudRate = 57600; //This will control the rate at what you receive the data
}
serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);
serialPort.Open();
}
}
public void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var serialPort = (SerialPort)sender;
// Process your data reading the stream with Read, ReadLine etc...
}
The approach we are using in our SerialPort Handler is, to have an AutoResetEvent to get notified as soon as there is an answer from the port.
SerialPort class of the FrameWork has a few issues with the integrated DataReceived event. It is sometimes fired when there is no complete package available (in case you defined the answer length). So you should check for the answer length you expect.
Our very stripped down implementation:
public class Serialport
{
private SerialPort _serialPort;
private List<byte> _buffer;
private AutoResetEvent _autoResetEvent;
private const int WriteTimeOut = 5;
private event EventHandler ReceivedDataChanged;
public Serialport()
{
_serialPort = new SerialPort();
// set PortName, BaudRate etc
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
_serialPort.DataReceived += ReceiveData;
}
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
var bytes = _serialPort.BytesToRead;
byte[] buffer = new byte[bytes];
if (_serialPort.IsOpen)
{
_serialPort.BaseStream.Read(buffer, 0, bytes);
_buffer.AddRange(buffer);
}
ReceivedDataChanged?.Invoke(this, new ReceivedBytesEventArgs(_buffer.ToArray()));
_buffer.Clear();
}
private void SendData(byte[] message, int answerLength)
{
_serialPort.ReceivedBytesThreshold = answerLength;
_serialPort.WriteTimeout = WriteTimeOut;
_serialPort.Write(message, 0, message.Length);
}
public string SendDataCommand()
{
if (_serialPort.IsOpen)
{
ReceivedDataChanged += InterpretAnswer;
SendData(message, length);
if (_autoResetEvent.WaitOne(100))
{
ReceivedDataChanged -= InterpretAnswer;
//Data Received and interpreted and send to the caller
return _requestAnswer;
}
ReceivedDataChanged -= InterpretAnswer;
}
return "Connection not open";
}
private void InterpretAnswer(object sender, EventArgs e)
{
// handle all interpretation
// Set the event
_autoResetEvent.Set();
}
}
The serialPort is initialised and opened. After that, we wire up all needed events and call the SendDataCommand() Method. This method is the public visible method which is called from some task. This calls the method SendData. As soon as there is an answer, the event is triggered and the interpretation is started. If the interpretation is done in the specified amount of time (_autoResetEvent.WaitOne(msToWait)) the result is given back to the calling method.
This should be done in a separate task, so the ui will not Block while you wait for the answer
As mentioned, this is a very stripped down example. You should do more checking in the received handler of SerialPort, because there are some issues with the event. With this approach you will have a bit more of abstraction to your business logic.
Hope this helps.
I'm trying to communicate back and forth with an Arduino via serial through a C# program. I've got a basic working example, but it's not pretty and not fault-less. I've included it at the end. I have done some research online, but it's difficult to look for something when you don't know all the details and intricacies of what you're looking for.
I'm under the impression that good serial communication protocol should include a handshake, send data and wait for response, receive data and send response, data clocking, etc. My question is how best to implement this. My existing code is one-way, from C# to the arduino's serial port, and it just sends the data and assumes that it was received. It's also very simple, sending just two bytes (a 1 or 0 to turn on or off an LED, and a 0-255 to control the LED's brightness via PWM). I'd like to be able to send sensor data or confirmation that the data was received and acted on, back from the arduino to the program.
I'm also curious about syncing. Does that go hand in hand with the handshake (no pun intended)? How can I reliably send data either way and be assured that nothing will be lost due to being out of sync?
Anywho, I've rambled, sorry. Hopefully someone can shed a little learning light on this subject. Here's my current messy code:
Arduino:
#define LEDPin 9
byte SerialCmd = 0;
byte SerialVal = 0;
void setup() {
Serial.begin(9600);
pinMode(LEDPin, OUTPUT);
digitalWrite(LEDPin, LOW);
}
void loop() {
while(Serial.available() > 1) {
SerialCmd = Serial.read();
SerialVal = Serial.read();
switch(SerialCmd) {
case 0:
digitalWrite(LEDPin, LOW);
break;
case 1:
analogWrite(LEDPin, SerialVal);
break;
}
}
}
C#:
using System;
using System.Windows.Forms;
namespace ArduinoTest2
{
public partial class Form1 : Form
{
byte[] SerialData = new byte[] { 0, 0 };
public Form1()
{
InitializeComponent();
serialPort1.PortName = "COM3";
serialPort1.BaudRate = 9600;
serialPort1.Open();
}
public void SerialWrite()
{
serialPort1.Write(SerialData, 0, 2);
}
private void button1_Click(object sender, EventArgs e)
{
SerialData[0] = 1;
SerialWrite();
}
private void button2_Click(object sender, EventArgs e)
{
SerialData[0] = 0;
SerialWrite();
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
SerialData[1] = Convert.ToByte(trackBar1.Value);
label1.Text = trackBar1.Value.ToString();
SerialWrite();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
serialPort1.Close();
}
}
}
I have methos that recieve data from opening COM port:
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
try
{
if (sp.IsOpen)
{
if (sp.BytesToRead > 0)
{
// Get data
}
}
}
}
Also I have method that does connection to COM port:
private void connectPort()
{
SerialPort mySerialPort = new SerialPort(port);
...
}
When I call method that closes port:
mySerialPort.DiscardInBuffer();
mySerialPort.DiscardOutBuffer();
mySerialPort.Close();
After I get data from device still. What is wrong?
I don't know for sure, but from the docs it sounds like the fact that the data is being raised from another thread may be buffering and/or lagging a bit behind the actual data (plus it's possible for you to receive data between when you've discarded the buffer and when you close it).
I'd probably unhooking the DataReceivedHandler first, then close the connection, finally discard the data, ex.
mySerialPort.DataReceived -= new SerialDataReceivedEventHandler(DataReceivedHandler);
Hi I'm trying to program a simple C# WPF that displays time information on a virtual scoreboard in real time from a timing system. I'm fairly new to programming so in depth explanation would be appreciated.
I have created a new thread to handle the incoming data from the COM port and as the app is developed this data will be interpreted. For now I just wanted to display the raw information (in hex) that is coming from the timer into a textbox. This works but not as intended. I am receiving tons of duplicate information, my only explanation is I am reading the data too slowly or its reading the same byte over and over. What I would like to happen is to take out each byte and display them, all controlled by one start/stop button.
Possible solutions include storing the entire buffer in a list or array which I'm not quite sure of yet, I don't want to add so many threads that the program freezes everything up.
Here is my code so far (I'm new to pretty much all the code I have written here, so if anything is bad practice please let me know):
public partial class MainWindow : Window
{
SerialPort comms;
Thread commThread;
bool flag;
string message;
public MainWindow()
{
InitializeComponent();
comms = new SerialPort();
}
private void PortControl_Click(object sender, RoutedEventArgs e)
{
if (!comms.IsOpen)
{
PortControl.Content = "Stop";
comms.PortName = "COM1";
comms.BaudRate = 9600;
comms.DataBits = 8;
comms.StopBits = StopBits.One;
comms.Parity = Parity.Even;
comms.ReadTimeout = 500;
comms.ReceivedBytesThreshold = 1;
commThread = new Thread(new ThreadStart(Handle));
comms.Open();
comms.DataReceived += new SerialDataReceivedEventHandler(ReadIn);
}
else
{
PortControl.Content = "Start";
flag = false;
comms.DataReceived -= ReadIn;
commThread.Join();
comms.Close();
}
}
private void ReadIn(object sender, SerialDataReceivedEventArgs e)
{
if (!commThread.IsAlive)
{
flag = true;
commThread.Start();
}
}
private void Handle()
{
while (flag)
{
if (comms.IsOpen)
{
try
{
message = comms.ReadByte().ToString("X2");
Dispatcher.BeginInvoke((Action)(() =>
{
ConsoleBox.Text += message + " ";
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
}
Here is one solution.
The serial port is receiving the data in its own thread, and you should read the incoming bytes in the data received handler.
I propose to read the data and add it to a thread-safe FIFO list in the data received handler and read the data from the list in the main thread.
See my solution in post Serial port reading + Threads or something better?
I am sending a character from visual studio C# to the serial port and I want arduino to read the character and do some work. But, its not reading it correctly. I have tested the arduino program using the serial monitor and it is working perfectly.Here's my C# code.
private void startBit_Click(object sender, EventArgs e)
{
char start = '!';
byte[] buffer = new byte[] { Convert.ToByte(start) };
timerRealTimeData.Enabled = true;
serialPort1.PortName = "COM29";
serialPort1.BaudRate = 9600;
serialPort1.DtrEnable = true;
serialPort1.Open();
serialPort1.Write(buffer, 0, 1);
if (serialPort1.IsOpen)
{
Start.Enabled = false;
Stop.Enabled = true;
}
}
Here's the arduino code for reading the serial port
char incomingByte;
void setup()
{
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop()
{
if(Serial.available() > 0) {
incomingByte = Serial.read();
if(incomingByte=='!')
{
digitalWrite(13,HIGH);
delay(2000);
digitalWrite(13,LOW);
}
}
}
I am stuck on this for a long time.Any help is appreciated
Try to read the equivalent Ascii (33) using an int instead of a char. Also change the line
if(Serial.available() > 0)
To
if(Serial.available())
Some reference for you. Here
First of all, create a function where you open the serial port, and a function where you close the serial port. Your click handler startBit_Click opens the serial port, which means that if the handler is called again, the port is already open and an exception will be generated. (unless you have other code not shown that closes the serial port?)
Second, I am guessing you are connected to the arduino through the USB port?
If so, DtrEnable should be false (default), as you have no XON/XOFF software handshaking.
You should also examine the buffer in the debug window, set a breakpoint after the buffer is assigned the character and check that the character you send is indeed what you think it is.