Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
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
47struct sts3032 sts;
48uint8_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 *********/
68int sts3032_move = 1024;
70/**********************************/
71
72
73static void sts3032_event(struct sts3032 *sts);
74static void write_buf(struct sts3032 *sts, uint8_t id, uint8_t *data, uint8_t len, uint8_t fun, uint8_t reply);
75static void handle_reply(struct sts3032 *sts, uint8_t id, uint8_t state, uint8_t *buf_param, uint8_t length);
76
77void sts3032_write_pos(struct sts3032 *sts, uint8_t id, int16_t position);
78void sts3032_event(struct sts3032 *sts);
79void sts3032_read_mem(struct sts3032 *sts, uint8_t id, uint8_t addr, uint8_t len);
80void sts3032_init(struct sts3032 *sts, struct uart_periph *periph, uint8_t *cbuf, size_t cbuf_len);
81void sts3032_read_pos(struct sts3032 *sts, uint8_t id);
83void sts3032_lock_eeprom(struct sts3032 *sts, uint8_t id, uint8_t lock);
86
87
99
101{
103}
104
106{
107
108 for (int i = 0; i < SERVOS_STS3032_NB; 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 }
119#endif
120
121}
122
124{
125 if (sts3032_enabled) {
126 sts3032_write_pos(&sts, sts.ids[idx], value);
127 }
128}
129
130
131static void sts3032_event(struct sts3032 *sts)
132{
133
136 if ((!sts->wait_reply && dt > STS3032_DELAY_MSG_MIN) || dt > STS3032_DELAY_MSG) {
138 int size = circular_buffer_get(&sts->msg_buf, buf, BUF_MAX_LENGHT);
139 if (size > 0) {
140 // first byte of the buffer indicate whether or not a replay is expected
141 // the rest is the message itself
142 uart_put_buffer(sts->periph, 0, buf + 1, size - 1);
143 sts->wait_reply = buf[0];
145 sts->echo = true;
146 }
147 }
148
150 switch (sts->rx_state) {
151 case STS3032_RX_IDLE:
152 if (uart_char_available(sts->periph) > 0) {
153 sts->buf_header[1] = sts->buf_header[0];
155 if (sts->buf_header[0] == 0xFF && sts->buf_header[1] == 0xFF) {
158 sts->buf_header[0] = 0;
159 sts->buf_header[1] = 0;
160 }
161 }
162 break;
169 }
170 break;
175 for (int i = 0; i < sts->nb_bytes_expected - 2; i++) {
178 }
180 sts->rx_checksum = ~sts->rx_checksum;
181 if (sts->rx_checksum == checksum) {
182 if (!sts->echo) {
184 }
185 } else {
187 }
188 sts->echo = false;
191 }
192 break;
193 default:
194 break;
195 }
196 }
197}
198
200{
201 uint8_t index = id_idx(sts, id);
202 if (index == 255) {
203 return;
204 }
205 sts->states[index] = state;
206 uint8_t offset = 0;
207 while (length > offset) {
208
209 switch (sts->read_addr + offset) {
211 if (offset + 2 < length) {
212 return;
213 }
214 sts->pos[index] = buf_param[offset] | (buf_param[offset + 1] << 8);
215 offset += 2;
216 break;
217
218 default:
219 offset++;
220 break;
221 }
222 }
223}
224
225
227{
228 for (int i = 0; i < SERVOS_STS3032_NB; i++) {
229 if (sts->ids[i] == id) {
230 return i;
231 }
232 }
233 return 255;
234}
235
236
238{
239 // lock = 0: unlock eeprom
240 // lock = 1: lock eeprom
241 uint8_t buf[2];
242 buf[0] = SMS_STS_LOCK;
243 buf[1] = lock;
245}
246
248{
249 // response level: 0: reply only on read and ping
250 // 1: always repond
251 uint8_t buf[2];
252 buf[0] = SMS_STS_RESPONSE_LEVEL;
253 buf[1] = level;
255}
256
258{
259 uint8_t buf[2];
260 buf[0] = SMS_STS_ID;
261 buf[1] = new_id;
263}
264
265void sts3032_write_pos(struct sts3032 *sts, uint8_t id, int16_t position)
266{
267 if (position < 0) {
268 position = -position;
269 position |= (1 << 15);
270 }
271 uint8_t buf[3];
273 buf[1] = position & 0xff;
274 buf[2] = position >> 8;
276}
277
279{
280 uint8_t buf[2];
281 buf[0] = SMS_STS_TORQUE_ENABLE;
282 buf[1] = enable;
284}
285
290
291void sts3032_read_mem(struct sts3032 *sts, uint8_t id, uint8_t addr, uint8_t len)
292{
293 uint8_t buf[2] = {addr, len};
294 write_buf(sts, id, buf, 2, INST_READ, 1);
295 sts->read_addr = addr;
296}
297
298static void write_buf(struct sts3032 *sts, uint8_t id, uint8_t *data, uint8_t len, uint8_t fun, uint8_t reply)
299{
301 uint8_t checksum = id + fun + len + 2;
302
303 buf[0] = reply; // wait for a reply to this message?
304
305 buf[1] = 0xff;
306 buf[2] = 0xff;
307 buf[3] = id;
308 buf[4] = 2 + len;
309 buf[5] = fun;
310 memcpy(&buf[6], data, len);
311 for (int i = 0; i < len; i++) {
312 checksum += data[i];
313 }
314 buf[len + 6] = ~checksum;
315
316 circular_buffer_put(&sts->msg_buf, buf, len + 7);
317}
318
319
320/******************** settings handlers **********************/
326
332
338
344
345/************************************************************/
void actuators_sts3032_set_id(float future_id)
void actuators_sts3032_set(uint8_t idx, int16_t value)
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
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
int circular_buffer_put(struct circular_buffer *cb, const uint8_t *buf, size_t len)
Copy buf in the circular buffer.
void circular_buffer_init(struct circular_buffer *cb, uint8_t *buffer, size_t len)
initialize a 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:357
uint8_t uart_getch(struct uart_periph *p)
Definition uart_arch.c:348
uint16_t foo
Definition main_demo5.c:58
static uint32_t idx
#define INST_WRITE
Definition sts3032_regs.h:6
#define SMS_STS_RESPONSE_LEVEL
#define SMS_STS_TORQUE_ENABLE
#define INST_READ
Definition sts3032_regs.h:5
#define SMS_STS_GOAL_POSITION_L
#define SMS_STS_PRESENT_POSITION_L
#define SMS_STS_ID
#define SMS_STS_LOCK
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:161
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.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
enum navigation_state current_state
Definition wedgebug.c:217