Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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);
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
123
124
125static void sts3032_event(struct sts3032 *sts)
126{
127
130 if ((!sts->wait_reply && dt > STS3032_DELAY_MSG_MIN) || dt > STS3032_DELAY_MSG) {
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];
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) {
152 sts->buf_header[0] = 0;
153 sts->buf_header[1] = 0;
154 }
155 }
156 break;
163 }
164 break;
169 for (int i = 0; i < sts->nb_bytes_expected - 2; i++) {
172 }
174 sts->rx_checksum = ~sts->rx_checksum;
175 if (sts->rx_checksum == checksum) {
176 if (!sts->echo) {
178 }
179 } else {
181 }
182 sts->echo = false;
185 }
186 break;
187 default:
188 break;
189 }
190 }
191}
192
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
252{
253 uint8_t buf[2];
254 buf[0] = SMS_STS_ID;
255 buf[1] = new_id;
257}
258
259void 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];
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
284
285void 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
292static void write_buf(struct sts3032 *sts, uint8_t id, uint8_t *data, uint8_t len, uint8_t fun, uint8_t reply)
293{
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 **********************/
320
326
332
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
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
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:357
uint8_t uart_getch(struct uart_periph *p)
Definition uart_arch.c:348
uint16_t foo
Definition main_demo5.c:58
#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