There's some outdated software that's used to control the scoreboard at my local athletics track and I've been tasked with creating a new advanced one. However, I cannot seem to get the scoreboard to do what I ask it to do.
I've installed the original software to the my laptop and it works fine, however, when I run my test software that sends data to the board through the serial port, it isn't doing what I want.
I have the "Scoreboard Data Protocol" supplied by the manufacturer and I've been following this. I will supply the code to my test program that I've been using to see if I can get it to work and I will also supply the Data Protocol.
In the text box, I type 010D0201SPAIN and 003C630 and send it to the board and this doesn't work.
public partial class Form1 : Form
{
private SerialPort m_port;
public Form1()
{
InitializeComponent();
m_list.Items.AddRange(SerialPort.GetPortNames()); // Adds ports to combobox
m_port = new SerialPort();
m_port.BaudRate = 9600;
m_port.DataBits = 8;
m_port.Parity = Parity.Even;
m_port.StopBits = StopBits.One;
//m_port.Handshake = Handshake.None;
m_port.Encoding = new ASCIIEncoding();
m_port.RtsEnable = true;
m_port.DtrEnable = true;
m_port.ReceivedBytesThreshold = 1;
m_port.DataReceived += DataReceivedEvent;
}
private void button1_Click(object sender, EventArgs e)
{
m_port.Close();
m_port.PortName = (string)m_list.SelectedItem;
try
{
m_port.Open();
m_sendbutton.Enabled = true;
button2.Enabled = true;
}catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
private void m_sendbutton_Click(object sender, EventArgs e)
{
m_port.Write(m_textbox.Text);
}
private void DataReceivedEvent(object sender, SerialDataReceivedEventArgs args)
{
Invoke(new EventHandler(DoUpdate));
}
private void DoUpdate(object s, EventArgs e)
{
label1.Text += m_port.ReadLine();
}
private void button2_Click(object sender, EventArgs e)
{
byte[] r_bytes = Encoding.ASCII.GetBytes(m_textbox.Text);
m_port.Write(r_bytes, 0, r_bytes.Length);
}
}
}
Scoreboard Data Protocol
Code: https://hastebin.com/epirobuduv.cs
Here's how to add STX and ETX around your message, in a byte array.
private void button2_Click(object sender, EventArgs e)
{
var msg = Encoding.ASCII.GetBytes(m_textbox.Text).ToList();
msg.Insert(0, 0x02); // STX at the start
msg.Add(0x03); // ETX at the end
m_port.Write(msg.ToArray(), 0, msg.Count);
}
Related
I am trying to retrieve weight data from a weight indicator which sends data through the RS232 com port ( Converted through USB)
following is the application I designed to receive data
enter image description here
the problem is it shows all the data which is sent from the indicator but the real weight reading is 15,000.
How can I achieve this?
Thank you
Data sheet of the indicator is as follows
Code is as follows
namespace Weight_Test
{
public partial class Form1 : Form
{
string dataIN;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
cbComPort.Items.AddRange(ports);
btnOpen.Enabled = true;
btnClose.Enabled = false;
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
dataIN = serialPort1.ReadExisting();
this.Invoke(new EventHandler(ShowData));
}
private void ShowData(object sender, EventArgs e)
{
txtWeight.Text = dataIN;
}
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
serialPort1.PortName = cbComPort.Text;
serialPort1.BaudRate = Convert.ToInt32(9600);
serialPort1.DataBits = Convert.ToInt32(8);
serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), "None");
serialPort1.Open();
btnOpen.Enabled = false;
btnClose.Enabled = true;
}
catch (Exception err)
{
MessageBox.Show(err.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
btnOpen.Enabled = true;
btnClose.Enabled = false;
}
}
private void btnClose_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
btnOpen.Enabled = true;
btnClose.Enabled = false;
}
}
}
}
It all seems to work properly. All you need is processing of received data.
You said that your result should be 15,000.
Depends on what sensor you use, it can supply specified resolution, accuracy. Please edit your post and give us some information from datasheet about sending data.
Since you got "+01500001F🥹", it looks like you have 15,000.01, which very is good, but of course I can't be sure.
All you have to do is to process these data. If you have it in string format, you should use Substring method to get rid of decimal places.
For example, with:
string receivedText = DataIN.Substring(0,7);
You'll get "+015000", which you can easily convert to Int32 value, using:
int receivedValue = Convert.ToInt32(receivedText);
And you'll finally get your 15000 as integer.
Okay so I'm trying to do a two-way communication from C# to Arduino (using FTDI232) and viceversa, from Arduino to C#.
Here's the code:
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
private string inData;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("A");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("B");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
inData = myPort.ReadLine();
this.Invoke(new EventHandler(displayData_event));
}
private void displayData_event(object sender, EventArgs e)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + inData;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I have three problems. One is when I want to close the application, I want the Serial Communication to turn off, because I made it automatically open using Form1_Load, as soon as you start the debug, it also opens Serial Communication, and it remains on, but I don't want to use a button that I have to click first to close the application. I need to close Serial Communication automatically after I close the application.
The second problem is with the Serial Port that denies the communication, what I mean is that I need to switch from Receiving Data to Sending Data. Here's a picture of what it looks like: Application Image
The the third problem is the LED one. Well its similar to the second one, but this time when I click the button OFF, I want it to switch back to Receiving Data. Here's the picture:
Application Image 2
EDIT : This code is only temporary. I needed it to turn off the Serial Communication
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
You are initializing and opening the port many times. This is not allowed. Use a single initialization and keep the member. This makes the code much smoother, too.
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
try
{
myPort.WriteLine("A");
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
try
{
myPort.WriteLine("B");
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var inData = myPort.ReadLine(); // Use local variable
Invoke(new Action<string>(displayData_event), inData);
}
private void displayData_event(string data)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + data;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
myPort = null;
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I think I also fixed your event handling. One handler that gets the data and then forwards the received text is enough. You would also not really require the exception handling around WriteLine now, since that cannot really fail.
I am working on a small winform application that reads input from a barcode scanner on a virtual com port and writes the data back to a text box on my winform. I am new to C# so have been struggling through. My current code is below and adapted from here
namespace Barcode_Scanner
{
public partial class Form1 : Form
{
SerialPort sp;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
comboBox1.DataSource = ports;
Application.DoEvents();
}
private void btn_getComData_Click(object sender, EventArgs e)
{
try
{
if (!sp.IsOpen)
sp.Open();
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
}
catch (Exception ex)
{
MessageBox.Show("There was a problem with the Serial Port: " + ex.Message, "Error!");
}
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
sp = (SerialPort)sender;
string data = sp.ReadExisting();
txt_comData.Text = data;
Application.DoEvents();
}
private void button1_Click(object sender, EventArgs e)
{
// Makes sure serial port is open before trying to write
string portname = comboBox1.SelectedItem.ToString();
sp = new SerialPort(portname, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.None;
sp.Open();
}
private void button2_Click(object sender, EventArgs e)
{
sp.Close();
}
}
}
The full string I am trying to scan is "3894038" but I am only able to get the textbox to display one character at a time in the text box. I suspect it has something to do with my .ReadExisting command, but I am a bit perplexed on how to proceed. Is there something wrong with my code?
Thanks for the help in advance.
Marshall
There are quite a few issues with your code. The issue you described is caused by the fact that you are assigning the value of ReadExisting to the textbox rather than appending it. I've fixed that and several other issues below.
Notes:
Use AppendText instead of assigning to add new data to the end of the text box's text
There is virtually never a good reason to call Application.DoEvents
You open the serial port in an inconsistent way in two different places
You already have sp in defined at the class level; there's no need to hide it with a cast of the event sender.
Fixed code:
namespace Barcode_Scanner
{
public partial class Form1 : Form
{
SerialPort sp;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
comboBox1.DataSource = ports;
}
private void btn_getComData_Click(object sender, EventArgs e)
{
try
{
if (!sp.IsOpen)
{
button1_Click(null, EventArgs.Empty);
}
}
catch (Exception ex)
{
MessageBox.Show("There was a problem with the Serial Port: " + ex.Message, "Error!");
}
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = sp.ReadExisting();
txt_comData.Appendtext(data);
}
private void button1_Click(object sender, EventArgs e)
{
// Makes sure serial port is open before trying to write
string portname = comboBox1.SelectedItem.ToString();
sp = new SerialPort(portname, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.None;
sp.Open();
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
}
private void button2_Click(object sender, EventArgs e)
{
sp.Close();
}
}
}
I'm having a problem with serial port data. I have designed a form where I have used a datareceived handler event and the whole of data needs to be printed in the RichTextBox placed in the form. The problem is I'm only receiving the last bits of data on the RichTextBox, while the MessageBox that is provided with the code runs the whole of data in part. Please suggest where I'm going wrong.Thanks in advance.
public partial class Form1 : Form
{
char po='\0';
string indata,pi;
string[] buffer;
public Form1()
{
InitializeComponent();
System.ComponentModel.IContainer components = new System.ComponentModel.Container();
serialPort1 = new System.IO.Ports.SerialPort(components);
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 9600;
serialPort1.DtrEnable = true;
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
po = Convert.ToChar(serialPort1.BytesToRead);
indata = sp.ReadExisting();
//return (indata);
//for (int p = 0; p <= 256; p++) ;
//MessageBox.Show(buffer[0]);
//MessageBox.Show(indata);
//richTextBox1.Text += indata;
//richTextBox1.Text = indata;
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.WordWrap = true;
richTextBox1.Text = indata;
}
}
It looks like you should be appending the data each time data is received over the serial port, so perhaps you should change
indata = sp.ReadExisting();
to:
indata += sp.ReadExisting();
To hold all of the contents of the Serial Data, including historical data that was previously sent.
Hope this helps!
Trying This Code....
private string StrValue = "";
private void Port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
double DouRWeight = 0;
try
{
DouRWeight = Val.ToDouble(Port.ReadLine());
if (DouRWeight != 0)
{
this.Invoke((System.Windows.Forms.MethodInvoker)delegate()
{
StrValue = Val.Format(DouRWeight.ToString(), "####0.000");
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.WordWrap = true;
richTextBox1.Text = StrValue ;
}
It's Completely Worked...
I have written a code in c# for receiving data through serial communication and display it in a text box. I am able to do that. But I am receiving data in following format, e.g.
1234 2345 3456 5667
or
every byte in next line..
But I want that every incoming byte should overwrite the previous byte and in the text box we should see just 1 byte and then another byte overwriting the previous one.
Please suggest how to do that?
private void SerialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = SerialPort.ReadExisting();
this.Invoke(new EventHandler(DisplayText));
}
private void DisplayText(object sender, EventArgs e)
{
txtIncomingData.AppendText(RxString);
}
You are appending every received data to your textbox! that is an expected behavior. You should rather change your textBox.Text value every time you want to display a new received data.
Change your DisplayText method from :
private void DisplayText(object sender, EventArgs e)
{
txtIncomingData.AppendText(RxString);
}
to
private void DisplayText(object sender, EventArgs e)
{
txtIncomingData.Text = RxString;
}
P.S: I am assuming that txtIncomingData is a textBox control, correct me if I'm wrong
The solution below works, but it gives blank bytes in between data.
SerialPort serialPort;
private delegate void SetTextDeleg(string text);
private void Form1_Load(object sender, EventArgs e)
{
serialPort= new SerialPort("COM6", 4800, Parity.None, 8, StopBits.One);
serialPort.Handshake = Handshake.None;
serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
serialPort.ReadTimeout = 500;
serialPort.WriteTimeout = 500;
serialPort.Open();
}
private void btnStart_Click(object sender, EventArgs e)
{
try
{
if(!serialPort.IsOpen)
serialPort.Open();
}
catch (Exception ex)
{
MessageBox.Show("Could not open Serial Port");
}
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
string data = serialPort.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
private void si_DataReceived(string data)
{
txtIncomingData.Text = data.Trim();
}