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

时间:2017-08-22 09:16:11

标签: c#

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

  • (1)是一种非常精确的接触传感器,低至mikrometer
  • (2)是一个与步进电机通信的微控制器,它可以移动传感器所连接的滑板

我通过串口向这两个设备通过向控制器或传感器发送特定命令进行通信,作为回报,我从(1)或(2)获得一个值来执行一个动作(即向上,向下或停止)。

现在当电机向下移动时,我想在传感器值改变后立即发送STOP信号。让我们说它一直读到12,0000毫米,一旦碰到一个可能的障碍物,它就会被推入并且读数为11,9997毫米。

为此我到目前为止有两个想法,哪种有效但不是我想要的那样。

  • 有一个后台线程,我在do-while循环中发送传感器读取信号,并检查相应的值是否改变为12,0000mm。这是为了保持UI响应。这有效但电机因我的口味而停了很晚,这让我的测量结果非常不一致,范围在9-11mm之间
  • 有一个计时器(10ms)在每个刻度线上我读取传感器数据并发回结果。这样做效果好一点,但是阻止了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);

    }

1 个答案:

答案 0 :(得分:0)

如果你真的想要保留两个线程并阻止一个线程直到另一个线程发生,那么你可以使用Monitor方法Pulse / Wait(请务必阅读{{3} }):

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 ms后更改 - 您将只能在500 ms后读取新值,在最坏情况下将电机停止延迟相同的量。