I am simply trying to send "0" to my MCU, when the MCU receive this byte, it will send back another byte ("0" or 1" or "2" or "3"). The MCU receive the byte normally, since the code written for the MCU is waiting till I receive the byte. The problem is with the C#, it seems that it's missing the data from the MCU, because sometimes I got the data correctly but most of the time I got it wrong.
Here is the code for the C#:
private void CheckConnPuf_Click(object sender, EventArgs e) //When Check Connected PUF button is clicked
{
comboBox2.Items.Clear();
int serialinput;
serialPort1.WriteLine("0"); //send "0" to the MCU to receive back a byte
while (serialPort1.BytesToRead < 0) ;//if there is no data in the buffer do nothing
serialinput = serialPort1.ReadChar(); // receive the byte
richTextBox1.Text = serialinput.ToString(); //print the received byte
if (serialinput==48) { //if the byte is "0"
comboBox2.Items.Add("R0_SPREAD");
}
else if (serialinput == 49) {//if the byte is "1"
comboBox2.Items.Add("R0_COMP");
}
else if (serialinput == 50) {//if the byte is "2"
comboBox2.Items.Add("ARBITER");
}
else if (serialinput == 51) {//if the byte is "3"
comboBox2.Items.Add("SRAM_150X125");
}
}
Here is the C# form to make things clear :
I am not sure about The part in the code where I wait for the data to be available in the buffer and then I can read it. If it's not correct, what is the way to do it ?
Related
I'm trying to read data from serial port. It reads data when I set breakpoint.
I have tried with parent delegate invoke, some delay also. It doesn't work for me.
Here is my code
Read code from class file:
public void comport_DataReceived2(object sender, SerialDataReceivedEventArgs e)
{
var bytes = comport.BytesToRead;
var buffer = new byte[bytes];
string test2 = comport.ReadExisting();
if (IsReadPDSS)
{
if(test2 != string.Empty && test2 != " " && test2.Length > 30)
{
test2 = test2.Substring(30);
test2.Replace("000000000000P0000W", "");
strReceived += test2;
}
}
else
{
strReceived = test2;
}
}
windows form retriving read data :
string ss=FormObj.strReceived.ToString();
When you do application debugging, your system is not entirely frozen. Only the application you debug. Thus, while your app is in a breakpoint, incoming data on the serial port still is being accumulated.
The control flow is a bit fuzzy (probably because you changed it over a few times while looking for the problem). As it is written now, you read the data from the serial port whenever the event is raised. It is not likely that 30 bytes have arrived at the time you read the data. If you break into the debugger and do single stepping, it is rather more likely that you will find more than 30 bytes in the receive buffer (depending on what your device which transmits does).
Hence, a better way to write the control flow would look like this:
public void comport_DataReceived2(object sender, SerialDataReceivedEventArgs e)
{
var bytes = comport.BytesToRead;
if( bytes > 30 )
{
var test2 = comport.ReadExisting();
// additional testing code as required...
}
}
Depending on how the event raising behavior works, you might need to accumulate the data yourself in an extra buffer if the event is not getting re-raised after being fired for the first time... But that should be easy enough to test and adapt.
I'm developing a small program that receives analog data from the serial port and displays it into multiple Textboxes.
The data is 10 bit A2D from a micro in the form of two Hex bytes and a letter to identify which A2D port it came from.
eg: 0x1A, 0x02, A
My program is receiving the data ok, and if I only display receive analog value at a time it works fine.
The problem I have is that I'm unsure how to process the incoming data when I try to receive multple A2D values.
The code below is suppose to display 3 analog values in separate text boxes, but only the first text box displays any data. What would be the best way to go able this?
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//Initialize a buffer to hold the received data
byte[] buffer = new byte[serialPort1.ReadBufferSize];
int bytes = serialPort1.BytesToRead;
//There is no accurate method for checking how many bytes are read
//unless you check the return from the Read method
bytesRead = serialPort1.Read(buffer, 0, bytes);
nValue = buffer[0] + (buffer[1] << 8);
switch1 = Convert.ToChar(buffer[2]);
switch (switch1)
{
case 'A':
DispString1 = nValue.ToString();
this.Invoke(new EventHandler(textBox0_TextChanged));
break;
case 'B':
DispString2 = nValue.ToString();
this.Invoke(new EventHandler(textBox1_TextChanged));
break;
case 'C':
DispString3 = nValue.ToString();
this.Invoke(new EventHandler(textBox2_TextChanged));
break;
}
}
private void textBox0_TextChanged(object sender, EventArgs e)
{
textBox0.Text = DispString1;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox1.Text = DispString2;
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
textBox2.Text = DispString3;
}
bytesRead = serialPort1.Read(buffer, 0, bytes);
You blindly assume that you'll get 3 bytes, required to make the rest of the code work. That is not how serial ports work. You in fact usually get only 1 or 2 bytes, serial ports are very slow. So of course your switch() statement cannot get a match.
Get ahead with:
byte[] buffer = new byte[3];
int len = 0;
while (len < 3) {
len += serialPort1.Read(buffer, 0, 3-len);
}
// etc..
Do note that you have a tricky synchronization problem. If you call the Open() method while the device is sending then the first byte you receive is not necessarily the first byte of the 3 byte response. You'll never get a proper response. A device usually sends extra bytes to indicate the start and the end of a frame of data to help solve that problem, that however doesn't seem to be the case here. Fixing this at the device end ought to be a strong goal.
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.
I developed an application that sends data for an Arduino by the serial port, but I can't understand how I can receive it on the Arduino. I send a string by the serial port for the Arduino and the Arduino receives it, but it does not work in my code (on the Arduino, I receive a byte at a time).
Update: it's working ;)
The code in C# that sends data:
using System;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.IO.Ports;
pulic class senddata() {
private void Form1_Load(object sender, System.EventArgs e)
{
//Define a serial port.
serialPort1.PortName = textBox2.Text;
serialPort1.BaudRate = 9600;
serialPort1.Open();
}
private void button1_Click(object sender, System.EventArgs e)
{
serialPort1.Write("10"); //This is a string. The 1 is a command. 0 is interpeter.
}
}
The Arduino code:
I have Update the Code
#include <Servo.h>
Servo servo;
String incomingString;
int pos;
void setup()
{
servo.attach(9);
Serial.begin(9600);
incomingString = "";
}
void loop()
{
if(Serial.available())
{
// Read a byte from the serial buffer.
char incomingByte = (char)Serial.read();
incomingString += incomingByte;
// Checks for null termination of the string.
if (incomingByte == '0') { //When 0 execute the code, the last byte is 0.
if (incomingString == "10") { //The string is 1 and the last byte 0... because incomingString += incomingByte.
servo.write(90);
}
incomingString = "";
}
}
}
Some things which make my eyebrow raise:
serialPort1.Write("1");
This will write exactly one byte, the 1, but no newline and no trailing NUL-Byte.
But here you are waiting for an additional NUL byte:
if (incomingByte == '\0') {
You should use WriteLine instead of Write, and wait for \n instead of \0.
This has two side effects:
First: If there is some buffering configured, then there is a certain chance, than a new line will push the buffered data to the Arduino. To be certain you have to dig through the docs at MSDN.
Second: This makes your protocol ASCII-only. This is important for easier debugging. You can then use a plain terminal program like Hyperterm or HTerm (edit) or even the Serial Monitor in the Arduino IDE itself (edit) to debug your Arduino-Code without worrying about bugs in your C# code. And when the Arduino code works you can concentrate on the C# part. Divide et impera.
Edit: Another thing I noticed after digging out my own Arduino:
incomingString += incomingByte;
....
if (incomingByte == '\n') { // modified this
if(incomingString == "1"){
This will of course not work as expected, because the string will contain "1\n" at this point. Either you compare to "1\n" or move the += line after the if.
You could alternatively try using the Firmata library - it's a much better way of having standard firmware on the Arduino and managing it from .net
I believe, Firmata 2.0+ has support for I2C and servo control.
http://firmata.org/
I know that we can use pin no.3 to send the data as a output in RS232. But I am just wondering that there is another way to send only the voltage 5v to the RS232 in a short period? I just want that 5v to trigger a PIC Microcontroller to do something.
Thank you in advance.
You could use the DTREnable (Data Terminal Ready) property of the SerialPort class to apply a positive voltage to those respective pins. This could be used to signal an MCU.
Something along the lines of...
serialPort.DtrEnable = true; //High
currentThread.Sleep(1000);
serialPort.DtrEnable = false; //Low
currentThread.Sleep(1000);
However! the voltage is likely to be incompatible as RS232 operates -25 to 25 volts for 1/0's. You will likely need an inline driver/receiver such as a MAX232 chip to operate between the MCU and computer, or dependant on your skill level you could build a receiver circuit.
you can use RTS or DTR as long as you aren't using them on the PIC side for flow control
PIC Microcontroller with TTL interface used logic as follows:
Logic 1 == 5 volt.
Logic 0 == 0 volt.
Computer with RS232 interface used logic as follows:
Logic 1 == -3 volt until -25 volt.
Logic 0 == 0 until 25 volt.
For connecting device TTL logic to RS232 logic can used MAX232 IC. MAX232 will translate your TTL logic to RS232 Logic.
Another options - cheaper and simple, used TRANSISTOR for convert TTL logic to RS232 logic vice versa, look at http://www.kmitl.ac.th/~kswichit/ap275/ap275.htm for details.
If need send data without hardware handshaking, only need pin 2 (RX), pin 3(TX), pin 5(GND). If need handshaking, add pin 7(RTS) AND pin 8(CTS).
Transmitte data as follows:
serialPort1.Open();
serialPort1.Write("your data in here");
Receive data as dollows:
public Form1()
{
InitializeComponent();
this.serialPort1.DataReceived += new SerialDataReceivedEventHandler(this.serialPort1_DataReceived);
serialPort1.Open();
}
void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int i = 0;
string[] DataReceived;
while (serialPort1.BytesToRead > 0)
{
DataReceived[i] = Convert.ToByte(serialPort1.ReadByte()); // data already in here
i++;
if (i == int.MaxValue-1)
i = 0;
}
// Parsing your data in here
}
If just need toggle output, used pin 4 (DTR) OR pint 7(RTS).
serialPort1.DtrEnable = true;ORserialPort1.RtsEnable = true;