简体   繁体   中英

My Emergency Stop button doesn't work because the code is running and the UI won't respond

I am controlling the short arm of a SCARA robot to rotate Clockwise and Counterclockwise. Now I want to create an emergency stop which can stop the robot short link while it is about to hit the wall. But the problem I am facing right now is that while the short link is moving, any buttons on the form cannot be clicked.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;


namespace SerialPort
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            cmdClose.Enabled = false;
            LongArmClose.Enabled = false;
            foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
            {
                txtPort.Items.Add(s);
            }
            foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
            {
                LongArmPort.Items.Add(s);
            }
        }

        public System.IO.Ports.SerialPort shortPort;
        public System.IO.Ports.SerialPort LongPort;

        public void shortSerialPort_connect(String port, int baudrate, Parity parity, int databits, StopBits stopbits)
        {
            DateTime dt = DateTime.Now;
            String dtn = dt.ToShortTimeString();

            shortPort = new System.IO.Ports.SerialPort(
            port, baudrate, parity, databits, stopbits);
            try
            {
                shortPort.Open();
                cmdClose.Enabled = true;
                cmdConnect.Enabled = false;
                txtReceive.AppendText("[" + dtn + "] " + "Short Link Port Connected\n");             
                shortPort.DataReceived += new SerialDataReceivedEventHandler(shortPort_DataReceived);
                ShortInitializationCommand();
            }
            catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
        }

        public void LongSerialPort_connect(String port, int baudrate, Parity parity, int databits, StopBits stopbits)
        {
            DateTime dt = DateTime.Now;
            String dtn = dt.ToShortTimeString();

            LongPort = new System.IO.Ports.SerialPort(
            port, baudrate, parity, databits, stopbits);
            try
            {
                LongPort.Open();
                LongArmClose.Enabled = true;
                LongArmConnect.Enabled = false;
                LongLinkReceived.AppendText("[" + dtn + "] " + "Long Link Port Connected\n");
                LongPort.DataReceived += new SerialDataReceivedEventHandler(LongPort_DataReceived);
                LongInitializationCommand();

            }
            catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
        }
        private void ShortInitializationCommand()
        {
            DateTime dt = DateTime.Now;
            String dtn = dt.ToShortTimeString();
            String[] commands = new String [14];
            commands[0] = "^KP 1 10";   // Set proportional gain
            commands[1] = "^KI 1 0";    // Set integral gain
            commands[2] = "^KD 1 0";    // Set differential gain
            commands[3] = "^ALIM 1 33"; // Set Amps limit   
            commands[4] = "^ATRIG 1 30";// Set Amps Trigger level
            commands[5] = "^ATGA 1 17"; // Set Amps Trigger action
            commands[6] = "^EMOD 1 18"; // Encoder 1 as feedback for channel 1 
            commands[7] = "^EHL 1 4096";// Set max counter limit for Encoder 1
            commands[8] = "^ELL 1 -4096";//Set min counter limit for Encoder 1
            commands[9] = "^EHLA 1 17"; // Set high limit action as safethy stop for Encoder 1 
            commands[10] = "^ELLA 1 17";// set low limit action as safety stop for Encoder 1
            commands[11] = "^EPPR 1 2048";//Set up pulses per revolution for encoder 1
            commands[12] = "^MMOD 1 3";// set to closed loop count position
            commands[13] = "^MXRPM 1 1";// set speed/ accelevation limit
            for (int i = 0; i <14; i++)
            {
                String data = commands[i] + '\r';
                shortPort.Write(data);
                txtReceive.AppendText("[" + dtn + "] " + "Short Link Sent: " + data + "\n");
            }
            txtReceive.AppendText("[" + dtn + "] " + "Short Link initialization finished " + "\n");

        }
        private void LongInitializationCommand()
        {
            DateTime dt = DateTime.Now;
            String dtn = dt.ToShortTimeString();
            String[] commands = new String[14];
            commands[0] = "^KP 1 10";   // Set proportional gain
            commands[1] = "^KI 1 0";    // Set integral gain
            commands[2] = "^KD 1 0";    // Set differential gain
            commands[3] = "^ALIM 1 33"; // Set Amps limit   
            commands[4] = "^ATRIG 1 30";// Set Amps Trigger level
            commands[5] = "^ATGA 1 17"; // Set Amps Trigger action
            commands[6] = "^EMOD 1 18"; // Encoder 1 as feedback for channel 1 
            commands[7] = "^EHL 1 4096";// Set max counter limit for Encoder 1
            commands[8] = "^ELL 1 -4096";//Set min counter limit for Encoder 1
            commands[9] = "^EHLA 1 17"; // Set high limit action as safethy stop for Encoder 1 
            commands[10] = "^ELLA 1 17";// set low limit action as safety stop for Encoder 1
            commands[11] = "^EPPR 1 2048";//Set up pulses per revolution for encoder 1
            commands[12] = "^MMOD 1 3";// set to closed loop count position
            commands[13] = "^MXRPM 1 1";// set speed/ acc elevation limit
            for (int i = 0; i < 14; i++)
            {
                String data = commands[i] + '\r';
                LongPort.Write(data);
                LongLinkReceived.AppendText("[" + dtn + "] " + "Long Link Sent: " + data + "\n");
            }
            LongLinkReceived.AppendText("[" + dtn + "] " + "Long Link initialization finished " + "\n");

        }
        private void shortPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                DateTime dt = DateTime.Now;
                String dtn = dt.ToShortTimeString();
                txtReceive.AppendText("[" + dtn + "] " + "Received: " + shortPort.ReadExisting() + "\n");

            }));
        }

    private void LongPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        this.BeginInvoke(new Action(() =>
        {
            DateTime dt = DateTime.Now;
            String dtn = dt.ToShortTimeString();
            LongLinkReceived.AppendText("[" + dtn + "] " + "Received: " + LongPort.ReadExisting() + "\n");
        }));
    }


    private void cmdConnect_Click(object sender, EventArgs e)
    {
        String port = txtPort.Text;
        int baudrate = Convert.ToInt32("115200");
        Parity parity = (Parity)Enum.Parse(typeof(Parity), "None");
        int databits = Convert.ToInt32("8");
        StopBits stopbits = (StopBits)Enum.Parse(typeof(StopBits), "One");
        shortSerialPort_connect(port, baudrate, parity, databits, stopbits);

    }

    private void LongArmConnect_Click(object sender, EventArgs e)
    {
        String port = LongArmPort.Text;
        int baudrate = Convert.ToInt32("115200");
        Parity parity = (Parity)Enum.Parse(typeof(Parity), "None");
        int databits = Convert.ToInt32("8");
        StopBits stopbits = (StopBits)Enum.Parse(typeof(StopBits), "One");
        LongSerialPort_connect(port, baudrate, parity, databits, stopbits);

    }

    private void Send_Click(object sender, EventArgs e)
    {

        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String data = txtDatatoSend.Text + '\r';
        shortPort.Write(data);
        txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");

    }

    private void LongArmSend_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String data = LongArmCommand.Text + '\r';
        LongPort.Write(data);
        LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
    }


    private void cmdClose_Click_1(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();

        if (shortPort.IsOpen)
        {
            shortPort.Close();
            cmdClose.Enabled = false;
            cmdConnect.Enabled = true;
            txtReceive.AppendText("[" + dtn + "] " + "Disconnected\n");
        }
    }



    private void LongArmClose_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();

        if (LongPort.IsOpen)
        {
            LongPort.Close();
            LongArmClose.Enabled = false;
            LongArmConnect.Enabled = true;
            LongLinkReceived.AppendText("[" + dtn + "] " + "Disconnected\n");
        }
    }

    private void ShortLinkClockwise_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String angle_string = ShortLinkAngle.Text;
        double angle = Convert.ToDouble(angle_string);          
        int Encoder = Convert.ToInt32(angle * 22.76);
        String Encoder_string = Encoder.ToString();           
        String data = "!PR 1 " + Encoder_string + '\r';
        shortPort.Write(data);
        txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
        //WHEN IT REACHES THE EXTREM, IT CANNOT BOUNCE BACK. SHOULD THERE BE ANY MORE SETTING FOR IT 
    }

    private void ShortLinkCounterClockwise_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String angle_string = ShortLinkAngle.Text;
        double angle = Convert.ToDouble(angle_string);
        angle = angle * -1;
        int Encoder = Convert.ToInt32(angle * 22.76);
        String Encoder_string = Encoder.ToString();
        String data = "!PR 1 " + Encoder_string + '\r'; 
        shortPort.Write(data);
        txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
    }

    private void LongLinkClockWise_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String angle_string = LongLinkAngle.Text;
        double angle = Convert.ToDouble(angle_string);
        int Encoder = Convert.ToInt32(angle * -22.76);
        String Encoder_string = Encoder.ToString();
        String data = "!PR 1 " + Encoder_string + '\r';
        LongPort.Write(data);
        LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");

        //DateTime dt = DateTime.Now;
        //String dtn = dt.ToShortTimeString();
        //String angle_string = LongLinkAngle.Text;
        //double angle = Convert.ToDouble(angle_string);

        //int encoder = Convert.ToInt32(-10 * 22.76);
        //String encoder_string = encoder.ToString();
        //String data = "!PR 1 " + encoder_string + '\r';
        //while (angle > 10)
        //{

        //    encoder = Convert.ToInt32(-10 * 22.76);
        //    encoder_string = encoder.ToString();
        //    data = "!PR 1 " + encoder_string + '\r';
        //    LongPort.Write(data);
        //    angle = angle - 10;
        //    Thread.Sleep(5000);
        //}

        //encoder = Convert.ToInt32(angle * -22.76);
        //encoder_string = encoder.ToString();
        //data = "!PR 1 " + encoder_string + '\r';
        //LongPort.Write(data);

        //LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");



        //WHEN IT REACHES THE EXTREM, IT CANNOT BOUNCE BACK. SHOULD THERE BE ANY MORE SETTING FOR IT 
    }

    private void LongLinkCounterClockwise_Click(object sender, EventArgs e)
    {
        DateTime dt = DateTime.Now;
        String dtn = dt.ToShortTimeString();
        String angle_string = LongLinkAngle.Text;
        double angle = Convert.ToDouble(angle_string);
        int Encoder = Convert.ToInt32(angle * 22.76);
        String Encoder_string = Encoder.ToString();
        String data = "!PR 1 " + Encoder_string + '\r';
        LongPort.Write(data);
        LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");

        //DateTime dt = DateTime.Now;
        //String dtn = dt.ToShortTimeString();
        //String angle_string = LongLinkAngle.Text;
        //double angle = Convert.ToDouble(angle_string);

        //int encoder = Convert.ToInt32(-10 * 22.76);
        //String encoder_string = encoder.ToString();
        //String data = "!PR 1 " + encoder_string + '\r';
            //while (angle > 10)
            //{

            //    encoder = Convert.ToInt32(10 * 22.76);
            //    encoder_string = encoder.ToString();
            //    data = "!PR 1 " + encoder_string + '\r';
            //    LongPort.Write(data);
            //    angle = angle - 10;
            //    Thread.Sleep(5000);
            //}

            //encoder = Convert.ToInt32(angle * 22.76);
            //encoder_string = encoder.ToString();
            //data = "!PR 1 " + encoder_string + '\r';
            //LongPort.Write(data);

            //LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
        }
    }
}

