Figure 1: Controlling a PIC Microcontroller from a PC Graphical User Interface diagram

A Graphical User Interface is a man-machine interface device, in which objects to handle are drawn as icons on the screen, so the user can send controls by by a pointing device, usually a mouse or a keyboard.

It is always easy and require less skills to operate a device from a visual representations of the workspace (GUI) by simply clicking a mouse or using a keyboard rather than a command line.  
The GUI can also be used to interface with other external devices located in different places. 

There are a lot of different kinds of software which can be used to design a GUI platform, the choice will usually depend on personal preferences, software capabilities and the operating systems (Windows, Linux, Mac…).
Among the popular ones we have Microsoft Visual studio with its popular programming languages visual basic and C#, Labview, Python, Matlab etc.

In this article we are going to design a Graphical User Interface using Microsoft Visual C#. This software could be installed in any computer running windows operating systems. The computer will connect to the microcontroller using an RS232 serial cable as shown on figure 2 below. The PIC microcontroller will receive commands from the computer to control devices connected to it such as motors, LEDs etc.

Figure 2: Male to Female RS232 serial cable

In recent days, the RS232 port usually referred to as COM port is being replaced by a USB port. You might not find this kind of port on your computer especially if you are using a laptop computer, in this case a USB to RS232 converter cable can be used as shown on figure 3 below.

Figure 3: USB to RS232 converter cable

Interfacing between a PC COM Port and Microcontroller USART module

A PIC microcontroller uses TTL level UART (5V for logic 1 and 0V for logic 0) while the PC serial port (COM Port) uses RS-232 (+3 to +15V for logic 0 and -3 to -15V for logic 1). Since both standards uses similar software protocol, both of them are able to communicate via UART. However, because of the differences in voltage level and polarity, we will need a level shifter to interface the TTL level UART with the RS-232. Nowadays, this can be easily done with the commonly available IC such as the MAX2322 from Maxim.
The diagram below on figure 4 illustrates how the MAX232 IC can be connected to the UART of a microcontroller (TX of PIC connected to T1IN of MAX232 and RX pin to R1OUT of MAX232) and a personal computer with DB9 connector.

Figure 4: The use of MAX232 IC to convert TTL levels from microcontroller to RS232 level

USART Configuration with MPLAB Code Configurator

We are going to use the same source code we did in the PIC Microcontroller Communication with RS232 Bus  article. In this example we are using the PIC18F26K20. The E of the EUSART stands for Enhanced USART, its basically the same with the USART but with some extra features like Sleep/ Wake up on receive. The PIC18F26K20 is connected to a PC via MAX232 voltage converter. Three LEDs are connected to PORTB, Red LED on RB0, Yellow LED on RB1 and Green LED on RB2.

In this example if 1 was received from the Windows terminal emulator, the PIC switches ON the Red LED, if 2 the Yellow LED is switched ON and if 3 switches ON the Green LED.

Figure 5: PIC18F26K20 Connected to PC via MAX232

Watch the Video Tutorial

Figure 6: Microcontroller Main.c code

For more information on the PIC microcontroller source code, please read the article:

PIC Microcontroller Communication with RS232 Bus – XC8

To learn how to configure the PIC USART with mikroC Pro for PIC, please read the article:

PIC Microcontroller Communication with RS232 Bus – mikroC

To learn how to configure the PIC USART with Flowcode for PIC, please read the article:

PIC Microcontroller Communication with RS232 Bus – Flowcode

In this article instead of using the Windows terminal emulator, we are going to design a Graphical User Interface (GUI) using C# to send commands to the PIC microcontroller to switch ON these LEDs by a click of a mouse.

PC GUI Software

Watch the Video Tutorial part 1: Design with C#

Figure 7 below shows the PC GUI interface. C# Serial port component is used to send data to serial port of the computer.

Figure 7: PC GUI Software Interface

We have Three LED buttons our the form. The Red, Yellow and Green buttons. Clicking on a button will send a command to the microcontroller.

