Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
actuators_dshot_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2018 Gautier Hattenberger <gautier.hattenberger@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 
30 #include "modules/core/abi.h"
31 #include "mcu_periph/ram_arch.h"
32 #include "mcu_periph/gpio.h"
33 #include BOARD_CONFIG
34 
35 #if PERIODIC_TELEMETRY
38 #endif
39 
40 struct dshot_private {
43 };
44 
47 
48 #if DSHOT_CONF_TIM1
49 static DSHOTDriver DSHOTD1;
50 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot1DmaBuffer);
51 #if DSHOT_BIDIR
52 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot1DmaCaptureBuffer);
53 #endif
54 static DSHOTConfig dshotcfg1 = DSHOT_CONF1_DEF;
55 #endif
56 #if DSHOT_CONF_TIM2
57 static DSHOTDriver DSHOTD2;
58 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot2DmaBuffer);
59 #if DSHOT_BIDIR
60 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot2DmaCaptureBuffer);
61 #endif
62 static DSHOTConfig dshotcfg2 = DSHOT_CONF2_DEF;
63 #endif
64 #if DSHOT_CONF_TIM3
65 static DSHOTDriver DSHOTD3;
66 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot3DmaBuffer);
67 #if DSHOT_BIDIR
68 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot3DmaCaptureBuffer);
69 #endif
70 static DSHOTConfig dshotcfg3 = DSHOT_CONF3_DEF;
71 #endif
72 #if DSHOT_CONF_TIM4
73 static DSHOTDriver DSHOTD4;
74 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot4DmaBuffer);
75 #if DSHOT_BIDIR
76 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot4DmaCaptureBuffer);
77 #endif
78 static DSHOTConfig dshotcfg4 = DSHOT_CONF4_DEF;
79 #endif
80 #if DSHOT_CONF_TIM5
81 static DSHOTDriver DSHOTD5;
82 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot5DmaBuffer);
83 #if DSHOT_BIDIR
84 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot5DmaCaptureBuffer);
85 #endif
86 static DSHOTConfig dshotcfg5 = DSHOT_CONF5_DEF;
87 #endif
88 #if DSHOT_CONF_TIM8
89 static DSHOTDriver DSHOTD8;
90 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot8DmaBuffer);
91 #if DSHOT_BIDIR
92 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot8DmaCaptureBuffer);
93 #endif
94 static DSHOTConfig dshotcfg8 = DSHOT_CONF8_DEF;
95 #endif
96 #if DSHOT_CONF_TIM9
97 static DSHOTDriver DSHOTD9;
98 static IN_DMA_SECTION_NOINIT(DshotDmaBuffer dshot9DmaBuffer);
99 #if DSHOT_BIDIR
100 static IN_DMA_SECTION_NOINIT(DshotRpmCaptureDmaBuffer dshot9DmaCaptureBuffer);
101 #endif
102 static DSHOTConfig dshotcfg9 = DSHOT_CONF9_DEF;
103 #endif
104 
105 #if PERIODIC_TELEMETRY
106 static void esc_msg_send(struct transport_tx *trans, struct link_device *dev) {
107  for (uint8_t i = 0; i < ACTUATORS_DSHOT_NB; i++) {
108  if (actuators_dshot_values[i].activated) {
110 
111  actuators_dshot_values[i].current = (float)dtelem.frame.current * 0.01f;
112  actuators_dshot_values[i].voltage = (float)dtelem.frame.voltage * 0.01f;
113  actuators_dshot_values[i].rpm = (float)dtelem.frame.rpm;
114 
115 #if DSHOT_BIDIR
116  const uint32_t erpm = dshotGetRpm(actuators_dshot_private[i].driver, actuators_dshot_private[i].channel);
117  if(erpm != DSHOT_BIDIR_ERR_CRC && erpm != DSHOT_BIDIR_TLM_EDT) {
118  actuators_dshot_values[i].rpm = (float) erpm;
119  }
120 #endif
121 
122  float bat_voltage = electrical.vsupply;
123  float power = actuators_dshot_values[i].current * bat_voltage;
124  float energy = (float)dtelem.frame.consumption;
125  float temp = dtelem.frame.temp;
126  float temp_dev = 0;
127  pprz_msg_send_ESC(trans, dev, AC_ID,
128  &actuators_dshot_values[i].current,
129  &bat_voltage,
130  &power,
132  &actuators_dshot_values[i].voltage,
133  &energy,
134  &temp,
135  &temp_dev,
136  &i,
137  &i);
138  }
139  }
140 }
141 #endif
142 
143 static void dshot_init_struct(struct dshot * ds)
144 {
145  ds->cmd = 0;
146  ds->rpm = 0;
147  ds->current = 0;
148  ds->voltage = 0;
149  ds->activated = false;
150 }
151 
152 static void dshot_set_struct(struct dshot * ds, struct dshot_private * dsp, DSHOTDriver * driver, uint32_t channel)
153 {
154  ds->activated = true;
155  dsp->driver = driver;
156  dsp->channel = channel;
157 }
158 
159 #define _CONCAT_GPIO(num, name) UART ## num ## _GPIO_ ## name
160 #define CONCAT_GPIO(num, name) _CONCAT_GPIO(num, name)
161 
163 {
164  // init dshot structure to zero
165  for (int i = 0; i < ACTUATORS_DSHOT_NB; i++) {
167  }
168 
169  // configure telemetry pin if needed
170  // the serial device interface might have to be activated
171  // by hand (ChibiOS HAL), but PPRZ one disabled
172 #ifdef DSHOT_TIM1_TELEMETRY_NUM
174  CONCAT_GPIO(DSHOT_TIM1_TELEMETRY_NUM, PORT_RX),
175  CONCAT_GPIO(DSHOT_TIM1_TELEMETRY_NUM, RX),
176  CONCAT_GPIO(DSHOT_TIM1_TELEMETRY_NUM, AF), FALSE);
177  PRINT_CONFIG_VAR(DSHOT_TIM1_TELEMETRY_NUM);
178 #endif
179 #ifdef DSHOT_TIM2_TELEMETRY_NUM
181  CONCAT_GPIO(DSHOT_TIM2_TELEMETRY_NUM, PORT_RX),
182  CONCAT_GPIO(DSHOT_TIM2_TELEMETRY_NUM, RX),
183  CONCAT_GPIO(DSHOT_TIM2_TELEMETRY_NUM, AF), FALSE);
184 #endif
185 #ifdef DSHOT_TIM3_TELEMETRY_NUM
187  CONCAT_GPIO(DSHOT_TIM3_TELEMETRY_NUM, PORT_RX),
188  CONCAT_GPIO(DSHOT_TIM3_TELEMETRY_NUM, RX),
189  CONCAT_GPIO(DSHOT_TIM3_TELEMETRY_NUM, AF), FALSE);
190 #endif
191 #ifdef DSHOT_TIM4_TELEMETRY_NUM
193  CONCAT_GPIO(DSHOT_TIM4_TELEMETRY_NUM, PORT_RX),
194  CONCAT_GPIO(DSHOT_TIM4_TELEMETRY_NUM, RX),
195  CONCAT_GPIO(DSHOT_TIM4_TELEMETRY_NUM, AF), FALSE);
196  PRINT_CONFIG_VAR(DSHOT_TIM4_TELEMETRY_NUM);
197 #endif
198 #ifdef DSHOT_TIM5_TELEMETRY_NUM
200  CONCAT_GPIO(DSHOT_TIM5_TELEMETRY_NUM, PORT_RX),
201  CONCAT_GPIO(DSHOT_TIM5_TELEMETRY_NUM, RX),
202  CONCAT_GPIO(DSHOT_TIM5_TELEMETRY_NUM, AF), FALSE);
203 #endif
204 #ifdef DSHOT_TIM8_TELEMETRY_NUM
206  CONCAT_GPIO(DSHOT_TIM8_TELEMETRY_NUM, PORT_RX),
207  CONCAT_GPIO(DSHOT_TIM8_TELEMETRY_NUM, RX),
208  CONCAT_GPIO(DSHOT_TIM8_TELEMETRY_NUM, AF), FALSE);
209 #endif
210 #ifdef DSHOT_TIM9_TELEMETRY_NUM
212  CONCAT_GPIO(DSHOT_TIM9_TELEMETRY_NUM, PORT_RX),
213  CONCAT_GPIO(DSHOT_TIM9_TELEMETRY_NUM, RX),
214  CONCAT_GPIO(DSHOT_TIM9_TELEMETRY_NUM, AF), FALSE);
215 #endif
216 
217  /*----------------
218  * Configure GPIO
219  *----------------*/
220 #ifdef DSHOT_SERVO_0
223 #endif
224 #ifdef DSHOT_SERVO_1
227 #endif
228 #ifdef DSHOT_SERVO_2
231 #endif
232 #ifdef DSHOT_SERVO_3
235 #endif
236 #ifdef DSHOT_SERVO_4
239 #endif
240 #ifdef DSHOT_SERVO_5
243 #endif
244 #ifdef DSHOT_SERVO_6
245  gpio_setup_pin_af_pullup(DSHOT_SERVO_6_GPIO, DSHOT_SERVO_6_PIN, DSHOT_SERVO_6_AF);
246  dshot_set_struct(&actuators_dshot_values[DSHOT_SERVO_6], &actuators_dshot_private[DSHOT_SERVO_6], &DSHOT_SERVO_6_DRIVER, DSHOT_SERVO_6_CHANNEL);
247 #endif
248 #ifdef DSHOT_SERVO_7
251 #endif
252 #ifdef DSHOT_SERVO_8
255 #endif
256 #ifdef DSHOT_SERVO_9
259 #endif
260 #ifdef DSHOT_SERVO_10
263 #endif
264 #ifdef DSHOT_SERVO_11
265  gpio_setup_pin_af_pullup(DSHOT_SERVO_11_GPIO, DSHOT_SERVO_11_PIN, DSHOT_SERVO_11_AF);
266  dshot_set_struct(&actuators_dshot_values[DSHOT_SERVO_11], &actuators_dshot_private[DSHOT_SERVO_11], &DSHOT_SERVO_11_DRIVER, DSHOT_SERVO_11_CHANNEL);
267 #endif
268 
269  /*---------------
270  * Configure DSHOT
271  *---------------*/
272 #if DSHOT_CONF_TIM1
273  dshotStart(&DSHOTD1, &dshotcfg1);
274 #endif
275 #if DSHOT_CONF_TIM2
276  dshotStart(&DSHOTD2, &dshotcfg2);
277 #endif
278 #if DSHOT_CONF_TIM3
279  dshotStart(&DSHOTD3, &dshotcfg3);
280 #endif
281 #if DSHOT_CONF_TIM4
282  dshotStart(&DSHOTD4, &dshotcfg4);
283 #endif
284 #if DSHOT_CONF_TIM5
285  dshotStart(&DSHOTD5, &dshotcfg5);
286 #endif
287 #if DSHOT_CONF_TIM8
288  dshotStart(&DSHOTD8, &dshotcfg8);
289 #endif
290 #if DSHOT_CONF_TIM9
291  dshotStart(&DSHOTD9, &dshotcfg9);
292 #endif
293 
294 #if PERIODIC_TELEMETRY
296 #endif
297 }
298 
299 
301 {
302 #ifdef DSHOT_SERVO_0
304 #endif
305 #ifdef DSHOT_SERVO_1
307 #endif
308 #ifdef DSHOT_SERVO_2
310 #endif
311 #ifdef DSHOT_SERVO_3
313 #endif
314 #ifdef DSHOT_SERVO_4
316 #endif
317 #ifdef DSHOT_SERVO_5
319 #endif
320 #ifdef DSHOT_SERVO_6
321  dshotSetThrottle(&DSHOT_SERVO_6_DRIVER, DSHOT_SERVO_6_CHANNEL, actuators_dshot_values[DSHOT_SERVO_6].cmd);
322 #endif
323 #ifdef DSHOT_SERVO_7
325 #endif
326 #ifdef DSHOT_SERVO_8
328 #endif
329 #ifdef DSHOT_SERVO_9
331 #endif
332 #ifdef DSHOT_SERVO_10
334 #endif
335 #ifdef DSHOT_SERVO_11
336  dshotSetThrottle(&DSHOT_SERVO_11_DRIVER, DSHOT_SERVO_11_CHANNEL, actuators_dshot_values[DSHOT_SERVO_11].cmd);
337 #endif
338 
339 #if DSHOT_CONF_TIM1
340  dshotSendFrame(&DSHOTD1);
341 #endif
342 #if DSHOT_CONF_TIM2
343  dshotSendFrame(&DSHOTD2);
344 #endif
345 #if DSHOT_CONF_TIM3
346  dshotSendFrame(&DSHOTD3);
347 #endif
348 #if DSHOT_CONF_TIM4
349  dshotSendFrame(&DSHOTD4);
350 #endif
351 #if DSHOT_CONF_TIM5
352  dshotSendFrame(&DSHOTD5);
353 #endif
354 #if DSHOT_CONF_TIM8
355  dshotSendFrame(&DSHOTD8);
356 #endif
357 #if DSHOT_CONF_TIM9
358  dshotSendFrame(&DSHOTD9);
359 #endif
360 
361 
362  struct act_feedback_t feedback[ACTUATORS_DSHOT_NB] = { 0 };
363  for (uint8_t i = 0; i < ACTUATORS_DSHOT_NB; i++) {
364  feedback[i].idx = get_servo_idx_DSHOT(i);
365  if (actuators_dshot_values[i].activated) {
367  feedback[i].rpm = dtelem.frame.rpm;
368  feedback[i].set.rpm = true;
369 #if DSHOT_BIDIR
370  const uint32_t erpm = dshotGetRpm(actuators_dshot_private[i].driver, actuators_dshot_private[i].channel);
371  if(erpm != DSHOT_BIDIR_ERR_CRC) {
372  if(erpm != DSHOT_BIDIR_TLM_EDT) {
373  feedback[i].rpm = (float) erpm;
374  feedback[i].set.rpm = true;
375  }
376  } else {
377  feedback[i].set.rpm = false;
378  }
379 #endif
380  }
381  }
382  AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_DSHOT_ID, feedback, ACTUATORS_DSHOT_NB);
383 }
Main include for ABI (AirBorneInterface).
#define ACT_FEEDBACK_DSHOT_ID
bool activated
current dshot channel is activated
float cmd
command
float current
current
float voltage
motor current
#define ACTUATORS_DSHOT_NB
Maxnum number of DSHOT commands This should be large enough for max applications: 8 motors +1 in case...
float rpm
rpm
#define DSHOT_SERVO_2_GPIO
Definition: board.h:353
#define DSHOT_SERVO_4_DRIVER
Definition: board.h:328
#define DSHOT_SERVO_2_CHANNEL
Definition: board.h:357
#define DSHOT_SERVO_2_AF
Definition: board.h:355
#define DSHOT_SERVO_5_DRIVER
Definition: board.h:334
#define DSHOT_SERVO_0_AF
Definition: board.h:349
#define DSHOT_SERVO_3_GPIO
Definition: board.h:359
#define DSHOT_CONF2_DEF
Definition: board.h:337
#define DSHOT_SERVO_2
Definition: board.h:352
#define DSHOT_SERVO_5_GPIO
Definition: board.h:331
#define DSHOT_SERVO_5
Definition: board.h:330
#define DSHOT_SERVO_1_DRIVER
Definition: board.h:322
#define DSHOT_SERVO_0_PIN
Definition: board.h:348
#define DSHOT_SERVO_1_PIN
Definition: board.h:320
#define DSHOT_SERVO_0_DRIVER
Definition: board.h:350
#define DSHOT_SERVO_3_PIN
Definition: board.h:360
#define DSHOT_SERVO_1_AF
Definition: board.h:321
#define DSHOT_SERVO_5_CHANNEL
Definition: board.h:335
#define DSHOT_CONF3_DEF
Definition: board.h:374
#define DSHOT_SERVO_0_CHANNEL
Definition: board.h:351
#define DSHOT_SERVO_1
Definition: board.h:318
#define DSHOT_SERVO_1_GPIO
Definition: board.h:319
#define DSHOT_SERVO_3_CHANNEL
Definition: board.h:363
#define DSHOT_SERVO_4_PIN
Definition: board.h:326
#define DSHOT_SERVO_3
Definition: board.h:358
#define DSHOT_SERVO_2_PIN
Definition: board.h:354
#define DSHOT_SERVO_1_CHANNEL
Definition: board.h:323
#define DSHOT_SERVO_3_AF
Definition: board.h:361
#define DSHOT_SERVO_5_PIN
Definition: board.h:332
#define DSHOT_SERVO_4
Definition: board.h:324
#define DSHOT_SERVO_0_GPIO
Definition: board.h:347
#define DSHOT_SERVO_5_AF
Definition: board.h:333
#define DSHOT_SERVO_3_DRIVER
Definition: board.h:362
#define DSHOT_SERVO_4_CHANNEL
Definition: board.h:329
#define DSHOT_SERVO_2_DRIVER
Definition: board.h:356
#define DSHOT_SERVO_4_AF
Definition: board.h:327
#define DSHOT_SERVO_4_GPIO
Definition: board.h:325
#define DSHOT_SERVO_0
Definition: board.h:346
void gpio_setup_pin_af_pullup(ioportid_t port, uint16_t pin, uint8_t af)
Setup a gpio for input pullup with alternate function.
Definition: gpio_arch.c:61
void gpio_setup_pin_af(ioportid_t port, uint16_t pin, uint8_t af, bool is_output)
Setup a gpio for input or output with alternate function.
Definition: gpio_arch.c:65
void actuators_dshot_arch_init(void)
Arch dependent init.
struct dshot_private actuators_dshot_private[ACTUATORS_DSHOT_NB]
#define CONCAT_GPIO(num, name)
static void dshot_set_struct(struct dshot *ds, struct dshot_private *dsp, DSHOTDriver *driver, uint32_t channel)
struct dshot actuators_dshot_values[ACTUATORS_DSHOT_NB]
static void dshot_init_struct(struct dshot *ds)
static void esc_msg_send(struct transport_tx *trans, struct link_device *dev)
void actuators_dshot_arch_commit(void)
DSHOTDriver * driver
struct Electrical electrical
Definition: electrical.c:92
Interface for electrical status: supply voltage, current, battery status, etc.
float vsupply
supply voltage in V
Definition: electrical.h:45
void dshotStart(DSHOTDriver *driver, const DSHOTConfig *config)
Configures and activates the DSHOT peripheral.
Definition: esc_dshot.c:154
void dshotSetThrottle(DSHOTDriver *driver, const uint8_t index, const uint16_t throttle)
prepare throttle order for specified ESC
Definition: esc_dshot.c:301
DshotTelemetry dshotGetTelemetry(DSHOTDriver *driver, uint32_t index)
return last received telemetry data
Definition: esc_dshot.c:468
void dshotSendFrame(DSHOTDriver *driver)
send throttle order
Definition: esc_dshot.c:404
DSHOT driver based on ChibiOS.
DshotTelemetryFrame frame
Definition: esc_dshot.h:159
#define DSHOT_BIDIR_TLM_EDT
Definition: esc_dshot.h:66
#define DSHOT_BIDIR_ERR_CRC
special values returned by dshotGetRpm function
Definition: esc_dshot.h:65
DSHOT Driver configuration structure.
Definition: esc_dshot.h:182
telemetry with timestamp
Definition: esc_dshot.h:158
#define DSHOT_BIDIR
Some architecture independent helper functions for GPIOs.
#define DSHOT_SERVO_10_AF
#define DSHOT_SERVO_9_PIN
#define DSHOT_SERVO_9_DRIVER
#define DSHOT_SERVO_8
#define DSHOT_SERVO_7_GPIO
#define DSHOT_SERVO_8_CHANNEL
#define DSHOT_SERVO_8_AF
#define DSHOT_SERVO_8_PIN
#define DSHOT_SERVO_7_AF
#define DSHOT_SERVO_9_AF
#define DSHOT_SERVO_7_PIN
#define DSHOT_SERVO_10_PIN
#define DSHOT_SERVO_7_CHANNEL
#define DSHOT_SERVO_10_GPIO
#define DSHOT_SERVO_9_CHANNEL
#define DSHOT_CONF4_DEF
#define DSHOT_SERVO_9_GPIO
#define DSHOT_SERVO_10
#define DSHOT_SERVO_10_CHANNEL
#define DSHOT_SERVO_8_DRIVER
#define DSHOT_SERVO_8_GPIO
#define DSHOT_SERVO_9
#define DSHOT_SERVO_7_DRIVER
#define DSHOT_SERVO_10_DRIVER
#define DSHOT_SERVO_7
int32_t rpm
RPM.
Definition: actuators.h:51
struct act_feedback_t::act_feedback_set_t set
Bitset registering what is set as feedback.
uint8_t idx
General index of the actuators (generated in airframe.h)
Definition: actuators.h:45
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
Specific RAM section for DMA usage on F7.
#define IN_DMA_SECTION_NOINIT(var)
Definition: ram_arch.h:85
uint16_t rpm
Definition: rpm_sensor.c:33
#define FALSE
Definition: std.h:5
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
DSHOT driver structure.
Definition: esc_dshot.h:287
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98