Pages: [1]   Go Down
Author Topic: C# GUI reading serial from Arduino?  (Read 2221 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 1
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've been trying to get the Arduino to communicate with C# GUI that I made for a couple days, I managed to get *MOST of it working by myself... but ran into a wall and cant seem to figure out a way pass this problem.

The project i'm working on is to use the PING))) Parallax Ultrasonic sensor to read the distance, then send it back to the arduino, the arduino converts it into cm, then send the signal to C# using serial.

I've gotten everything working to the point of C#. I got the Arduino to send the serial signal (distance in cm) to C# and  C# reading it and saving it into a result (double).

The problem.... I cant seem to get C# to loop this reading and continue to read... if I put a While loop into it, the GUI wont load up at all.
If I put the code into the GUI_Load event handler, then it'll do the reading once, then that's it.

What do I need to do to make it read continuously? Or at least... once a second to "detect" a signal change.

The Arduino is sending a distance reading every half a second.

I'll try to figure out how to upload my codes up. It's been very interesting to get working... but  I'm stumped... any help or finger in  the right way would be very appreciated.
Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

you could try putting Application.DoEvents(); in your while loop, after the arduino stuff.

if that doesn't work you could use a timer object and put the arduino call in it's "tick" event.

both of these approaches should free up the GUI to update on a separate thread.
Logged

UK
Offline Offline
Sr. Member
****
Karma: 1
Posts: 491
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Isn't there some kind of "OnSerialReady" event handler in C# that you can put your code in?

Andrew
Logged

Copenhagen / Denmark
Offline Offline
Edison Member
*
Karma: 6
Posts: 2360
Do it !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can use the  serialPort.DataReceived event.

But be prepared for some threading issues.

The serialPort.DataReceived event is running in another thread than the GUI, so you can not directly update the GUI from that event.

You need to implement a delegate to do that.

try to google  "c# serialport thread delegate" or something like that.
Logged

0
Offline Offline
Full Member
***
Karma: 1
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
int pingPin = 7;
void setup()
{
Serial.begin(9600);
Serial.print("?Bff");
delay (100);
Serial.print("?G420"); //set screen to be 4x20
delay (100);
}
void loop()
{
//Serial.print("?f");  //clear screen
long duration, cm;
// triggers the ping sensor with the sequence
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  
// Set pinPing to read the time it takes to get a HIGH back
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

//Convert to centimeters using the method
cm = microsecondsToCentimeters(duration);

//Prints the RESULT! WOO!!!
Serial.print (cm);
Serial.println (" cm");
delay (500);
}

long microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

That's my arduino's code....... very simple... when I do serial monitor with The Arduino software, I get a three or two digit number then a space, then a cm.

My code for C#.... this version only run ONCE the reading, but it work. I tried to put while loop in it, but it wont work at all, wont load up the Gui... so I figure this is probably the first step.
The objective is to "display" the correct picture correlating to the amount of water in the pitcher depending on the distance from the water to the U/S sensor. Sorry if my code is a litte messy.
Code:

namespace WaterPitcher
{
    public partial class WaterMeterGUI : Form
    {

        public SerialPort com1 = new SerialPort
            ("COM16", 9600, Parity.None, 8, StopBits.One);


        public WaterMeterGUI()
        {
            InitializeComponent();
        }
        

