Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
actuators_sts3032.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Flo&Fab <surname.name@enac.fr>
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
28 #include "string.h"
29 #include "mcu_periph/uart.h"
30 #include "mcu_periph/sys_time.h"
31 #include "mcu_periph/sys_time_arch.h"
32 #include <stdint.h>
34 
35 #ifndef STS3032_IDS
36 #error "STS3032_IDS must be defined"
37 #endif
38 
39 #ifndef STS3032_DEBUG
40 #define STS3032_DEBUG FALSE
41 #endif
42 
43 #ifndef STS3032_RESPONSE_LEVEL
44 #define STS3032_RESPONSE_LEVEL 0
45 #endif
46 
47 struct sts3032 sts;
48 uint8_t cbuf[50 * SERVOS_STS3032_NB]; // buffer large enough to queue a command to each servo
49 
50 #ifndef STS3032_DELAY_MSG
51 #define STS3032_DELAY_MSG 1000
52 #endif
53 
54 #ifndef STS3032_DELAY_MSG_MIN
55 #define STS3032_DELAY_MSG_MIN 0
56 #endif
57 
58 #define BUF_MAX_LENGHT 15
60 
61 
62 
63 /****** settings globals *********/
68 int sts3032_move = 1024;
70 /**********************************/
71 
72 
73 static void sts3032_event(struct sts3032 *sts);
74 static void write_buf(struct sts3032 *sts, uint8_t id, uint8_t *data, uint8_t len, uint8_t fun, uint8_t reply);
75 static void handle_reply(struct sts3032 *sts, uint8_t id, uint8_t state, uint8_t *buf_param, uint8_t length);
76 
77 void sts3032_write_pos(struct sts3032 *sts, uint8_t id, int16_t position);
78 void sts3032_event(struct sts3032 *sts);
79 void sts3032_read_mem(struct sts3032 *sts, uint8_t id, uint8_t addr, uint8_t len);
80 void sts3032_init(struct sts3032 *sts, struct uart_periph *periph, uint8_t *cbuf, size_t cbuf_len);
81 void sts3032_read_pos(struct sts3032 *sts, uint8_t id);
82 void sts3032_enable_torque(struct sts3032 *sts, uint8_t id, uint8_t enable);
83 void sts3032_lock_eeprom(struct sts3032 *sts, uint8_t id, uint8_t lock);
84 void sts3032_set_response_level(struct sts3032 *sts, uint8_t id, uint8_t level);
85 void sts3032_set_id(struct sts3032 *sts, uint8_t id, uint8_t new_id);
86 
87 
89 {
90  sts.periph = &(STS3032_DEV);
95 
96  static const uint8_t tmp_ids[SERVOS_STS3032_NB] = STS3032_IDS;
97  memcpy(sts.ids, tmp_ids, sizeof(tmp_ids));
98 }
99 
101 {
102  sts3032_event(&sts);
103 }
104 
106 {
107 
108  for (int i = 0; i < SERVOS_STS3032_NB; i++) {
109  sts3032_read_pos(&sts, sts.ids[i]);
110  }
111 
112 #if STS3032_DEBUG
113  float data[SERVOS_STS3032_NB + 1];
114  data[0] = sts.nb_failed_checksum;
115  for (int i = 0; i < SERVOS_STS3032_NB; i++) {
116  data[i + 1] = sts.pos[i];
117  }
118  DOWNLINK_SEND_PAYLOAD_FLOAT(DefaultChannel, DefaultDevice, SERVOS_STS3032_NB + 1, data);
119 #endif
120 
121 }
122 
123 
124 
125 static void sts3032_event(struct sts3032 *sts)
126 {
127 
128  uint32_t now = get_sys_time_usec();
129  uint32_t dt = now - sts->time_last_msg;
130  if ((!sts->wait_reply && dt > STS3032_DELAY_MSG_MIN) || dt > STS3032_DELAY_MSG) {
131  uint8_t buf[BUF_MAX_LENGHT];
132  int size = circular_buffer_get(&sts->msg_buf, buf, BUF_MAX_LENGHT);
133  if (size > 0) {
134  // first byte of the buffer indicate whether or not a replay is expected
135  // the rest is the message itself
136  uart_put_buffer(sts->periph, 0, buf + 1, size - 1);
137  sts->wait_reply = buf[0];
138  sts->time_last_msg = now;
139  sts->echo = true;
140  }
141  }
142 
144  switch (sts->rx_state) {
145  case STS3032_RX_IDLE:
146  if (uart_char_available(sts->periph) > 0) {
147  sts->buf_header[1] = sts->buf_header[0];
149  if (sts->buf_header[0] == 0xFF && sts->buf_header[1] == 0xFF) {
151  sts->nb_bytes_expected = 2;
152  sts->buf_header[0] = 0;
153  sts->buf_header[1] = 0;
154  }
155  }
156  break;
157  case STS3032_RX_HEAD_OK:
160  sts->nb_bytes_expected = uart_getch(sts->periph); //length
163  }
164  break;
169  for (int i = 0; i < sts->nb_bytes_expected - 2; i++) {
172  }
175  if (sts->rx_checksum == checksum) {
176  if (!sts->echo) {
178  }
179  } else {
181  }
182  sts->echo = false;
184  sts->nb_bytes_expected = 1;
185  }
186  break;
187  default:
188  break;
189  }
190  }
191 }
192 
193 static void handle_reply(struct sts3032 *sts, uint8_t id, uint8_t state, uint8_t *buf_param, uint8_t length)
194 {
195  uint8_t index = id_idx(sts, id);
196  if (index == 255) {
197  return;
198  }
199  sts->states[index] = state;
200  uint8_t offset = 0;
201  while (length > offset) {
202 
203  switch (sts->read_addr + offset) {
205  if (offset + 2 < length) {
206  return;
207  }
208  sts->pos[index] = buf_param[offset] | (buf_param[offset + 1] << 8);
209  offset += 2;
210  break;
211 
212  default:
213  offset++;
214  break;
215  }
216  }
217 }
218 
219 
221 {
222  for (int i = 0; i < SERVOS_STS3032_NB; i++) {
223  if (sts->ids[i] == id) {
224  return i;
225  }
226  }
227  return 255;
228 }
229 
230 
232 {
233  // lock = 0: unlock eeprom
234  // lock = 1: lock eeprom
235  uint8_t buf[2];
236  buf[0] = SMS_STS_LOCK;
237  buf[1] = lock;
239 }
240 
242 {
243  // response level: 0: reply only on read and ping
244  // 1: always repond
245  uint8_t buf[2];
246  buf[0] = SMS_STS_RESPONSE_LEVEL;
247  buf[1] = level;
249 }
250 
251 void sts3032_set_id(struct sts3032 *sts, uint8_t id, uint8_t new_id)
252 {
253  uint8_t buf[2];
254  buf[0] = SMS_STS_ID;
255  buf[1] = new_id;
257 }
258 
259 void sts3032_write_pos(struct sts3032 *sts, uint8_t id, int16_t position)
260 {
261  if (position < 0) {
262  position = -position;
263  position |= (1 << 15);
264  }
265  uint8_t buf[3];
266  buf[0] = SMS_STS_GOAL_POSITION_L;
267  buf[1] = position & 0xff;
268  buf[2] = position >> 8;
270 }
271 
273 {
274  uint8_t buf[2];
275  buf[0] = SMS_STS_TORQUE_ENABLE;
276  buf[1] = enable;
278 }
279 
281 {
283 }
284 
285 void sts3032_read_mem(struct sts3032 *sts, uint8_t id, uint8_t addr, uint8_t len)
286 {
287  uint8_t buf[2] = {addr, len};
288  write_buf(sts, id, buf, 2, INST_READ, 1);
289  sts->read_addr = addr;
290 }
291 
292 static void write_buf(struct sts3032 *sts, uint8_t id, uint8_t *data, uint8_t len, uint8_t fun, uint8_t reply)
293 {
294  uint8_t buf[BUF_MAX_LENGHT];
295  uint8_t checksum = id + fun + len + 2;
296 
297  buf[0] = reply; // wait for a reply to this message?
298 
299  buf[1] = 0xff;
300  buf[2] = 0xff;
301  buf[3] = id;
302  buf[4] = 2 + len;
303  buf[5] = fun;
304  memcpy(&buf[6], data, len);
305  for (int i = 0; i < len; i++) {
306  checksum += data[i];
307  }
308  buf[len + 6] = ~checksum;
309 
310  circular_buffer_put(&sts->msg_buf, buf, len + 7);
311 }
312 
313 
314 /******************** settings handlers **********************/
315 void actuators_sts3032_set_id(float future_id)
316 {
317  sts3032_future_id = (int)(future_id + 0.5);
319 }
320 
322 {
323  sts3032_lock_eprom = (int)(lock + 0.5);
325 }
326 
328 {
329  sts3032_move = pos;
331 }
332 
334 {
335  sts3032_response_level = (int)(level + 0.5);
337 }
338 
339 /************************************************************/
void actuators_sts3032_set_id(float future_id)
int sts3032_response_level
void actuators_sts3032_init(void)
struct sts3032 sts
void sts3032_enable_torque(struct sts3032 *sts, uint8_t id, uint8_t enable)
static void write_buf(struct sts3032 *sts, uint8_t id, uint8_t *data, uint8_t len, uint8_t fun, uint8_t reply)
uint8_t cbuf[50 *SERVOS_STS3032_NB]
void actuators_sts3032_set_response_level(float level)
void sts3032_write_pos(struct sts3032 *sts, uint8_t id, int16_t position)
int sts3032_current_id
#define STS3032_RESPONSE_LEVEL
int sts3032_enabled
void sts3032_read_mem(struct sts3032 *sts, uint8_t id, uint8_t addr, uint8_t len)
void sts3032_lock_eeprom(struct sts3032 *sts, uint8_t id, uint8_t lock)
void sts3032_read_pos(struct sts3032 *sts, uint8_t id)
void actuators_sts3032_event(void)
int sts3032_lock_eprom
void actuators_sts3032_move(float pos)
int sts3032_future_id
void sts3032_init(struct sts3032 *sts, struct uart_periph *periph, uint8_t *cbuf, size_t cbuf_len)
void actuators_sts3032_lock_eprom(float lock)
#define STS3032_DELAY_MSG
uint8_t id_idx(struct sts3032 *sts, uint8_t id)
#define STS3032_DELAY_MSG_MIN
#define BUF_MAX_LENGHT
void actuators_sts3032_periodic(void)
static void handle_reply(struct sts3032 *sts, uint8_t id, uint8_t state, uint8_t *buf_param, uint8_t length)
void sts3032_set_id(struct sts3032 *sts, uint8_t id, uint8_t new_id)
uint8_t buf_rx_param[255]
static void sts3032_event(struct sts3032 *sts)
void sts3032_set_response_level(struct sts3032 *sts, uint8_t id, uint8_t level)
int sts3032_move
uint8_t rx_checksum
uint8_t buf_header[2]
uint8_t rx_id
uint8_t nb_bytes_expected
uint16_t pos[SERVOS_STS3032_NB]
uint8_t states[SERVOS_STS3032_NB]
uint32_t time_last_msg
struct uart_periph * periph
uint16_t nb_failed_checksum
enum sts3032_rx_state rx_state
struct circular_buffer msg_buf
uint8_t ids[SERVOS_STS3032_NB]
@ STS3032_RX_IDLE
@ STS3032_RX_HEAD_OK
@ STS3032_RX_GOT_LENGTH
uint8_t read_addr
static uint8_t checksum
Definition: airspeed_uADC.c:61
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:71
void circular_buffer_init(struct circular_buffer *cb, uint8_t *buffer, size_t len)
initialize a circular buffer.
int circular_buffer_put(struct circular_buffer *cb, uint8_t *buf, size_t len)
Copy buf in the circular buffer.
int circular_buffer_get(struct circular_buffer *cb, uint8_t *buf, size_t len)
copy the next buffer available in cb to buf.
static const float offset[]
struct State state
Definition: state.c:36
int uart_char_available(struct uart_periph *p)
Check UART for available chars in receive buffer.
Definition: uart_arch.c:323
uint8_t uart_getch(struct uart_periph *p)
Definition: uart_arch.c:314
#define INST_WRITE
Definition: sts3032_regs.h:6
#define SMS_STS_RESPONSE_LEVEL
Definition: sts3032_regs.h:30
#define SMS_STS_TORQUE_ENABLE
Definition: sts3032_regs.h:42
#define INST_READ
Definition: sts3032_regs.h:5
#define SMS_STS_GOAL_POSITION_L
Definition: sts3032_regs.h:44
#define SMS_STS_PRESENT_POSITION_L
Definition: sts3032_regs.h:53
#define SMS_STS_ID
Definition: sts3032_regs.h:28
#define SMS_STS_LOCK
Definition: sts3032_regs.h:50
Architecture independent timing functions.
Periodic telemetry system header (includes downlink utility and generated code).
void WEAK uart_put_buffer(struct uart_periph *p, long fd, const uint8_t *data, uint16_t len)
Definition: uart.c:266
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
UART peripheral.
Definition: uart.h:72
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
short int16_t
Typedef defining 16 bit short type.
Definition: vl53l1_types.h:93
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98
enum navigation_state current_state
Definition: wedgebug.c:217