Some few serial port class methods:

  • Close(): Closes the port connection, sets the IsOpen property to false, and disposes of the internal Stream object. Call this to disconnect your serial port.
  • DiscardInBuffer(): Discards data from the serial driver’s receive buffer.
  • Dispose(): Releases all resources used by the Component.(Inherited from Component.)
  • Open(): Opens a new serial port connection.
  • Read(Char[], Int32, Int32): Reads a number of characters from the SerialPort input buffer and writes them into an array of characters at a given offset.
  • ReadExisting(): Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object.
  • ReadLine(): Reads up to the NewLine value in the input buffer.
  • Write(String): Writes the specified string to the serial port.
  • Write(Char[], Int32, Int32): Writes a specified number of characters to the serial port using data from a buffer as shown on the code below.
 //Send a character 1'to serial port. 
        private void redLEDOFF_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '1'; //ASCII for 1.
            ComPort.Write(buff, 0, 1);
            redLEDOFF.Visible = false;
            redONLED.Visible = true;
            yellowLEDOFF.Visible = true;
            greenLEDOFF.Visible = true;           
        }

Before sending any data, the serial port must be open first by using  the serialPort.Open();

To learn in detail how to design a serial port interface with C#, please read the article:

Creating a serial port interface with C#

Figure 8 below shows the PC GUI interface sending commands to PIC microcontroller. In this example when the Red button is clicked, the PIC red LED switches ON (character 1 is sent to PIC), when the yellow button is clicked, the PIC yellow LED switches ON (character 2 is sent to PIC) and lastly when the Green button is clicked, the PIC green LED is switched ON (character 3 is sent to PIC). If a button is clicked again while already ON character 4 is sent to PIC to switch OFF all LEDs.

Figure 8: PC GUI Software interface sending commands to PIC microcontroller

In this simulation, Proteus COMPIM component is used.

The COMPIM model is a Physical Interface Model of a serial port. Incoming serial data is buffered and presented to the circuit as a digital signal, whilst serial digital data generated by a PIC UART model appears at the PC’s physical COM port. The COMPIM model also provides for baud rate translation, and for optional hardware or software handshaking on both the physical and virtual sides of the device. This allows any real world hardware equipped with a serial port to interact with a VSM simulation. For example, you could use it to develop a program for a microcontroller within Proteus VSM that would operate a real physical modem or a monitor debugger running on one PC can be used to debug a simulated design running within VSM.

The COMPIM RXD pin is connected to PIC RX pin and COMPIM TXD pin is connected to PIC TX pin. Right-click the COMPIM and select Edit Properties. Select physical port, physical baud rate & virtual baud rate as shown on figure 9 below.

Figure 9: COMPIM Edit Properties

Watch the Video Tutorial part 2: Setup Project

Full GUI C# code

/*
 * Project:     Serial Port Interface in C#
 * Company:     Student Companion 
 * Created:     October 2016
 * Notes:       This is a simple demontration on how to use the SerialPort control for
 *              communicating with your PC's  COM Port. 
 *              This is for educational purposes only and not for any commercial use. 
 *              For more on this, please visit: http://www.studentcompanion.net/en/creating-a-serial-port-interface-with-c/
 * */
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;
using System.IO.Ports;  //This is a namespace that contains the SerialPort class

