Удерживая кнопку, чтобы продолжить отправку переменной в последовательном

#c# #loops #button

Вопрос:

Я пытаюсь создать приложение, которое взаимодействует с arduino, и для перемещения сервопривода ему требуется вход от последовательного. Я кое-что сделал, но мне нужно продолжать нажимать кнопку, чтобы отправить переменную в последовательный, но мне нужно, чтобы она работала так же, как кнопка, поэтому, если я удерживаю ее нажатой, она продолжает отправлять переменные в последовательный.

 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 test
{
    public partial class Form1 : Form
    {
        
        private void Form1_Load(object sender, EventArgs e)
        {
            serialPort1.Open();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            serialPort1.Close();
        }
        public Form1()
        {
            InitializeComponent();
        }
        private void button3_MouseDown(object sender, MouseEventArgs e)
        {
            serialPort1.Write("z");
        }

        private void button4_MouseDown(object sender, MouseEventArgs e)
        {
            serialPort1.Write("c");
        }

        private void button1_MoseDown(object sender, MouseEventArgs e)
        {
            serialPort1.Write("a");
        }
                
        private void button2_MouseDown(object sender, MouseEventArgs e)
        {
            serialPort1.Write("d");
        }

       
    }
}
 

а вот и arduino

 #include<Servo.h> // include server library
Servo ser;
Servo ser1;// create servo object to control a servo
int poser = 0; // initial position of server
int val; // initial value of input

void setup() {
  Serial.begin(9600); // Serial comm begin at 9600bps
  ser.attach(9);// server is connected at pin 9
  
}

void loop() {
  if (Serial.available()) // if serial value is available 
  {
    val = Serial.read();// then read the serial value
    if (val == 'd') //if value input is equals to d
    {
      poser  = 1; //than position of servo motor increases by 1 ( anti clockwise)
      ser.write(poser);// the servo will move according to position 
      delay(10);//delay for the servo to get to the position
     }
    if (val == 'a') //if value input is equals to a
    {
      poser -= 1; //than position of servo motor decreases by 1 (clockwise)
      ser.write(poser);// the servo will move according to position 
      delay(10);//delay for the servo to get to the position
    }
     if (val == 'c') //if value input is equals to d
    {
      poser  = 10; //than position of servo motor increases by 1 ( anti clockwise)
      ser.write(poser);// the servo will move according to position 
      delay(10);//delay for the servo to get to the position
  }
  if (val == 'z') //if value input is equals to a
    {
      poser -= 10; //than position of servo motor decreases by 1 (clockwise)
      ser.write(poser);// the servo will move according to position 
      delay(10);//delay for the servo to get to the position
    }
}
}
 

Комментарии:

1. Установите флажок, когда кнопка есть down , и снимите флажок, когда кнопка есть up . Запустите задачу с помощью TPL, проверьте состояние флага и отправьте последовательное сообщение с заданным интервалом. Смотрите здесь: docs.microsoft.com/en-us/dotnet/standard/parallel-programming/…

2. Вы также можете использовать таймер — в нем есть встроенный Timer класс, System.Threading который запускает событие каждые X интервалов, где X может быть любым промежутком времени. Это, по сути, вызывает событие, когда прошло время.

3. вам нужна кнопка повтора, этот элемент управления существует в WPF, но я не знаю, существует ли он в winforms или нет

Ответ №1:

Я бы предложил использовать задачу с маркером отмены. Из раздела Как: Отменить задачу и ее дочерние элементы

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

namespace test
{
    public partial class Form1 : Form
    {
      CancellationTokenSource taskATokenSource = new CancellationTokenSource();

      private void button1_MoseDown(object sender, MouseEventArgs e)
      {
        Task.Run(TaskA(taskATokenSource.Token), taskATokenSource.Token);
      }

      private void button1_MoseUp(object sender, MouseEventArgs e)
      {
        taskATokenSource.Cancel();
      }

      private Action TaskA(CancellationToken ct)
      {
        //For example only
        //Needs slowed down or some other way to prevent input buffer from overflowing.
        while (!ct.IsCancellationRequested)
        {
            serialPort1.Write("a");
        }

        return null;
      }