以下设置: 我有2个USB设备。
我通过串口向这两个设备通过向控制器或传感器发送特定命令进行通信,作为回报,我从(1)或(2)获得一个值来执行一个动作(即向上,向下或停止)。
现在当电机向下移动时,我想在传感器值改变后立即发送STOP信号。让我们说它一直读到12,0000毫米,一旦碰到一个可能的障碍物,它就会被推入并且读数为11,9997毫米。
为此我到目前为止有两个想法,哪种有效但不是我想要的那样。
为了启动或停止动作,只需要发信号一次电机,需要不断发信号通知传感器以获得更新的读数。我理解在我的“解决方案”中,它取决于程序当前的位置。如果它在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);
}
答案 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后读取新值,在最坏情况下将电机停止延迟相同的量。