        private void WaterMeterGUI_Load(object sender, EventArgs e)
        {
            try
            {
                com1.PortName = "COM16";
                com1.BaudRate = 9600;
                com1.Parity = Parity.None;
                com1.DataBits = 8;
                com1.StopBits = StopBits.One;
                com1.Handshake = Handshake.None;
                com1.ReadTimeout = 1000;
                com1.WriteTimeout = 500;
                com1.Open();
      
                com1.DiscardInBuffer();
            string READ = "";
            READ = com1.ReadLine();
            string[] Split = READ.Split(new Char[] { ' ' });
            //SHOW RESULT
            double result = Convert.ToDouble(Convert.ToString(Split[0]));
            lblresult.Text = Convert.ToString(result);
            if (result < 3)
            {
                SetVis();
                this.pic16.Visible = true;
            }
            else if (result >= 3 && result < 5)
            {
                SetVis();
                this.pic15.Visible = true;
            }
            else if (result >= 5 && result < 7)
            {
                SetVis();
                this.pic14.Visible = true;
            }
            else if (result >= 7 && result < 9)
            {
                SetVis();
                this.pic13.Visible = true;
            }
            else if (result >= 9 && result < 11)
            {
                SetVis();
                this.pic12.Visible = true;
            }
            else if (result >= 11 && result < 13)
            {
                SetVis();
                this.pic11.Visible = true;
            }
            else if (result >= 13 && result < 15)
            {
                SetVis();
                this.pic10.Visible = true;
            }
            else if (result >= 15 && result < 17)
            {
                SetVis();
                this.pic9.Visible = true;
            }
            else if (result >= 17 && result < 19)
            {
                SetVis();
                this.pic8.Visible = true;
            }
            else if (result >= 17 && result < 19)
            {
                SetVis();
                this.pic7.Visible = true;
            }
            else if (result >= 19 && result < 21)
            {
                SetVis();
                this.pic6.Visible = true;
            }
            else if (result >= 21 && result < 23)
            {
                SetVis();
                this.pic5.Visible = true;
            }
            else if (result >= 23 && result < 25)
            {
                SetVis();
                this.pic4.Visible = true;
            }
            else if (result >= 25 && result < 27)
            {
                SetVis();
                this.pic3.Visible = true;
            }
            else if (result >= 27 && result < 29)
            {
                SetVis();
                this.pic2.Visible = true;
            }
            else if (result >= 29 && result < 31)
            {
                SetVis();
                this.pic1.Visible = true;
            }
            }

            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message.ToString(), "ERROR");
            }
        

        }


        void SetVis()
        {
            this.picempty.Visible = false;
            this.pic16.Visible = false;
            this.pic15.Visible = false;
            this.pic14.Visible = false;
            this.pic13.Visible = false;
            this.pic12.Visible = false;
            this.pic11.Visible = false;
            this.pic10.Visible = false;
            this.pic9.Visible = false;
            this.pic8.Visible = false;
            this.pic7.Visible = false;
            this.pic6.Visible = false;
            this.pic5.Visible = false;
            this.pic4.Visible = false;
            this.pic3.Visible = false;
            this.pic2.Visible = false;
            this.pic1.Visible = false;
        }
    }
}

Logged

Boston
Offline Offline
Full Member
***
Karma: 0
Posts: 101
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Subscribing to the serial event and then invoking a delegate is definitely the most elegant and "correct" way to do this.  but conceptually it's a bit of a hurdle for a beginner.

what I'd suggest is:  
  • on the design view, drag a timer out onto the form.
  • rightclick on it and select "properties"
  • set the "enabled" property to "true"
  • set the "interval" property to however often (in milliseconds) you want the program to check the serial port
  • next doubleclick on the timer.  that will automatically create a function in your code called "timername_tick(...)"    which will get excecuted every time the timer's interval is up.
  • put the code you want executed over and over in that function  (leave the com1 initialization code where it is though)

Logged

Chile
Offline Offline
Edison Member
*
Karma: 35
Posts: 1251
Arduino rocks?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You must user Serial port component events, not directly the comN.read

Code:
       private void serialPortCom_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
         {
             int bytesToRead = serialPortCom.BytesToRead;
             char[] z = new char[bytesToRead];
             serialPortCom.Read(z, 0, bytesToRead);
            
             foreach(char s in z)
                 WriteLog(String.Format(Properties.Resources.Log_Received,s,(int)s));
         }

http://code.google.com/p/ciclopeee/source/browse/branches/ciclopeee_dotnet/PruebaArduino/FormMain.cs
« Last Edit: April 05, 2009, 10:57:07 am by eried » Logged

My website: http://ried.cl

Pages: [1]   Go Up
Jump to: