1use crate::group_sync_write::GroupSyncWrite;
2use crate::port_handler::PortHandler;
3use crate::protocol_packet_handler::ProtocolPacketHandler;
4use crate::values::*;
5use std::collections::HashMap;
6use std::sync::{Arc, Mutex};
7use std::thread;
8use std::time::Duration;
9
10pub struct ST3215 {
11 port_handler: Arc<Mutex<PortHandler>>,
12 #[allow(dead_code)]
13 group_sync_write: Arc<Mutex<GroupSyncWrite>>,
14}
15
16impl ST3215 {
17 pub fn new(device: &str) -> Result<Self, String> {
19 let mut port_handler = PortHandler::new(device);
20 port_handler.open_port()?;
21
22 let group_sync_write = GroupSyncWrite::new(STS_ACC, 7);
23
24 Ok(Self {
25 port_handler: Arc::new(Mutex::new(port_handler)),
26 group_sync_write: Arc::new(Mutex::new(group_sync_write)),
27 })
28 }
29
30 pub fn ping_servo(&self, sts_id: u8) -> bool {
32 let mut port = self.port_handler.lock().unwrap();
33 let mut handler = ProtocolPacketHandler::new(&mut *port);
34 let (model, comm, error) = handler.ping(sts_id);
35 comm.is_success() && model != 0 && error == 0
36 }
37
38 pub fn list_servos(&self) -> Vec<u8> {
40 let mut servos = Vec::new();
41 for id in 0..254 {
42 if self.ping_servo(id) {
43 servos.push(id);
44 }
45 thread::sleep(Duration::from_millis(10)); }
47 servos
48 }
49
50 pub fn read_load(&self, sts_id: u8) -> Option<f32> {
52 let mut port = self.port_handler.lock().unwrap();
53 let mut handler = ProtocolPacketHandler::new(&mut *port);
54 let (load, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_PRESENT_LOAD_L);
55 if comm.is_success() && error == 0 {
56 Some(load as f32 * 0.1)
57 } else {
58 None
59 }
60 }
61
62 pub fn read_voltage(&self, sts_id: u8) -> Option<f32> {
64 let mut port = self.port_handler.lock().unwrap();
65 let mut handler = ProtocolPacketHandler::new(&mut *port);
66 let (voltage, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_PRESENT_VOLTAGE);
67 if comm.is_success() && error == 0 {
68 Some(voltage as f32 * 0.1)
69 } else {
70 None
71 }
72 }
73
74 pub fn read_current(&self, sts_id: u8) -> Option<f32> {
76 let mut port = self.port_handler.lock().unwrap();
77 let mut handler = ProtocolPacketHandler::new(&mut *port);
78 let (current, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_PRESENT_CURRENT_L);
79 if comm.is_success() && error == 0 {
80 Some(current as f32 * 6.5)
81 } else {
82 None
83 }
84 }
85
86 pub fn read_temperature(&self, sts_id: u8) -> Option<u8> {
88 let mut port = self.port_handler.lock().unwrap();
89 let mut handler = ProtocolPacketHandler::new(&mut *port);
90 let (temperature, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_PRESENT_TEMPERATURE);
91 if comm.is_success() && error == 0 {
92 Some(temperature)
93 } else {
94 None
95 }
96 }
97
98 pub fn read_acceleration(&self, sts_id: u8) -> Option<u8> {
100 let mut port = self.port_handler.lock().unwrap();
101 let mut handler = ProtocolPacketHandler::new(&mut *port);
102 let (acc, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_ACC);
103 if comm.is_success() && error == 0 {
104 Some(acc)
105 } else {
106 None
107 }
108 }
109
110 pub fn read_mode(&self, sts_id: u8) -> Option<u8> {
116 let mut port = self.port_handler.lock().unwrap();
117 let mut handler = ProtocolPacketHandler::new(&mut *port);
118 let (mode, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_MODE);
119 if comm.is_success() && error == 0 {
120 Some(mode)
121 } else {
122 None
123 }
124 }
125
126 pub fn read_correction(&self, sts_id: u8) -> Option<i16> {
128 let mut port = self.port_handler.lock().unwrap();
129 let mut handler = ProtocolPacketHandler::new(&mut *port);
130 let (correction, comm, error) = handler.read_2byte_tx_rx(sts_id, STS_OFS_L);
131 if comm.is_success() && error == 0 {
132 let mask = 0x07FFF;
133 let mut bits = correction & mask;
134 if (correction & 0x0800) != 0 {
135 bits = bits & 0x7FF;
136 Some(-(bits as i16))
137 } else {
138 Some(bits as i16)
139 }
140 } else {
141 None
142 }
143 }
144
145 pub fn is_moving(&self, sts_id: u8) -> Option<bool> {
147 let mut port = self.port_handler.lock().unwrap();
148 let mut handler = ProtocolPacketHandler::new(&mut *port);
149 let (moving, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_MOVING);
150 if comm.is_success() && error == 0 {
151 Some(moving != 0)
152 } else {
153 None
154 }
155 }
156
157 pub fn set_acceleration(&self, sts_id: u8, acc: u8) -> Option<bool> {
160 let mut port = self.port_handler.lock().unwrap();
161 let mut handler = ProtocolPacketHandler::new(&mut *port);
162 let (comm, error) = handler.write_tx_rx(sts_id, STS_ACC, &[acc]);
163 if comm.is_success() && error == 0 {
164 Some(true)
165 } else {
166 None
167 }
168 }
169
170 pub fn set_speed(&self, sts_id: u8, speed: u16) -> Option<bool> {
173 let mut port = self.port_handler.lock().unwrap();
174 let mut handler = ProtocolPacketHandler::new(&mut *port);
175 let (comm, error) = handler.write_2byte_tx_rx(sts_id, STS_GOAL_SPEED_L, speed);
176 if comm.is_success() && error == 0 {
177 Some(true)
178 } else {
179 None
180 }
181 }
182
183 pub fn disable_torque(&self, sts_id: u8) -> Result<(), String> {
185 let mut port = self.port_handler.lock().unwrap();
186 let mut handler = ProtocolPacketHandler::new(&mut *port);
187 let (comm, error) = handler.write_tx_rx(sts_id, STS_TORQUE_ENABLE, &[0]);
188 if comm.is_success() && error == 0 {
189 Ok(())
190 } else {
191 Err(format!("Failed to disable torque for servo {}: comm={:?}, error={}", sts_id, comm, error))
192 }
193 }
194
195 pub fn enable_torque(&self, sts_id: u8) -> Result<(), String> {
197 let mut port = self.port_handler.lock().unwrap();
198 let mut handler = ProtocolPacketHandler::new(&mut *port);
199 let (comm, error) = handler.write_tx_rx(sts_id, STS_TORQUE_ENABLE, &[1]);
200 if comm.is_success() && error == 0 {
201 Ok(())
202 } else {
203 Err(format!("Failed to enable torque for servo {}: comm={:?}, error={}", sts_id, comm, error))
204 }
205 }
206
207 #[deprecated(since = "0.1.0", note = "Utilisez disable_torque à la place")]
211 pub fn stop_servo(&self, sts_id: u8) -> Option<bool> {
212 self.disable_torque(sts_id).ok().map(|_| true)
213 }
214
215 #[deprecated(since = "0.1.0", note = "Utilisez enable_torque à la place")]
219 pub fn start_servo(&self, sts_id: u8) -> Result<(), String> {
220 self.enable_torque(sts_id)
221 }
222
223 pub fn set_mode(&self, sts_id: u8, mode: u8) -> Result<(), String> {
226 let mut port = self.port_handler.lock().unwrap();
227 let mut handler = ProtocolPacketHandler::new(&mut *port);
228 let (comm, _error) = handler.write_tx_rx(sts_id, STS_MODE, &[mode]);
229 if comm.is_success() {
230 Ok(())
231 } else {
232 Err("Failed to set mode".to_string())
233 }
234 }
235
236 pub fn correct_position(&self, sts_id: u8, correction: i16) -> Result<(), String> {
239 let mut corr = correction.abs() as u16;
240 if corr > MAX_CORRECTION {
241 corr = MAX_CORRECTION;
242 }
243
244 let mut port = self.port_handler.lock().unwrap();
245 let mut handler = ProtocolPacketHandler::new(&mut *port);
246
247 let lo = handler.sts_lobyte(corr);
248 let mut hi = handler.sts_hibyte(corr);
249
250 if correction < 0 {
251 hi |= 1 << 3;
252 }
253
254 let (comm, _error) = handler.write_tx_rx(sts_id, STS_OFS_L, &[lo, hi]);
255 if comm.is_success() {
256 Ok(())
257 } else {
258 Err("Failed to correct position".to_string())
259 }
260 }
261
262 pub fn rotate(&self, sts_id: u8, speed: i16) -> Result<(), String> {
265 self.set_mode(sts_id, 1)?;
266
267 let abs_speed = speed.abs() as u16;
268 let abs_speed = if abs_speed > MAX_SPEED {
269 MAX_SPEED
270 } else {
271 abs_speed
272 };
273
274 let mut port = self.port_handler.lock().unwrap();
275 let mut handler = ProtocolPacketHandler::new(&mut *port);
276
277 let lo = handler.sts_lobyte(abs_speed);
278 let mut hi = handler.sts_hibyte(abs_speed);
279
280 if speed < 0 {
281 hi |= 1 << 7;
282 }
283
284 let (comm, _error) = handler.write_tx_rx(sts_id, STS_GOAL_SPEED_L, &[lo, hi]);
285 if comm.is_success() {
286 Ok(())
287 } else {
288 Err("Failed to rotate".to_string())
289 }
290 }
291
292 fn get_block_position(&self, sts_id: u8) -> Option<u16> {
294 let mut stop_matches = 0;
295 loop {
296 let moving = self.is_moving(sts_id)?;
297
298 if !moving {
299 let position = self.read_position(sts_id);
300 let _ = self.set_mode(sts_id, 0);
301 let _ = self.disable_torque(sts_id);
302
303 if let Some(pos) = position {
304 stop_matches += 1;
305 if stop_matches > 4 {
306 return Some(pos);
307 }
308 } else {
309 return None;
310 }
311 } else {
312 stop_matches = 0;
313 }
314
315 thread::sleep(Duration::from_millis(20));
316 }
317 }
318
319 pub fn define_middle(&self, sts_id: u8) -> Option<bool> {
321 let mut port = self.port_handler.lock().unwrap();
322 let mut handler = ProtocolPacketHandler::new(&mut *port);
323 let (comm, error) = handler.write_tx_rx(sts_id, STS_TORQUE_ENABLE, &[128]);
324 if comm.is_success() && error == 0 {
325 Some(true)
326 } else {
327 None
328 }
329 }
330
331 pub fn tare_servo(&self, sts_id: u8) -> (Option<u16>, Option<u16>) {
334 if self.correct_position(sts_id, 0).is_err() {
335 return (None, None);
336 }
337
338 thread::sleep(Duration::from_millis(500));
339
340 self.set_acceleration(sts_id, 100);
341 let _ = self.rotate(sts_id, -250);
342 thread::sleep(Duration::from_millis(500));
343
344 let min_position = self.get_block_position(sts_id);
345
346 let _ = self.rotate(sts_id, 250);
347 thread::sleep(Duration::from_millis(500));
348
349 let max_position = self.get_block_position(sts_id);
350
351 if let (Some(mut min_pos), Some(mut max_pos)) = (min_position, max_position) {
352 let distance = if min_pos >= max_pos {
353 ((MAX_POSITION - min_pos + max_pos) / 2) as i16
354 } else {
355 ((max_pos - min_pos) / 2) as i16
356 };
357
358 let corr = if min_pos > MAX_POSITION / 2 {
359 min_pos as i16 - MAX_POSITION as i16 - 1
360 } else {
361 min_pos as i16
362 };
363
364 if self.correct_position(sts_id, corr).is_ok() {
365 min_pos = 0;
366 max_pos = (distance * 2) as u16;
367 thread::sleep(Duration::from_millis(500));
368
369 self.move_to(sts_id, distance as u16, 2400, 50, false);
370 }
371
372 return (Some(min_pos), Some(max_pos));
373 }
374
375 (None, None)
376 }
377
378 pub fn move_to(&self, sts_id: u8, position: u16, speed: u16, acc: u8, wait: bool) -> Option<bool> {
384 self.set_mode(sts_id, 0).ok()?;
385 self.set_acceleration(sts_id, acc)?;
386 self.set_speed(sts_id, speed)?;
387
388 let curr_pos = self.read_position(sts_id)?;
389
390 self.write_position(sts_id, position)?;
391
392 if wait {
393 let distance = (position as i32 - curr_pos as i32).abs() as f64;
394 let time_to_speed = speed as f64 / (acc as f64 * 100.0);
395 let distance_acc = 0.5 * (acc as f64 * 100.0) * time_to_speed.powi(2);
396
397 let time_wait = if distance_acc >= distance {
398 (2.0 * distance / acc as f64).sqrt()
399 } else {
400 let remain_distance = distance - distance_acc;
401 time_to_speed + (remain_distance / speed as f64)
402 };
403
404 thread::sleep(Duration::from_secs_f64(time_wait));
405 }
406
407 Some(true)
408 }
409
410 pub fn write_position(&self, sts_id: u8, position: u16) -> Option<bool> {
412 let mut port = self.port_handler.lock().unwrap();
413 let mut handler = ProtocolPacketHandler::new(&mut *port);
414 let (comm, error) = handler.write_2byte_tx_rx(sts_id, STS_GOAL_POSITION_L, position);
415 if comm.is_success() && error == 0 {
416 Some(true)
417 } else {
418 None
419 }
420 }
421
422 pub fn read_status(&self, sts_id: u8) -> Option<HashMap<String, bool>> {
424 let mut port = self.port_handler.lock().unwrap();
425 let mut handler = ProtocolPacketHandler::new(&mut *port);
426 let (status_byte, comm, error) = handler.read_1byte_tx_rx(sts_id, STS_STATUS);
427
428 if !comm.is_success() || error != 0 {
429 return None;
430 }
431
432 let status_bits = [
433 "Voltage",
434 "Sensor",
435 "Temperature",
436 "Current",
437 "Angle",
438 "Overload",
439 ];
440
441 let mut status = HashMap::new();
442 for (i, name) in status_bits.iter().enumerate() {
443 status.insert(name.to_string(), (status_byte & (1 << i)) == 0);
444 }
445
446 Some(status)
447 }
448
449 pub fn read_position(&self, sts_id: u8) -> Option<u16> {
451 let mut port = self.port_handler.lock().unwrap();
452 let mut handler = ProtocolPacketHandler::new(&mut *port);
453 let (position, comm, error) = handler.read_2byte_tx_rx(sts_id, STS_PRESENT_POSITION_L);
454 if comm.is_success() && error == 0 {
455 Some(position)
456 } else {
457 None
458 }
459 }
460
461 pub fn read_speed(&self, sts_id: u8) -> Option<i16> {
463 let mut port = self.port_handler.lock().unwrap();
464 let mut handler = ProtocolPacketHandler::new(&mut *port);
465 let (speed, comm, error) = handler.read_2byte_tx_rx(sts_id, STS_PRESENT_SPEED_L);
466 if comm.is_success() && error == 0 {
467 Some(handler.sts_tohost(speed, 15))
468 } else {
469 None
470 }
471 }
472
473 pub fn lock_eprom(&self, sts_id: u8) -> CommResult {
475 let mut port = self.port_handler.lock().unwrap();
476 let mut handler = ProtocolPacketHandler::new(&mut *port);
477 handler.write_1byte_tx_only(sts_id, STS_LOCK, 1)
478 }
479
480 pub fn unlock_eprom(&self, sts_id: u8) -> CommResult {
482 let mut port = self.port_handler.lock().unwrap();
483 let mut handler = ProtocolPacketHandler::new(&mut *port);
484 handler.write_1byte_tx_only(sts_id, STS_LOCK, 0)
485 }
486
487 pub fn change_id(&self, sts_id: u8, new_id: u8) -> Result<(), String> {
491 if new_id > 253 {
492 return Err("new_id must be between 0 and 253".to_string());
493 }
494
495 if !self.ping_servo(sts_id) {
496 return Err(format!("Could not find servo: {}", sts_id));
497 }
498
499 if !self.unlock_eprom(sts_id).is_success() {
500 return Err("Could not unlock Eprom".to_string());
501 }
502
503 let mut port = self.port_handler.lock().unwrap();
504 let mut handler = ProtocolPacketHandler::new(&mut *port);
505 if !handler.write_1byte_tx_only(sts_id, STS_ID, new_id).is_success() {
506 return Err("Could not change Servo ID".to_string());
507 }
508
509 drop(port);
510 let _ = self.lock_eprom(sts_id);
511
512 Ok(())
513 }
514}