繁体   English   中英

如果USB设备1触发事件(通过串行端口),则以最快的方式向USB设备2发出信号-C#

[英]Fastest way to signal USB Device 2 if USB Device 1 fires event (both via serial port) - C#

所以下面的设置:我有2个USB设备。

  • (1)是一种非常精确的接触传感器,精确到测微仪
  • (2)是与步进电机通讯的微控制器,步进电机移动连接传感器的滑板

我通过向控制器或传感器发送特定命令,通过串行端口与这2个设备进行通信,作为回报,我从(1)或(2)中获取了执行操作(即,向上,向下或停止)的值。

现在,当电动机下降时,我想在传感器值更改后立即发送STOP信号。 可以说它一直读取120000毫米,一旦碰到可能的障碍物,它就会被推入并读出119997毫米。

到目前为止,我有2个想法,哪种想法可行,但并不是我真正想要的。

  • 有一个后台线程,在该线程中,我在do-while循环中发送传感器读取信号,并检查该值是否相对于12,0000mm发生了变化。 这是为了使UI保持响应。 这种方法有效,但是电机停了下来直到我觉得不对,这使我在9-11mm之间的测量结果非常不稳定
  • 有一个计时器(10毫秒),在每个滴答处,我都会在该计时器上读取传感器数据并发送回结果。 这工作得更好一些,但是阻塞了UI线程,从我在后台线程中读取计时器的结果来看,这并不是一件好事。

电动机只需发出信号一次即可开始或停止动作,而传感器则需要不断发出信号以更新读数。 我了解在我的“解决方案”中,它取决于程序的当前位置。 如果它在while循环的末尾,则需要几毫秒的时间才能重新启动并读出传感器。

有没有办法在11.9960和12.0000之间或类似的水平上获得有效的传感器数据,这意味着要非常快地发送停止信号,或者至少我可以更好地控制电动机何时停止? X速度对我的电动机(ROR_Speed(X))越快,结果得到的精度就越低。 我可以设置一个很低的速度,但是那将永远是不可能的。 我希望这些信息足以应付一些小费或改进。

对于重要的代码(带有多个类的整个代码相当大)

    private void Read_sensor()                                   
    {
        Sensor.SendCommand();
        Sensor_height = Sensor.GetDecimalOutput();
    }

    private void Sensor_Read()                                         
    {
        System.Threading.Thread t = new System.Threading.Thread(() => Sensor_read());
        t.Start();
    }

    private void Sensor_read()                                         
    {
        do
        {
            Read_sensor();
            if (Sensor_height > Sensor_height_Check + 3000)  //the sensor answer is between
            {                                                //0 and 120000, for readout
                Motor.Instance.MST(0);  //stop signal        //needs to be divided by 10000
                    Thread.Sleep(500);
                    Threadbreak = 1;
                    Read_sensor();
                    break;
            }
        } while (Threadbreak == 0);
    }
private void button3_Click(object sender, EventArgs e)
    {
        Threadbreak = 0;
        Sensor.SendCommand();           //gets intial value
        Sensor_height_Check = Sensor.GetDecimalOutput();
        Sensor_Read();                  //start background thread
        Motor.Instance.ROR_Speed(1000); //motor moves sled down
        do                              //wait until backgroundtrhead is stopped
        {                              //not really good pracice I know maybe
            counter += 1;              //someone could point me in the right
        } while (Threadbreak != 1);    //direction here as well
        MessageBox.Show("Check: " + Convert.ToString(Sensor_height_Check) + "Actual: " + Convert.ToString(Sensor_height));
        Motor.Instance.Move_steps_Schlitten(-80000);

    }

如果您确实想要保留两个线程并阻塞一个线程直到另一个线程发生问题,则可以使用Monitor方法Pulse / Wait (确保阅读这本好书 ):

object sync = new object();

// thread 1 - block
lock(sync)
    Monitor.Wait(sync);

// thread 2 - signal
lock(sync)
    Monitor.Pulse(sync);

在您的情况下,使用async/await和仅一个线程会更有效(轻松):

async void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    await RotateMotorUntilSensor();
    button1.Enabled = true;
}

Task RotateMotorUntilSensor(someParameters) => Task.Run(() =>
{
    Invoke(new Action(() => Text = "Start"));

    // .. start motor here

    while (true)
    {

        // .. read sensor here

        if (someCondition)
        {

            // ... stop motor here

            Invoke(new Action(() => Text = "stop"));
            break;
        }
        Thread.Sleep(0);
    }
});

您想尽可能多地阅读传感器。 轮询时间会引入延迟。 以您的代码为例:如果您已读取传感器,并且其值在1毫秒后更改-您将只能在500毫秒后读取新值,最坏的情况下,电动机停止将延迟相同的时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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