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;
Related
I have a win forms app that i am trying to add a bar code scan too.
The window has multi able text boxes which the user fills in. When user clicks on a box and scans bar code it goes into the selected text box.
Is it possible to write an event to put the text into a particular textbox when scanned even if a different text box is highlighted?
If so how would i do this.
Thanks
There are different types of barcode scanners: keyboard wedge, and serial ones.
Keyboard wedge will send 'messages' as if they were input from the keyboard. So normally they only appear when some kind of edit box has focus.
To put that scanned data in a textbox without having focus, the best and safest way would be to capture the messages in a seperate background thread (this could work for KB wedge as wel as for serial). With KB wedge, your thread would have to check the (prefix)codes to see if they are coming from the barcode scanner - if not, forward then to the normal windows message processing.
Some barcode scanners might have libraries available that already do that for you.
On the other hand, if the app has only one window, and a KB wedge scanner is used, a seperate thread could be avoided, and the messages can be captured inside that window, analysed, and if a barcode is detected the data can be put in the right text box. But I would never trust the user to be in the right text box when scanning the barcode - in fact, that text box should better be read-only.
But, in general, when the application has multiple windows, a background thread may be the only option. Some examples:
A user scans a barcode on a document (invoice for example), and that document needs to be opened automatically. The thread could capture the code, and open that document.
A user scans an EAN code, and wants to see the details of the product. Same as above.
Here's some example code that handles scan events. The scnner has to be configured as a serial scanner, they usually come with barcodes that configure the scanner.
private SerialPort InitializeScanner()
{
SerialPort port = null;
bool result;
int iPort = 2;
do
{
try
{
result = true;
port = new SerialPort("COM" + iPort, 9600, Parity.None, 8, StopBits.One);
port.Close();
if (!port.IsOpen)
port.Open();
port.DiscardOutBuffer();
port.DiscardInBuffer();
port.DataReceived += OnScan;
}
catch (IOException)
{
iPort++;
result = false;
}
} while (result == false && iPort <= 20);
return port;
}
It's all about this line:
port.DataReceived += OnScan;
Here's an example of OnScan. You can set any textbox in that function, although note that you have to use Invoke to set the GUI components, the serial port thread is a different thread from the GUI one.
private void OnScan(object sender, SerialDataReceivedEventArgs args)
{
SerialPort port = sender as SerialPort;
string line = port.ReadExisting();
int idx = line.IndexOf('\r');
if (idx != -1)
{
line = line.Substring(0, idx);
_scanBuffer += line;
Invoke((MethodInvoker)delegate { OnScan(_scanBuffer); });
_scanBuffer = "";
}
else
{
_scanBuffer += line;
}
}
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 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'm more familiar with C language and recently I've been ask to do C# for serial communication.
Below is my code for receiving data from COM port:
public void RxData()
{
int i = 0;
int Data;
bool StartRx = false;
int timer;
while (true)
{
Data = sp.ReadByte();
if (Data == 0x01)
{
StartRx = true;
}
if (StartRx == true)
{
RxBuffer[i++] = Data;
}
if (Data == 0x04)
{
RxChkSum = RxBuffer[i - 2];
break;
}
timer++;
if(timer>100)
{
timer = 0;
break;
}
}
}
Above is the way I receive data starting with 0x01 and ends with 0x04.
I'm incrementing a timer to count til 100 and quit the while loop in case I don't receive any data. Some sort like a timeout.
But seems like the timer don't work. When I don't receive any data, my program just stuck in the while loop forever.
I know this is the way we write in embedded c programming. But is this the right way to write in C#?
I think you might be interested in handling data coming from the serial port using an event handler. In the .net SerialPort class, you can register an event handler for data received:
var sp = new SerialPort("COM1") {
BaudRate = 9600,
Parity = Parity.None,
StopBits = StopBits.One,
DataBits = 8,
Handshake = Handshake.None
};
sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
You can also set the ReceivedBytesThreshold property on the SerialPort, which determines when your event handler will get fired.
Then, you just set up your event handler to read data and do what you need with it:
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting();
}
Using this type of pattern, you don't have to loop, you just set the threshold you need, and let the framework call your event handler when the serial port's got that many bytes ready for you.
Hopefully that helps and I haven't missed your point completely. :)
ReadByte is a synchronous call. It will only return when there is a byte read.
To have your attempt getting to work you can check for available data before reading:
if(sp.BytesToRead > 0)
{
Data = sp.ReadByte();
}
Besides that I prefer asynchronous reading as hmqcnoesy suggested.
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/