Simple Serial Read from A/D device

dangdongho1

New member
Joined
May 24, 2018
Messages
1
Programming Experience
Beginner
Hi guys, my first post on this forum, and it's going to be a long one :playful:.

I'm just getting back into programming. I have some limited experience - over the years: Quickbasic, Visual Basic 6 and dabbled in PIC programming and also with HTML/CSS. I have written some useful and workable solutions, and therefore I have some understanding with algorithms and programming, but C# is pushing my limits. I want to learn the "C" type structure because of the similarities with Java and "Processing and Arduino" which I'm currently involved with.

To set the scene (if I haven't already :drunk:), this is where I'm currently at. I've already written the software in "Processing 2.2.1" and it works as required, but I want more on the GUI side, hence learning C#.

It's basically a data logger. The Arduino board (A/D converter) is reliably outputting data, 10bit (0-1023) to the serial bus at 100 samples per second. The data is read and saved to a file for further evaluation (x/y plot and some basic math). The A/D converter is connected to a load cell and the software will record and evaluate the thrust performance of home-made model rocket engines (sugar rockets and black powder rockets).

This is a personal hobby project and the software will be posted on some pyrotechnic and model rocket forums that I'm associated with.

So finally, this is the C# code that I got off the net:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace SimpleSerial
{
    public partial class Form1 : Form
    {
        // Add this variable 
        string RxString;

        public Form1()
        {
            InitializeComponent();
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = "COM8";
            serialPort1.BaudRate = 57600;

            serialPort1.Open();
            if (serialPort1.IsOpen)
            {
                buttonStart.Enabled = false;
                buttonStop.Enabled = true;
                textBox1.ReadOnly = false;
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
                buttonStart.Enabled = true;
                buttonStop.Enabled = false;
                textBox1.ReadOnly = true;
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen) serialPort1.Close();
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            // If the port is closed, don't try to send a character.
            if (!serialPort1.IsOpen) return;

            // If the port is Open, declare a char[] array with one element.
            char[] buff = new char[1];

            // Load element 0 with the key character.
            buff[0] = e.KeyChar;

            // Send the one character buffer.
            serialPort1.Write(buff, 0, 1);

            // Set the KeyPress event as handled so the character won't
            // display locally. If you want it to display, omit the next line.
               e.Handled = true;
        }

        private void DisplayText(object sender, EventArgs e)
        {
            textBox1.AppendText(RxString);
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            RxString = serialPort1.ReadExisting();
            this.Invoke(new EventHandler(DisplayText));
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
    }
}

The code works ok, in that it records the data to the text box. I was able to check by copy/paste into notepad++ and it does indeed record at the 100 sample sec rate. The problem is that it "hangs" sometimes which is a big no no. After spending many hours making a rocket motor that may burn for 2-10 seconds only to have the data not recorded is not a good outcome.

I don't understand the code completely - I do understand some parts but don't know where to look. One thing is, that it only ever hangs at the (buttonStop) event.

I don't need it to be so complicated. With my software, there is no need for background threading or asynchronous operations. What I would like is that when the data is recording, nothing else happens!! - it doesn't need to!! I don't want it to!! except for the stop button which writes the data to a file. This is not a "live" oscilloscope or heart monitor etc.

In future it would be good to be able to send data to the serial port for basic "handshaking" operations, but that's not important at this stage.

I don't want to be a C# serial operations expert - I want to develop the GUI, file IO ops, drawing graphs etc. which I think I'll have a better understanding of, If not, then I'll ask questions here on this forum. Also, I don't wish to be spoon fed, but at this point this part of my software is dragging the whole thing down and me with it.

It's also important to point out that I have done a lot of research over the last 2-3 weeks. Some pointers in the right direction would be absolutely appreciated.

Cheers.
 
Last edited by a moderator:
You do need background threading. A SerialPort raises its DataReceived event on a secondary thread for good reason. It means that the event can be handled immediately, rather than waiting for whatever other operation(s) may be occurring on the UI thread. It also means that your UI will remain responsive while the SerialPort event(s) is being handled.

As for your issue, the first thing to do is work out exactly where the issue is. An application hang is either an infinite loop or a method that doesn't return. In your case, it seems like either IsOpen or Close in your 'buttonStop_Click' method are the only likely candidates so you should start by determining which of them does return.
 
As jmcilhinney indicate you negate the purpose of DataReceived by immediately invoking the UI thread, this is probably stalling any other UI interation. I would add RxString in DataReceived to a class level StringBuilder and leave that event there. Then use a Timer to show the text from the StringBuilder in textbox for example once a second.
 
Back
Top Bottom