I'm making my first steps in Arduino programming and noticed that serial output working only with the default serial console that came with the Arduino software
This is my Arduino Code:
void setup()
{
pinMode(13 , OUTPUT);
Serial.begin(9600);
}
void loop ()
{
if (Serial.available()> 0)
{
Serial.println("Hello World");
char Letter = Serial.read();
if (Letter == '1')
{
digitalWrite(13,HIGH);
}
else if (Letter = '0')
{
digitalWrite(13, LOW);
}
}
}
And for the PC side I'm using the MSDN console application which is working for for any other device I've used before.
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport(VS.90).aspx
All I want for now is for it to print the "Hello World" when property has changed.
Now when I using the Arduino's own serial console every thing works well.
I've checked that the Baud-rate and port are correct, and other settings I've left on default.
What can be the problem ??
Related
I'm making a C# Win forms app that reads data from an arduino over serial port, parses it and displays it in a textbox.
My problem is that the value in the textbox is always a few seconds older than the value being sent by arduino even if I slow down the arduino to send the data once per second.
I know the problem must be in my C# code because when I read the serial port using a serial monitor everything's fine.
my code:
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
string msgType;
string serialMsg;
serialMsg = port.ReadLine();
if(serialMsg.Substring(0, 1) != "#")
{
return;
}
msgType = serialMsg.Substring(1, 4);
if(msgType == "VOLT") // recieve supply voltage reading
{
textBox1.Invoke((MethodInvoker)delegate { textBox1.Text = serialMsg.Substring(5, serialMsg.Length - 5); });
}
if (msgType == "AMPS") // recieve supply current reading
{
textBox2.Invoke((MethodInvoker)delegate { textBox2.Text = serialMsg.Substring(5, serialMsg.Length - 5); });
}
if (msgType == "LOAD") // recieve load current reading
{
textBox3.Invoke((MethodInvoker)delegate { textBox3.Text = serialMsg.Substring(5, serialMsg.Length - 5); });
}
}
The messages coming from the arduino are in this format: # + TYPE + DATA
Can you tell me what's slowing it down?
I was sending the messages from the arduino too quickly so I put a 50ms delay between them
I also used ReadExisting instead of ReadLine
This solved all the lagging
I´d like to stream a text file containing G-Code to an Arduino UNO via the serialPort.
The Arduino receives all bytes with the SerialEvent and adds it to a char array named buffer. If the buffer is full it is supposed to send an "!;" over the serial port to C#.
This works fine as I have tested it with the Serial Montior application of the Arduino IDE. But I can´t type text as fast as C# can send it :)
The C# program reads the G-Code file linewise and then sends each char in a line to the arduino. After each char I want to check if the Arduino tells me if the buffer is full. Otherwise keep streaming.
Somehow c# never notices the "!;" or even gets any Bytes to read from the Arduino while streaming. I have the feeling that the serialPort.Write() function blocks the port.
This is the Arduino Code:
void serialEvent()
{
// wenn im Puffer noch platz ist
if (buffercount < MAX_BUF)
{
char c = (char)Serial.read();
buffer[buffercount++] = c;
}
else
{
Serial.print("!;");
}
}
The serialEvent is fired every time the Arduino receives bytes on the port.
Max_BUF has a value of 64.
This is the C# Code:
private void startStreaming(string Text)
{
string[] stringSeparators;
string Text2Stream;
if (Text == "")
{
Text2Stream = File.ReadAllText(textBoxSelectFile.Text);
stringSeparators = new string[] { "\n" };
}
else
{
stringSeparators = new string[] { "\r\n" };
Text2Stream = Text;
}
string[] t2s = Text2Stream.Split(stringSeparators, StringSplitOptions.None);
foreach (string zeile in t2s)
{
if (zeile.Contains(")") || zeile.Contains("("))
{
continue;
}
// Code schicken
foreach (char c in zeile)
{
if (c == ' ') continue;
serialPort.Write(c.ToString());
if (serialPort.BytesToRead > 0)
{
if(serialPort.ReadExisting() == "!;")
{
**wait and do smth.**
}
}
}
serialPort.Write(";");
addTextToLog(zeile);
}
}
serialPort.ReadExisiting() never happens because there are never BytesToRead.
The ";" is for both the sign for the end of a line.
startStreaming is started in an asynchronous thread as BackGroundWorker.
Somehow c# never notices the "!;" or even gets any Bytes to read from the Arduino while streaming. I have the feeling that the serialPort.Write() function blocks the port.
The Write command is not blocking the port. The arduino is just much slower then your computer. So between these two lines:
serialPort.Write(c.ToString());
if (serialPort.BytesToRead > 0)
the arduino is occupied and no data is received yet. Therefore BytesToRead is 0. Two possibilities to solve that come right away to my mind.
1) Use the serialPort.DataReceived event for asynchronous processing. This will be triggered every time you receive data. Then you can react upon the received data in that event or
2) Just give the arduino some time with System.Threading.Thread.Sleep(1000);
serialPort.Write(c.ToString());
System.Threading.Thread.Sleep(1000);
if (serialPort.BytesToRead > 0)
You need to find out which is the minimum timespan to wait.
I have a program that reads serial data from an arduino through a com port.
It works successfully when i program it to print the serial data onto a console, and it does so.
For example, the arduino says outputs "21", and the console writes "21".
But if I make an if statement saying If(data == "21"){/*dosomething*/}
it doesnt work even if the data is printed as "21".
Here are the parts of my code related to this issue.
Arduino
if(digitalRead(i) == HIGH && stat[i-2] == false){
Serial.print(i); Serial.println(1);
stat[i-2] = true;
}
The arduino code is kind of difficult to understand without the rest of the code, but all it does is scans all the ports to see if one of them is high. If it is, it prints the port number and a 1 next to it. For example if port 2 is high, it outputs "21". The same happens when port 2 is low, it outputs "20".
C# (an event handler)
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort serialPort1 = sender as SerialPort;
string dataString = (serialPort1).ReadLine();
screen.clearline();
Console.Write(dataString);
if (dataString == "connectAlready")
{
connect.con();
}
if (dataString == "20")
{
Console.WriteLine("pdown");
}
if (dataString == "21")
{
Console.WriteLine("pup");
}
}
This is the event handler called when data is received.
It prints data to the screen such as "21","20", but it does not perform the functions in the If statements.
Any help would be appreciated, thank you very much.
My guess is that the strings you are comparing aren't completely equal. Arduino's documentation for its println() function states that the serial print ends in a carriage return character ('\r'), followed by the newline character ('\n'). The SerialPort.ReadLine() function reads and returns the string "up to the NewLine value in the input buffer" (found here), so the '\r' character is probably still in dataString.
If this is your problem, you can solve it by removing the last character with something like:
dataString = dataString.TrimEnd('\r');
I'm trying to convert TCL code, used to communicate with a serial port to a "robot", to C#. But for some reason my commands are not getting responses.
This is the serial com init in TCL:
proc openUart {} {
set robot::fd_ [open COM${robot::port_num}: w+]
fconfigure $robot::fd_ -mode 9600,e,7,1
fconfigure $robot::fd_ -blocking 0
fconfigure $robot::fd_ -buffering none
fileevent $robot::fd_ readable ""
}
A "command" is sent like this:
proc SendCmd {command} {
set commandlen [string length $command]
for {set i 0} {$i < $commandlen} {incr i} {
set letter [string index $command $i]
after 10
puts -nonewline $robot::fd_ $letter
}
after [expr 2 * 10]
puts -nonewline $robot::fd_ "\n"
flush $robot::fd_
}
This is how I translated this to C#. Opening the port:
private void Initialize(string com)
{
_comPort = new SerialPort(com,9600,Parity.Even,7,StopBits.One)
{
Encoding = Encoding.ASCII,
NewLine = "\n"
};
_comPort.Open();
}
And sending a command:
private string SendCommand(Commands cmd)
{
string commandToWrite = Command(cmd);
for (int i = 0; i < CommandLen; i++)
{
Thread.Sleep(10);
_comPort.Write(commandToWrite.ToCharArray(), i, 1);
}
Thread.Sleep(10 * 2);
_comPort.Write("\n");
_comPort.BaseStream.Flush();
}
I connected my PC to the robot with a serial to USB cable and ran both TCL and C# programs -
The TCL script turns on a LED on the robot.
My C# code doesn't turn the LED on, meaning the robot did not recognize the command.
I'm using the same com port, so I believe the problem is one of these:
I did not initialize the com port correctly in C#. How do you set the blocking and buffering?
Could there be an encoding issue in C#? isn't ASCII the default encoding in TCL?
Could there be a timing difference in how I'm sending the command letter-by-letter between the two languages?
Issue resolved!
I finally looped back the cable into my PC using another serial cable and 2 blue wires, crossing the RX\TX (thanks don_q for the idea!).
Using a simple serial monitor, "UART Terminal", I sniffed the commands, and to my surprise the TCL script was adding a '\r' before the '\n'!
So in fact the robot was expecting this command format -
:010508010000F1\r\n
I changed the NewLine property in C# to be "\r\n", and now I finish a command by using -
_comPort.WriteLine("");
And now everything works.
I'm trying to write a program in C# to communicate with my Arduino UNO from my computer via a serial connection. At the moment I'm just writing a simple application that establishes contact with the Arduino, and then with several controls to control each pin on the arduino; either read a value from it or write a value to it.
I've managed to establish contact with the Arduino and to set pin-values, but it doesn't always want to obey my commands. I set up a few check boxes, and when I check a box, an LED should turn on, and off when I un-check it. The problem is that sometimes the LED's just stay on or off and I have to click the box a few times before it responds again, or reset my circuit...
I was trying to do some fault-finding, but couldn't get to the root of the problem: is it my app or is it the Arduino code?
Here are the relevant pieces of my code:
private void sendValue(int RW, int _Pin, int Val) //send from my app to serial port
{
if (CommPort.IsOpen)
{
CommPort.WriteLine(RW.ToString() + "," + _Pin.ToString() + "," + Val.ToString());
}
}
private void chP9_CheckedChanged(object sender, EventArgs e) //call the sendValue routine
{
if (chP9.Checked)
{
sendValue(1, 9, 255); //('Write', to pin 9, 'On')
}
else
{
sendValue(1, 9, 0); //('Write', to pin 9, 'Off')
}
}
This is my C# code, it compiles a comma-delimited string to send over the serial port to be read by the Arduino.
Here's the Arduino code:
int RW; //0 to read pin, 1 to write to pin
int PN; //Pin number to read or write
int Val; //Value to write to pin
void setup() {
Serial.begin(38400);
}
void loop() {
ReadIncoming();
ProcessIncoming();
}
void ReadIncoming()
{
if(Serial.available() > 0)
{
RW = Serial.parseInt();
PN = Serial.parseInt();
Val = Serial.parseInt();
}
while(Serial.available() > 0) //Clear the buffer if any data remains after reading
{
Serial.read();
}
}
void ProcessIncoming()
{
if(RW == 0)
{
pinMode(PN, INPUT);
}
else
{
pinMode(PN, OUTPUT);
analogWrite(PN, Val);
}
}
parseInt just takes out the first integer value it finds, stores it and throws away the comma, and does it again and again, but it seems a bit counter-intuitive.
I think my problem lies here:
while(Serial.available() > 0) //Clear the buffer if any data remains after reading
{
Serial.read();
}
I think the App is sending data faster than the Arduino code could handle, especially with this loop, but what do I do with excess data?
I don't like to use the parseInt, but it's the only way I could find to read my instructions correctly. How do I send a byte array from C# and read that array into an array in Arduino?
I've pointed out my hypotheses, and explored alternatives but couldn't get any solutions. What suggestions do you guys have for me?
It is not that clear to me why it works at all. You ought to consider a smarter way to encode the command. You need only three bytes:
private void sendValue(int RW, int _Pin, int Val) {
var cmd = new byte[] { (byte)RW, (byte)_Pin, (byte)Val };
ComPort.Write(cmd, 0, cmd.Length);
}
Then you just need to read those 3 bytes on the Arduino end:
void ReadIncoming() {
if (Serial.available() >= 3) {
RW = Serial.read();
PN = Serial.read();
Val = Serial.read();
ProcessIncoming();
}
}