简体   繁体   English

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

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

So following setup: I have 2 USB devices. 所以下面的设置:我有2个USB设备。

  • (1) is a very accurate contact sensor, down to mikrometer (1)是一种非常精确的接触传感器,精确到测微仪
  • (2) is a microcontroller which communicates with a stepper motor which moves a sled to which the sensor is connected (2)是与步进电机通讯的微控制器,步进电机移动连接传感器的滑板

I communicate with those 2 devices via serial port by sending a specific command to either the controller or the sensor and in return I get a value from (1) or (2) perfoms an action (ie move up, down or stop). 我通过向控制器或传感器发送特定命令,通过串行端口与这2个设备进行通信,作为回报,我从(1)或(2)中获取了执行操作(即,向上,向下或停止)的值。

Now as the motor moves down, I want to send the STOP signal as soon as the sensor value changes. 现在,当电动机下降时,我想在传感器值更改后立即发送STOP信号。 Lets say it reads 12,0000mm all the the time and as soon as it hits a possible obstacle, it is pushed in and it reads 11,9997mm. 可以说它一直读取120000毫米,一旦碰到可能的障碍物,它就会被推入并读出119997毫米。

For that I had 2 ideas so far, which kind of worked but not really as I wanted it too. 到目前为止,我有2个想法,哪种想法可行,但并不是我真正想要的。

  • Have a background thread where I send the sensor read signal in a do-while loop and checking the if the value changed in regard to the 12,0000mm. 有一个后台线程,在该线程中,我在do-while循环中发送传感器读取信号,并检查该值是否相对于12,0000mm发生了变化。 This is to keep the UI responsive. 这是为了使UI保持响应。 This worked but the motor stopped to late for my taste, which gave me very inconsitent measuring results ranging between 9-11mm 这种方法有效,但是电机停了下来直到我觉得不对,这使我在9-11mm之间的测量结果非常不稳定
  • Have a timer (10ms) where on each tick I read the sensor data and send back the result. 有一个计时器(10毫秒),在每个滴答处,我都会在该计时器上读取传感器数据并发送回结果。 This worked a bit better but blocks the UI thread and from what I read a timer within a background thread is not a good thing to do. 这工作得更好一些,但是阻塞了UI线程,从我在后台线程中读取计时器的结果来看,这并不是一件好事。

The motor only need to be signaled once in order to start or stop an action, the sensor needs to be signaled constantly for an updated readout. 电动机只需发出信号一次即可开始或停止动作,而传感器则需要不断发出信号以更新读数。 I understand that in my "solutions" it depends on where the programm is currently. 我了解在我的“解决方案”中,它取决于程序的当前位置。 If it is at the end of the while loop, it needs a few milliseconds in order to start again and read out the sensor. 如果它在while循环的末尾,则需要几毫秒的时间才能重新启动并读出传感器。

Is there a way to get consitent sensor data between 11.9960 and 12.0000, or similar, meaning to send the stop signal really fast or that at least I can control better when the motor will stop? 有没有办法在11.9960和12.0000之间或类似的水平上获得有效的传感器数据,这意味着要非常快地发送停止信号,或者至少我可以更好地控制电动机何时停止? The faster the speed X is of my motor (ROR_Speed(X)) the less accurate the results got. X速度对我的电动机(ROR_Speed(X))越快,结果得到的精度就越低。 I could set a very low speed but then it would take forever which is not an option. 我可以设置一个很低的速度,但是那将永远是不可能的。 I hope the information is enough for some tipps or improvements. 我希望这些信息足以应付一些小费或改进。

For important code (the whole code is quite big with multiple classes) 对于重要的代码(带有多个类的整个代码相当大)

    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);

    }

If you really want to keep two threads and block one until something happens in another, then you can use Monitor methods Pulse / Wait (make sure to read this great book ): 如果您确实想要保留两个线程并阻塞一个线程直到另一个线程发生问题,则可以使用Monitor方法Pulse / Wait (确保阅读这本好书 ):

object sync = new object();

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

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

In your case it would be more efficient (easy) to use async/await and just one thread: 在您的情况下,使用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);
    }
});

You want to read sensor as often as possible. 您想尽可能多地阅读传感器。 Polling time introduces the lag. 轮询时间会引入延迟。 Taking your code as example: if you have read the sensor and its value is changed 1 ms after - you will only be able to read new value 500 ms later, delaying motor stop by the same amount at worst. 以您的代码为例:如果您已读取传感器,并且其值在1毫秒后更改-您将只能在500毫秒后读取新值,最坏的情况下,电动机停止将延迟相同的时间。

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

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