Moving the Focal Point
Software control
Section titled “Software control”In AUTD3, a Pattern is overwritten each time it is sent.
Therefore, running code like the following moves the focal position roughly once per second.
let mut patterns = geometry.pattern_buffer();loop { for sign in [1.0_f32, -1.0] { let target = center + offset((sign * 20.0) * mm, 0.0 * mm, 0.0 * mm); autd3_rs_pattern::focus( &geometry, target, wavelength, &autd3_rs_pattern::FocusOption::default(), &mut patterns, ); let mut builder = client.datagram_builder(); builder.push(Pattern::new(&patterns)); for frame in &builder.build()? { client.send_checked(frame).await?; } tokio::time::sleep(Duration::from_secs(1)).await; }}patterns = geometry.pattern_buffer()while True: for sign in (1.0, -1.0): target = center + np.array([sign * 20.0, 0.0, 0.0]) pattern.focus( geometry, target, wavelength, pattern.FocusOption(), patterns, ) builder = client.datagram_builder() builder.push(Pattern(patterns)) for frame in builder.build(): await client.send_checked(frame) await asyncio.sleep(1.0)var patterns = geometry.PatternBuffer();while (true){ foreach (var sign in new[] { 1.0f, -1.0f }) { var target = center + new Vector3(sign * 20.0f, 0.0f, 0.0f); Pattern.Focus( geometry, target, wavelength, new FocusOption(), patterns ); var builder = client.DatagramBuilder(); builder.Push(new Pattern(patterns)); foreach (var frame in builder.Build()) { await client.SendCheckedAsync(frame); } await Task.Delay(TimeSpan.FromSeconds(1)); }}The code above controls the timing in software.
Its accuracy depends on the OS and the execution environment, so if higher-precision control is needed, using FociStm / PatternStm is recommended.
Hardware control with FociStm
Section titled “Hardware control with FociStm”The code that achieves behavior equivalent to the above using FociStm is as follows.
let points = [ ControlPoints::from(center + offset(20.0 * mm, 0.0 * mm, 0.0 * mm)), ControlPoints::from(center + offset(-20.0 * mm, 0.0 * mm, 0.0 * mm)),];let mut builder = client.datagram_builder();builder.push(FociStm::new(0.5 * Hz, &points, FociStmOption::default()));for frame in &builder.build()? { client.send_checked(frame).await?;}points = [ ControlPoints([ControlPoint(center + np.array([20.0, 0.0, 0.0]))]), ControlPoints([ControlPoint(center + np.array([-20.0, 0.0, 0.0]))]),]builder = client.datagram_builder()builder.push(FociStm(0.5 * Hz, points, FociStmOption()))for frame in builder.build(): await client.send_checked(frame)var points = new[]{ new ControlPoints(new[] { new ControlPoint(center + new Vector3(20.0f, 0.0f, 0.0f)) }), new ControlPoints(new[] { new ControlPoint(center + new Vector3(-20.0f, 0.0f, 0.0f)) }),};var builder = client.DatagramBuilder();builder.Push(new FociStm(0.5f * Hz, points));foreach (var frame in builder.Build()){ await client.SendCheckedAsync(frame);}Because FociStm / PatternStm loops inside the AUTD3 device, no software loop is needed, and it automatically loops infinitely after being sent.
In addition, the timing is controlled by the timer built into the AUTD3 device, so it is highly accurate and can be specified with a resolution as fine as 25 µs.
However, due to constraints of this timer, there are frequencies that cannot be output.
The switching timing of FociStm / PatternStm is specified by the frequency or period of one loop.
That is, in this case two focal points make 0.5 Hz (2 s), so each focal point is output for 1 s.
Note that by using SamplingConfig, the frequency or period can be specified as the sampling frequency, that is per focal point, rather than per loop.
To switch an arbitrary Pattern rather than just a focal point, use PatternStm instead of FociStm.