So following setup: I have 2 USB devices.
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).
Now as the motor moves down, I want to send the STOP signal as soon as the sensor value changes. 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.
For that I had 2 ideas so far, which kind of worked but not really as I wanted it too.
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.
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? The faster the speed X is of my motor (ROR_Speed(X)) the less accurate the results got. 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 ):
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 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.