Go Down

Topic: C# serial data communication with arduino (Read 688 times) previous topic - next topic

Eredin

Hello,
i am trying to create simple weather win app that reads data from Arduino nano connected to DHT11. I am using (or trying to use to be specific) serial communication for this. I managed to open to and close (connect and disconnect) port connected to an Arduino, but it seems that SerialDataReceivedEventHandler is newer "used". I know it's well known problem, I tried to use many sollutions from internet but none of them worked for me

This is my Arduino code

Code: [Select]

#include "DHT.h"

#define DHTPIN 2   

#define DHTTYPE DHT11   

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println("DHTxx test!");
  dht.begin();
}

void loop() {

  float h = dht.readHumidity();
  float t = dht.readTemperature();

  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    Serial.println(t);
    Serial.println(h);
  }
}


Here is c# code responsible for reading from serial port

Code: [Select]

    private void SerialDataReceivedEventHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs  e) // Instrukcje jakie mają się wykonac w momencieodebrania danych z portu szeregowego.
        {

                if (parity == true)
                {
                temperature = serialPort1.ReadLine();
                this.Invoke(new EventHandler(pole_temp_TextChanged));
                parity = !parity; // negacja zmiennej boolean
                }
                else
                {
                    humidity = serialPort1.ReadExisting();
                    this.Invoke(new EventHandler(pole_humm_TextChanged));
                parity = !parity;
                }
           
        }



Code: [Select]

        private void Form1_Load(object sender, EventArgs e)
        {
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(SerialDataReceivedEventHandler);
        }


because Arduino sends every temperature and humidity read on a new line, I use bold parity to check what data is currently in serial port.
First temperature, second humidity, third temperature etc.

and here i am trying to input temperature and humidity data to textboxe's
Code: [Select]

         private void pole_temp_TextChanged(object sender, EventArgs e)
        {
            pole_temp.Text = temperature + " C";
        }

        private void pole_humm_TextChanged(object sender, EventArgs e)
        {
            pole_humm.Text = humidity + " %";
        }







As i mentioned before, i think that serial communication is not "used'. In arduine IDE serial monitor i get proper readings. Even "C" for temperature and "%" for humidity is not shown in textboxes.
Anyd ideas why it is not working?

ieee488

#1
Jun 17, 2018, 06:36 pm Last Edit: Jun 17, 2018, 06:41 pm by ieee488
https://www.youtube.com/watch?reload=9&v=vHeG3Gt6STE


Just view and learn!


If that one is not what you want, there are other tutorials on Youtube.




.

horace

for a simple terminal emulator in C# have a look at
https://github.com/horace3/VB_terminal_emulator

and C# and Java programs which use an arduino+canbus shield to Monitor Canbus traffic
https://github.com/horace3/Arduino_Canbus_Monitor

leefromseattle

I use the arduino to control stuff in a game engine. I've never been able to get that event handler to fire either. I have to poll to get data....

Code: [Select]
serial1.DataReceived += OnDataReceived;

and

Code: [Select]

void OnDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        print("Received: " + sender.ToString() + " "  + e.EventType + " " + e.ToString());
    }


Never triggers....while serial.Read or readline have the valid data depending on what Im sending  :smiley-confuse:

sumguy

I am still learning C# but the following should receive your data from your Arduino and give you a snippet to build on and use the DataReceived event handler.

Code: [Select]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        public delegate void myDelegate(string sData);

        public Form1()

        {
          InitializeComponent();
            }
  

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string sData;
            serialPort1.ReadTimeout = 20;

            try
            {
                sData = serialPort1.ReadLine();
                this.BeginInvoke((new myDelegate(Text_Out)), sData);
            }


            catch (Exception ex)
            {
            }
        }


private void Text_Out(string sData)
        {
            richTextBox1.AppendText(sData);
        }

      

        private void Form1_Load(object sender, EventArgs e)
        {
          
            serialPort1.Open();
        }
    }
    }

horace

Never triggers....while serial.Read or readline have the valid data depending on what Im sending  :smiley-confuse:
I assume using the Form Designer you have set up the Properties (baud rate etc) and DataReceived Event handler for the SerialPort component

sterretje

It's a bit confusing that you use a variable called parity. Parity is associated with serial communications. I would rename it to e.g. isTemperature; if set it indicates that the data is the temperature, if not set it indicates that the data is the humidity.

You have the risk that your data is out of sync; you think that you receive temperature but you actually receive humidity and vice versa.

Have a look at Robin's Serial Input Basics and apply those principles in your C# code; example 3 for starters and next example 5 (where you receive both the temperature and humidity in a one 'go')..

Write the corresponding Arduino code to send comma separated data.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

horace


sumguy

In my example the data was printed in a rich text box which was ok but never really identified what the data was.

As sterretje pointed out the use of parity tends to be confusing, a better option might be to give your Arduino data a descriptive header so that the C# app can recognize what it is and where it should be directed. This would be the beginnings of a simple protocol.

So the transmit part of the Arduino would be something like this

Code: [Select]
Serial.println("temp");
  Serial.println(t);
  Serial.println("hum");
  Serial.println(h);


To handle the new "protocol" I added new logic to the Text_Out sub that takes the data from the Arduino and places it in a Queue that, through conditional logic, "aligns" it and makes sure it ends up in the correct text box.

Code: [Select]
Queue<string> myqueue=new Queue<string>();

private void Text_Out(string sData)
        {
            
            string header;
            string temperature;
            string humidity;

            myqueue.Enqueue(sData);

            //Peek at the queue to make sure the header is in location zero

header = myqueue.Peek();
                if (header!="temp")
                    if (header!="hum")
                    {
                        myqueue.Dequeue();  //there was no header in location zero so toss the data to synch everthing to the headers
                    }
                  

                // if there are two values in the queue we have our header (value 0) and our data (value 1)

            if (myqueue.Count > 1){

  header = myqueue.Dequeue();

                if (header == "temp") {
                    temperature = myqueue.Dequeue();
                    textBox1.Text = temperature;
                }


                if (header == "hum") {
                    humidity = myqueue.Dequeue();
                    textBox2.Text = humidity;
                }  
            
            }
        }


There is also a small adjustment to the DataReceived handler

Code: [Select]
   private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string sData;
            serialPort1.ReadTimeout = 20;
            while (serialPort1.BytesToRead > 0)
            {
                try
                {
                    sData = serialPort1.ReadLine();
                    this.BeginInvoke((new myDelegate(Text_Out)), sData);
                }


                catch (Exception ex)
                {
                }
            }
        }

KawasakiZx10r

#9
Jul 23, 2018, 12:44 am Last Edit: Jul 23, 2018, 12:47 am by KawasakiZx10r
Do some simple research on the Microsoft C# references, Iv been learning VB and C# the past week and found all i need in there examples and function references to create a lovely Serial tool for my Arduino projects, even flashing the Arduinos themselfs. A tip for your search function, don't use SerialPort.ReadExisting and instead use SerialPort.ReadLine, that will get each line perfectly then you can just search for the indexOf.

here's my App :P

Serial App

Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.

Albert Einstein

Go Up