I have a system that makes a loop on all serial ports and send a command 'at' for them.
These ports return 'ok' in Putty, but in the C# the MessageBox is empty.
Why is this happening?
Putty: http://i.imgur.com/AZY7aRY.png /
C#: http://i.imgur.com/wgGyT2x.png
public partial class Form1 : Form
{
List<SerialPort> serialPort = new List<SerialPort>();
private delegate void SetTextDeleg(string text);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var portNames = SerialPort.GetPortNames();
foreach (var port in portNames)
{
SerialPort sp;
sp = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.None;
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.ReadTimeout = 500;
sp.WriteTimeout = 500;
serialPort.Add(sp);
listPorts.Items.Add(port);
}
}
private void listPorts_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
foreach (var sp in serialPort)
{
// Open port
try
{
if (!sp.IsOpen)
sp.Open();
sp.Write("at\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Error opening/writing to serial port :: " + ex.Message, "Error!");
}
}
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
SerialPort sp = (SerialPort)sender;
string data = sp.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
private void si_DataReceived(string data)
{
String retorno = data.Trim();
MessageBox.Show(data);
}
}
Your modem response something like this: \n\rOK\n\r you should read all stream in the buffer or you should read 3 time the serial port buffer with ReadLine() method.
Related
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 making a C# form application that receives data from an instrument communicating at Baud Rate 2400, parity None, 8 bit data, 1 stop bit.
The data is coming in a continuous string line in the form [000000][000000][000000]. For example if during a procedure the reading on the instrument is varying like 0.50,0.49,0.72,0.61,0.48 then the string of received data would be [000050][000049][000072][000061][000048], which is how it is currently being displayed in the textbox.
I need to display the Maximum value reached during a procedure into the textbox and in the correct format, like in this case it should be 0.72. I am at a loss about what would be the code for that.
Below is my current code for serial port communication.
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void Main_Load(object sender, EventArgs e)
{
}
//this is the button to open port.
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
//Event handler for data received.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Regex rx = new Regex(#"\[(\d+)\]");
double.TryParse(richTextBox2.Text, out double max);
foreach (Match match in rx.Matches(indata))
{
double val = int.Parse(match.Groups[1].Value) / 100.0;
if (val > max)
max = val;
}
richTextBox2.Text = max.ToString();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
//this is the button to close port
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
try
{
serialPort1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button3_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.DataReceived += DataReceivedHandler;
}
else
{
MessageBox.Show("Error : Port needs to be open or wrong port selected!");
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen)
serialPort1.Close();
}
private void button4_Click(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
comboBox1.Items.AddRange(ports);
comboBox1.SelectedIndex = 0;
button2.Enabled = false;
}
So you want to process data every time there is data to process right?
If you are using the "System.IO.Ports", and your serialPort1 is of the type SerialPort, you have the "DataReceived" event available. So after you instantiate the serialPort1 you can:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
try
{
//check and set the settings of your device
serialPort1 = new SerialPort
{
PortName = comboBox1.Text,
BaudRate = 2400,
Parity = Parity.None,
StopBits = StopBits.Odd,
DataBits = 8,
Handshake = Handshake.None,
RtsEnable = true
};
serialPort1.DataReceived += DataReceivedHandler;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Then you just need to declare the event handler, something like this:
private void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Regex rx = new Regex(#"\[(\d+)\]");
double.TryParse(textBox13.Text, out double max);
foreach (Match match in rx.Matches(indata))
{
double val = int.Parse(match.Groups[1].Value) / 100.0;
if (val > max)
max = val;
}
textBox13.Text = max .ToString();
}
This will compare the values received and the current value in the textbox.
If I understand you're formatting requirement correctly you basically want to remove zeros at the front from each of the numbers and then compare them to find the max value and display them in the format of x.xx If that's the case create a separate method to handle it like this:
private decimal GetMaxReading(string rawReadingData)
{
decimal maxReading = 0;
var readings = rawReadingData.Split('[',).ToList();
foreach (var reading in readings)
{
var readingString = reading.TrimStart('0')
.TrimEnd(']');
var isInt = int.TryParse(readingString, out int readingValue);
var value = isInt ? (decimal)readingValue / 100 : 0;
maxReading = value > maxReading ? value : maxReading;
}
return maxReading;
}
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 building a weather station and I have a little problem. How do the received data to run at a textbox or rich box? The application connects Arduino, but does not operate to read data.
Thank you,
[enter image description here][1]
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string InputData = String.Empty;
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
// Display each port name to the console.
foreach (string port in ports)
{
comboBox1.Items.Add(port);
}
}
public void guzikpolacz_Click(object sender, EventArgs e)
{
serialPort1.PortName = comboBox1.Text; // Ustawiamy numer Portu COM
// Ustawiamy wartość baudrate portu
//Inne ustawienia zdefiniowane na stałe
serialPort1.Parity = Parity.None; // bez parzystości
serialPort1.StopBits = StopBits.One; // jeden bit stopu
serialPort1.DataBits = 8; // osiem bitów danych
serialPort1.Open();
polestatusu.Text = "Port Otwarty";
polestatusu = SerialPort;
panel1.BackColor = Color.Lime;
guzikpolacz.Enabled = false; //blokujemy przycisk Połącz
guzikrozlacz.Enabled = true;
}
private void guzikrozlacz_Click(object sender, EventArgs e)
{
serialPort1.Close(); //Zamykamy SerialPort
panel1.BackColor = Color.Red;
polestatusu.Text = "Port Zamknięty";
guzikpolacz.Enabled = true; //aktywujemy przycisk Połącz
guzikrozlacz.Enabled = false; // deaktywujemy przycisk Rozłącz
}
private delegate void UpdateUiTextDelegate(string text);
}
}
Thank you very much, but unfortunately it did not work :( The application connects to the serialport but nothing happens. The connection to the Arduino program Putty works.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string InputData = String.Empty;
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
// Display each port name to the console.
foreach (string port in ports)
{
comboBox1.Items.Add(port);
}
;}
public void guzikpolacz_Click(object sender, EventArgs e)
{
serialPort1.PortName = comboBox1.Text; // Ustawiamy numer Portu COM
// Ustawiamy wartość baudrate portu
//Inne ustawienia zdefiniowane na stałe
serialPort1.Parity = Parity.None; // bez parzystości
serialPort1.StopBits = StopBits.One; // jeden bit stopu
serialPort1.DataBits = 8; // osiem bitów danych
serialPort1.Open();
polestatusu.Text = "Port Otwarty";
panel1.BackColor = Color.Lime;
guzikpolacz.Enabled = false; //blokujemy przycisk Połącz
guzikrozlacz.Enabled = true;
}
private void guzikrozlacz_Click(object sender, EventArgs e)
{
serialPort1.Close(); //Zamykamy SerialPort
panel1.BackColor = Color.Red;
polestatusu.Text = "Port Zamknięty";
guzikpolacz.Enabled = true; //aktywujemy przycisk Połącz
guzikrozlacz.Enabled = false; // deaktywujemy przycisk Rozłącz
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => serialPort1_DataReceived(sender, e)));
}
else
{
var sp = sender as SerialPort;
//this assumes you want the data from the arduino as text.
// you may need to decode it here.
textBox1.Text = sp.ReadExisting();
}
}
private delegate void UpdateUiTextDelegate(string text);
public Delegate myDelegate { get; set; }
}
}
enter image description here
try adding this event handler to your serial port
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => serialPort1_DataReceived(sender, e)));
}
else
{
var sp = sender as SerialPort;
//this assumes you want the data from the arduino as text.
// you may need to decode it here.
polestatusu.Text = sp.ReadExisting();
}
}
I am trying to send ASCII caracters to a VideoJet Excel 170i printer, via a RS-232 cable (Serial)
When I am using the test program, i have no problem getting a response from the printer, i can change the status of the printer.
This is the code i've made
public partial class Form1 : Form
{
private SerialPort port = new SerialPort("COM1");
private delegate void SetTextDeleg(string data);
public Form1()
{
InitializeComponent();
}
private void addtoText(string text)
{
this.richTextBox1.Text = this.richTextBox1.Text + "\n" + text;
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
port.BaudRate = 9600;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.DataBits = 8;
port.Handshake = Handshake.None;
port.ReadTimeout = 2000;
port.WriteTimeout = 500;
port.DtrEnable = true;
port.RtsEnable = true;
port.Open();
port.DataReceived += DataReceivedHandler;
addtoText("Port is ready");
}
catch (Exception ex)
{
//Console.WriteLine("Error opening my port: {0}", ex.Message);
addtoText("Error opening my port: {0}" + ex.Message);
}
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
System.Threading.Thread.Sleep(500);
string indata = sp.ReadExisting();
this.BeginInvoke(new SetTextDeleg(DisplayToUI), new object[] { indata });
}
private void DisplayToUI(string displayData)
{
addtoText(displayData);
}
private void button1_Click(object sender, EventArgs e)
{
port.Write(tbxAscii.Text);
}
private void Form1_Leave(object sender, EventArgs e)
{
port.Close();
}
}
I need to sent ASCII caracters to the printer, like
[1B][01][09]
To turn the printer to Print Mode.
The printer is supposed to respond, i get no response, and the printer doesn't change its status.
I have a program made to test the serial connection made by the printer, and i can see that all the settings are OK (Baud rate, Parity... port), and indeed on port COM1.
So i think that my port.write is not sending any info to the printer... or maybe i'm sending corrup info and i'm not reading the response of the printer.
are you sure that you want to send [1B][01][09] or do you want to send that byte sequence 0x1b,0x01,0x09
just to see if this works, send the following in you click handler
private void button1_Click(object sender, EventArgs e)
{
var bytes = new byte[] { 0x1b, 0x01, 0x09 };
port.Write(bytes, 0, bytes.Length);
port.Flush(); // make sure everything is written
}
reading has to be changed, to handle bytes
SerialPort sp = (SerialPort)sender;
System.Threading.Thread.Sleep(500);
var available = sp.BytesToRead; // check how many bytes are ready to be read
if (available < 1)
return;
var buffer = new byte[available];
sp.Read(buffer, 0, available);
var indata = BitConverter.ToString(buffer); // convert bytes to a hex representation
this.BeginInvoke(new SetTextDeleg(DisplayToUI), new object[] { indata });