namespace PIC_GUI
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            updatePorts();           //Call this function everytime the page load 
                                     //to update port names
        }
        private SerialPort ComPort = new SerialPort();  //Initialise ComPort Variable as SerialPort
        private void updatePorts()
        {
            // Retrieve the list of all COM ports on your Computer
            string[] ports = SerialPort.GetPortNames();
            foreach (string port in ports)
            {
                cmbPortName.Items.Add(port);
            }
        }
        //whenever the connect button is clicked, it will check if the port is already open, call the disconnect function.
        // if the port is closed, call the connect function.
        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (ComPort.IsOpen)
            {
                disconnect();                
            }
            else
            {
                connect();                
            }
        }
        private void connect()
        {
            bool error = false;

            // Check if all settings have been selected
            if (cmbPortName.SelectedIndex != -1 & cmbBaudRate.SelectedIndex != -1 & cmbParity.SelectedIndex != -1 & cmbDataBits.SelectedIndex != -1 & cmbStopBits.SelectedIndex != -1)
            {
                //if yes than Set The Port's settings
                ComPort.PortName = cmbPortName.Text;
                ComPort.BaudRate = int.Parse(cmbBaudRate.Text);      //convert Text to Integer
                ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), cmbParity.Text); //convert Text to Parity
                ComPort.DataBits = int.Parse(cmbDataBits.Text);        //convert Text to Integer
                ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cmbStopBits.Text);  //convert Text to stop bits

                try  //always try to use this try and catch method to open your port. 
                     //if there is an error your program will not display a message instead of freezing.
                {
                    //Open Port
                    ComPort.Open();
                }
                catch (UnauthorizedAccessException) { error = true; }
                catch (System.IO.IOException) { error = true; }
                catch (ArgumentException) { error = true; }

                if (error) MessageBox.Show(this, "Could not open the COM port. Most likely it is already in use, has been removed, or is unavailable.", "COM Port unavailable", MessageBoxButtons.OK, MessageBoxIcon.Stop);

            }
            else
            {
                MessageBox.Show("Please select all the COM Port Settings", "Controlling a PIC Microcontroller from a PC GUI", MessageBoxButtons.OK, MessageBoxIcon.Stop);

            }
            //if the port is open, Change the Connect button to disconnect, enable the send button.
            //and disable the groupBox to prevent changing configuration of an open port.
            if (ComPort.IsOpen)
            {
                btnConnect.Text = "Disconnect";
                groupRed.Enabled = true; //enable the red LED button
                groupYellow.Enabled = true; //enable the Yellow LED button
                groupGreen.Enabled = true; //enable the Green LED button               
            }
        }
        // Call this function to close the port.
        private void disconnect()
        {
            ComPort.Close();
            btnConnect.Text = "Connect";
            groupRed.Enabled = false; //disable the red LED button
            groupYellow.Enabled = false; //disable the Yellow LED button
            groupGreen.Enabled = false; //disable the Green LED button           

        }
        
        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (ComPort.IsOpen) ComPort.Close();  //close the port if open when exiting the application.
        }
        //Send a character 1'to serial port. 
        private void redLEDOFF_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '1'; //ASCII for 1.
            ComPort.Write(buff, 0, 1);
            redLEDOFF.Visible = false;
            redONLED.Visible = true;
            yellowLEDOFF.Visible = true;
            greenLEDOFF.Visible = true;           
        }
        //Switch OFF all LEDs by sending '4'
        private void redONLED_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '4'; //ASCII for 4.
            ComPort.Write(buff, 0, 1);
            redLEDOFF.Visible = true;
            redONLED.Visible = false;
        }

        private void yellowLEDOFF_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '2'; //ASCII for 2.
            ComPort.Write(buff, 0, 1);
            yellowLEDOFF.Visible = false;
            yellowLEDON.Visible = true;
            greenLEDOFF.Visible = true;
            redLEDOFF.Visible = true;
        }

        private void yellowLEDON_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '4'; //ASCII for 4.
            ComPort.Write(buff, 0, 1);
            yellowLEDOFF.Visible = true;
            yellowLEDON.Visible = false;
        }

        private void greenLEDOFF_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '3'; //ASCII for 3.
            ComPort.Write(buff, 0, 1);
            greenLEDOFF.Visible = false;
            greenLEDON.Visible = true;
            yellowLEDOFF.Visible = true;
            redLEDOFF.Visible = true;
        }

        private void greenLEDON_Click(object sender, EventArgs e)
        {
            char[] buff = new char[1];
            buff[0] = '4'; //ASCII for 4.
            ComPort.Write(buff, 0, 1);
            greenLEDOFF.Visible = true;
            greenLEDON.Visible = false;
        }
    }
}

You can download the full project files (MPLAB XC8 source code and Proteus Schematic design, C# Project) below here. All the files are zipped, you will need to unzip them (Download a free version of the Winzip utility to unzip files).

Download Mplab Project: EUSART MPLAB XC8 Project

Download Proteus Schematic: pic-gui-proteus

Download C# GUI Project: pic_gui_c_project

(Visited 946 times, 1 visits today)