enter image description here

You should take long-running tasks off of the UI thread. I recommend the BackgroundWorker class.

http://www.dotnetperls.com/backgroundworker

Follow the tutorial above, and when you're ready, execute the "problem" code that causes your ui to freeze via the BackgroundWorker.

Here is a stop sign I was able to whip up with a little google, pen, paper, geometry, and grit:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

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

        private void Form1_Load(object sender, EventArgs e)
        {
            Point[] pts = 
            {
                new Point(40, 40),
                new Point(70, 40),
                new Point(100, 70),
                new Point(100, 100),
                new Point(70, 130),
                new Point(40, 130),
                new Point(10, 100),
                new Point(10, 70)
            };

            GraphicsPath polygon_path = new GraphicsPath(FillMode.Winding);
            polygon_path.AddPolygon(pts);
            Region polygon_region = new Region(polygon_path);
            button1.Region = polygon_region;
            button1.Padding = new Padding(5, 35, 0, 0);
            button1.SetBounds(button1.Location.X, button1.Location.Y, pts[3].X + 5, pts[4].Y + 5);
            button1.BackColor = Color.Red;
            button1.ForeColor = Color.White;
            button1.TextAlign = ContentAlignment.MiddleCenter;
            button1.UseCompatibleTextRendering = true;
            button1.Text = "Stop";
        }
    }
}

In order to make this button actually cancel anything, you should first set the "WorkerSupportsCancellation" property of the background worker to true.

Then, periodically check in your DoWork function if backgroundworker.CancellationPending property is true, and abort the operation properly when it is.

In your emergency stop click event, do the following:

// Cancel the asynchronous operation.
this.backgroundWorker1.CancelAsync();

// Disable the Cancel button.
cancelAsyncButton.Enabled = false;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM