i have develop application for getting weight from weigh Bridge machine using C#.Net. i am trying lot of ways but, doesn't read correct data format weight from weigh bridge machine. i am getting output like
00000001Kg00000001B00000001B00000001B00000001B00000001B00000001B00000001B
continuously get from serial port.i want to get weight from weigh bridge machine my code is listed below:
private void Form1_Load(object sender, EventArgs e)
{
string[] portNames = SerialPort.GetPortNames();
foreach (var portName in portNames)
{
comboBox1.Items.Add(portName);
}
comboBox1.SelectedIndex = 0;
}
private void button1_Click(object sender, EventArgs e)
{
if (_serialPort != null && _serialPort.IsOpen)
_serialPort.Close();
if (_serialPort != null)
_serialPort.Dispose();
_serialPort = new SerialPort(comboBox1.Text, BaudRate, Parity.None, 8, StopBits.One);
_serialPort.DataReceived += SerialPortOnDataReceived;
_serialPort.Open();
textBox1.Text = "Listening on " + _serialPort.PortName + "...\r\n";
}
private delegate void Closure();
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired)
BeginInvoke(new Closure(() => { SerialPortOnDataReceived(sender, serialDataReceivedEventArgs); }));
else
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
string str = System.Text.Encoding.UTF8.GetString(data);
textBox1.Text += str.ToString();
}
}
how could i get right weight for save it into my database? in Order to get the right weight it must be like
00000001Kg
at real time and change itself according to weigh scale weight.
Your last line of code is just appending everything to the textbox. You might want to clear it beforehand, and maybe try to check if the data you received is your undesired string (00000001B) and just don't add it.
To log data, you could use the TextChanged event of the textbox... just an idea...
Related
So I am sending from an Arduino Uno an int from potentiometer(0 - 1023) and when I am reading it and print it in a label, there are no numbers.And I read somewhere that I need to read the bytes, how I am going to do that?
namespace Receiver
{
public partial class Form1 : Form
{
SerialPort port;
UITimer _timer = new UITimer();
public Form1()
{
InitializeComponent();
if (port == null)
{
port = new SerialPort("COM11", 9600);//Set your board COM
port.Open();
}
}
private void Form1_Load(object sender, EventArgs e)
{
_timer.Interval = 200;
_timer.Tick += _timer_Tick;
_timer.Enabled = true;
_timer.Start();
}
private void _timer_Tick(object sender, EventArgs e)
{
string a = port.ReadExisting();
afisare.Text = a;
}
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
_timer.Stop();
if (port != null && port.IsOpen)
{
port.Close();
}
}
}
}
First, make sure that you are using the correct Baud rate for your serial communication or otherwise you will receive unreadable data.
Your code is only missing a correct interpretation of the incoming data. On top of that I would recommend removing the timer and using the built-in DataReceived event. That means you can delete all your timer related code and add an event handler to your SerialPort initialization:
if (port == null)
{
port = new SerialPort("COM11", 9600); //Set your board COM
port.DataReceived += DataReceivedEvent;
port.Open();
}
Then you of course have to declare your DataReceivedEvent handler. Since you said that your potentiometer can contain values ranging from 0-1023 and you didn't provide your Arduino code, I'm assuming that that's the only thing being send over the port.
This would mean you are sending 2 bytes every cycle which need to be parsed back to an integer.
This works by performing a left shift of your two received bytes.
private void DataReceivedEvent(object sender, SerialDataReceivedEventArgs e)
{
SerialPort senderPort = (SerialPort)sender;
byte[] buffer = new byte[2];
if (senderPort.Read(buffer, 0, 2) != 0)
{
int data = (int)buffer[0] << 8 | buffer[1];
Console.WriteLine("Received data: {0}", data);
}
}
If you want to use div's Answer on the C# side, you have to send those two bytes as well.
That gives you a bit more precision than in your comment (dividing by 4 and multiply by 4.015 --why??--)
Using the corresponding shift operation:
void loop() {
int a= analogRead(A0);
Serial.write(a>>8);
Serial.write(a & 0xFF);
delay(200);
}
You must be sure that you use the c# DataReceivedEvent trigger, when both bytes are available:
https://learn.microsoft.com/de-de/dotnet/api/system.io.ports.serialport.bytestoread
I want to change BackColor of a Button for a fixed time when a certain value comes from a serial port. I set the Timer object here:
public formLabel()
{
InitializeComponent();
// ...
timerColor.Tick += timerColor_Tick;
timerColor.Interval = 3000;
}
Then, when I receive signal from a serial port:
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
MessageBox.Show("Dati Ricevuti: " + indata);
if (indata.CompareTo("K") == 0)
{
timerColor.Enabled = true;
btnEsito.BackColor = Color.Green;
btnEsito.Text = "GOOD";
// Do something
}
if (indata.CompareTo("O") == 0)
{
timerColor.Enabled = true;
btnEsito.BackColor = Color.Red;
btnEsito.Text = "NO GOOD";
}
}
and here is the method to stop the timer:
private void timerColor_Tick(object sender, EventArgs e)
{
MessageBox.Show("HERE!");
timerColor.Enabled = false;
btnEsito.BackColor = Color.White;
}
BackColor of btnEsito becomes Green or Red based on the type of signal I receive but the program doesn't show the message "HERE!", and the button doesn't come back White.
Could anyone help me?
The System.Windows.Forms.Timer is designed for single threaded use & needs to be started & stopped on the UI thread. You are trying to start the timer on a separate thread, so you need to ensure modifying the timer Enabled property is done on the UI thread. You could do this by creating a delegate method & invoking that from your event handlers - possibly something like this :
delegate void TimerDelegate(bool Enable);
private void ControlTimer(bool Enable)
{
timerColor.Enabled = Enable;
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
MessageBox.Show("Dati Ricevuti: " + indata);
if (indata.CompareTo("K") == 0)
{
Invoke((TimerDelegate)ControlTimer, true);
btnEsito.BackColor = Color.Green;
btnEsito.Text = "GOOD";
// Do something
}
if (indata.CompareTo("O") == 0)
{
Invoke((TimerDelegate)ControlTimer, true);
btnEsito.BackColor = Color.Red;
btnEsito.Text = "NO GOOD";
}
}
private void timerColor_Tick(object sender, EventArgs e)
{
MessageBox.Show("HERE!");
Invoke((TimerDelegate)ControlTimer, false);
btnEsito.BackColor = Color.White;
}
I am receiving data on serial port 250 packets per second where each packet is of size 23 bytes. I am using following code handling the data received on serial port.
private SerialPort connectComPort = new SerialPort();
List<byte> receivedBytes1 = new List<byte>();
public Form1()
{
InitializeComponent();
connectComPort.DataReceived += new SerialDataReceivedEventHandler(receiveData);
//Background worker for parsing packet
m_oWorker = new BackgroundWorker();
m_oWorker.DoWork += new DoWorkEventHandler(m_oWorker_DoWork);
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
}
private void buttton_Click(object sender, EventArgs e)
{
m_oWorker.RunWorkerAsync();
}
void m_oWorker_DoWork(object sender, DoWorkEventArgs e)
{
modprocessReceivedBuffer();
m_oWorker.ReportProgress(100);
}
private void receiveData(object sender, SerialDataReceivedEventArgs e)
{
while (connectComPort.BytesToRead > 0)
receivedBytes1.Add((byte)connectComPort.ReadByte());
}
private void modprocessReceivedBuffer()
{
while (1 == 1)
{
if (receivedBytes1.Count() != 0)
{
var tiff = receivedBytes1.GetRange(0, (int)receivedBytes1[4]).ToList<byte>();
receivedBytes1.RemoveRange(0, (int)receivedBytes1[4]);
modifiedProcess(tiff);
}
else
{
Thread.Sleep(100);
}
}
}
Thus I am just queuing the data received on serial port in a list and I am running a process on background thread whose job is to parse packet. My question is their any better method than this to handle such large data. Currently its 250 packets/sec but this rate can be increased to 16000 packets/sec.
This (VB converted to C#) is what I would do. This will eliminate the issue you were going to eventually have with two threads accessing the list. I also changed the code to read all the bytes at once. There are comments in the code that point at areas to be addressed.
System.Threading.AutoResetEvent dataRcvd = new System.Threading.AutoResetEvent(false);
private void receiveData(object sender, SerialDataReceivedEventArgs e)
{
dataRcvd.Set();
}
private void modprocessReceivedBuffer()
{
while (1 == 1) {
dataRcvd.WaitOne();
while (connectComPort.BytesToRead > 0) {
byte[] buf = new byte[connectComPort.BytesToRead];
int bytsRead = connectComPort.Read(buf, 0, buf.Length);
if (buf.Length != bytsRead) {
Array.Resize(ref buf, bytsRead);
}
//what if there is more than one message in receivedBytes1
if (receivedBytes1.Count() != 0) {
//I think a check is needed for enoung bytes in receivedBytes1????????
var tiff = receivedBytes1.GetRange(0, Convert.ToInt32(receivedBytes1(4))).ToList<byte>();
receivedBytes1.RemoveRange(0, Convert.ToInt32(receivedBytes1(4)));
modifiedProcess(tiff);
}
}
}
}
I have a serialport dataRecived event with 2 methods inside it. The LogFile is loging data and drawSetpoint is drawing a graph.
public void serialPort1_DataRecived (object sender, SerialDataReceivedEventArgs e)
{
DateTime time = DateTime.Now;
string Rdata = serialPort1.ReadLine();
LogFile(Rdata, (int)numericSetpoint.Value);
drawSetpoint(time,numericSetpoint.Value.ToString());
}
Both methods take the second argument from a numericUpDown control which looks like this
public void numericSetpoint_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (serialPort1.IsOpen)
{
int setpoint = (int)numericSetpoint.Value;
//send to serial port .....
}
The problem is both methods in my data recived event read digits as I type them. For example, if I type 150, LogFile will show 1,15,150 and the draw function will start drawing 1,15,150. I would like both functions to take the value from the numericSetpoint control after the enter key is pressed so i get the whole value. How could I do that ?
You are using the KeyPress event. Instead consider using the ValueChanged event which only fires when enter is pressed or the user leaves the control https://msdn.microsoft.com/en-us/library/system.windows.forms.numericupdown.valuechanged%28v=vs.110%29.aspx
It sounds like your data rx event is firing while your typing. I would try filling a buffer in your data rx event and hold off on any logging or plotting until you've sent your data. There are bunch of "safe" ways to do this but the core logic is as follows:
byte[] buffer = new byte[MAX_BUFFER];
private volatile bool _ready = false;
private Object _lock = new Object();
public void serialPort1_DataRecived (object sender, SerialDataReceivedEventArgs e)
{
DateTime time = DateTime.Now;
// Either read as bytes or convert string to bytes, add to your buffer
// string Rdata = serialPort1.ReadLine();
lock(_lock )
{
if(_ready)
{
_ready = false;
var myData = your buffer as string
// clear buffer
LogFile(myData, (int)numericSetpoint.Value);
drawSetpoint(time,numericSetpoint.Value.ToString());
}
}
}
...
public void numericSetpoint_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (serialPort1.IsOpen)
{
int setpoint = (int)numericSetpoint.Value;
//send to serial port .....
lock(_lock ) { _ready = true; }
}
}
}
There is a functionality in my module, where the user can
scan the number of serial ports in the system and when the
user clicks "Auto scan" button, the code will have to go
through each serial port and send a test message and wait
for the reply.
I am using Progress bar control to show process of autoscan.
For which i need to pass the value to "x" and "Y" in my code to
update the bar. How can i pass the value since my code is already
in a foreach loop for getting the serialports.
Y = should pass the value of total number of serial ports
X = should iterate through each port and pass the value
Hope i am clear with req.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string strAckData = "";
foreach (SerialPort sp in comPortsList)
{
sp.Open();
string sendData = "Auto scan";
sp.Write(sendData);
strAckData += "Connection live on port " + sp.ReadExisting() + "\n";
sp.Close();
double dIndex = (double)x; **//How to pass the value here ?**
double dTotal = (double)y; **//How to pass the value here ?**
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
// update the progress bar
backgroundWorker1.ReportProgress(iProgressPercentage);
}
richTextBox1.Invoke(new MethodInvoker(delegate { richTextBox1.Text = strAckData; }));
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressBar.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
StatusLabel.Text = "Auto Scan completed";
}
You can get the number of ports from your comPortsList variable. Then the index is just a matter of incrementing a loop variable:
double dTotal = (double)(comPortsList.Count);
double dIndex = 0;
foreach (SerialPort sp in comPortsList)
{
// talk to serial port as at the moment
dIndex = dIndex + 1; // or ++dIndex to be more concise
double dProgressPercentage = dIndex / dTotal;
// etc.
}