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_faulhaber.c
Go to the documentation of this file.
1/*
2 * Copyright (C) Freek van Tienen <freek.v.tienen@gmail.com>
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 "mcu_periph/uart.h"
29#include "mcu_periph/sys_time.h"
31#include "modules/core/abi.h"
32#include <stdio.h>
33#include <string.h>
34
35/* Proportional gain on the velocity for the position controller */
36#ifndef FAULHABER_P_GAIN
37#define FAULHABER_P_GAIN 0.07
38#endif
39
40/* Maximum velocity for the position controller */
41#ifndef FAULHABER_MAX_VELOCITY
42#define FAULHABER_MAX_VELOCITY 12000
43#endif
44
46
47/* Faulhaber message parser */
60
61#define Polynom 0xD5
63{
64 uint8_t i;
65 u8CRC = u8CRC ^ u8Byte;
66 for (i = 0; i < 8; i++) {
67 if (u8CRC & 0x01) {
68 u8CRC = (u8CRC >> 1) ^ Polynom;
69 } else {
70 u8CRC >>= 1;
71 }
72 }
73 return u8CRC;
74}
75
76static void faulhaber_send_command(struct uart_periph *dev, uint8_t cmd_code, uint8_t *data, uint8_t data_length)
77{
78 uart_put_byte(dev, 0, 'S'); // Character (S) as Start of Frame
79 uart_put_byte(dev, 0, data_length + 4); // Telegram length without SOF/EOF (packet length)
80 uint8_t crc8 = faulhaber_crc8(data_length + 4, 0xFF); // Start CRC with 0xFF
81 uart_put_byte(dev, 0, 0x01); // Node number of the slave (0 = Broadcast)
82 crc8 = faulhaber_crc8(0x01, crc8);
83 uart_put_byte(dev, 0, cmd_code); // See Tab. 2
84 crc8 = faulhaber_crc8(cmd_code, crc8);
85 for (uint8_t i = 0; i < data_length; i++) { // Data area (length = packet length – 4)
86 uart_put_byte(dev, 0, data[i]);
87 crc8 = faulhaber_crc8(data[i], crc8);
88 }
89 uart_put_byte(dev, 0, crc8); // CRC8 with polynomial 0xD5 over byte 2–N
90 uart_put_byte(dev, 0, 'E'); // Character (E) as End of Frame
92}
93
94#define UINIT 0
95#define GOT_SOF 1
96#define GOT_LENGTH 2
97#define GOT_NODE_NB 3
98#define GET_DATA 4
99#define GET_CRC 5
100#define GET_EOF 6
101#define GOT_FULL_PACKET 7
102
104{
105 switch (p->state) {
106 case UINIT:
107 if (c == 'S') {
108 p->state = GOT_SOF;
109 p->calc_crc8 = 0xFF;
110 }
111 break;
112 case GOT_SOF:
113 if (c - 4 < 0) {
114 p->state = UINIT;
115 } else {
116 p->data_length = c - 4;
117 p->calc_crc8 = faulhaber_crc8(c, p->calc_crc8);
118 p->state = GOT_LENGTH;
119 }
120 break;
121 case GOT_LENGTH:
122 p->node_nb = c;
123 p->calc_crc8 = faulhaber_crc8(c, p->calc_crc8);
124 p->state = GOT_NODE_NB;
125 break;
126 case GOT_NODE_NB:
127 p->cmd_code = c;
128 p->data_idx = 0;
129 p->calc_crc8 = faulhaber_crc8(c, p->calc_crc8);
130 p->state = GET_DATA;
131 break;
132 case GET_DATA:
133 p->data[p->data_idx++] = c;
134 p->calc_crc8 = faulhaber_crc8(c, p->calc_crc8);
135 if (p->data_idx >= p->data_length) {
136 p->state = GET_CRC;
137 }
138 break;
139 case GET_CRC:
140 if (p->calc_crc8 == c) {
141 p->state = GET_EOF;
142 } else {
143 p->state = UINIT;
144 }
145 break;
146 case GET_EOF:
147 if (c == 'E') {
148 p->state = GOT_FULL_PACKET;
149 } else {
150 p->state = UINIT;
151 }
152 break;
153 default:
154 p->state = UINIT;
155 break;
156 }
157}
158
159// Controlword 0x6040.00
160// <Statusword 0x6041.00
161// 0x6060 (Mode of Operation) (6: HOME, 1: PP)
162// <0x6061.00(Mode of Operation feedback)
163// 0x607A.00 (Target Position)
164// <0x607A.00 (Actual Position)
165// Start positioning via the rising edge in bit 4 of the controlword. Also set the optional bits here.
166
181
183{
184 static float last_time = 0;
185 switch (faulhaber.mode) {
186
187 /* Initialize and home the motor */
188 case FH_MODE_INIT:
189 switch(faulhaber.state) {
190 case 0: {
191 // Start the controller boot timer
194 break;
195 }
196 case 1: {
197 // Check if the controller is ready, 5 seconds delay
198 if (get_sys_time_float() - last_time < 5.0)
199 break;
200
201 // Enable power on the motor
202 static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0E, 0x00}; // Set 0x6040.00 to 0x000E: Try to start
206 break;
207 }
208 case 2: {
209 // Wait 10ms for the next command
210 if(get_sys_time_float() - last_time < 0.01)
211 break;
212
213 // Set to homing mode
214 static uint8_t data[] = { 0x60, 0x60, 0x00, 0x06 }; // Set 0x6060.00 to 0x06: Homing mode
218 break;
219 }
220 case 3: {
221 // Wait 10ms for the next command
222 if(get_sys_time_float() - last_time < 0.01)
223 break;
224
225 // Set the homing method
226 static uint8_t data[] = { 0x98, 0x60, 0x00, 0x11 }; // Set 0x6098.00 to 0x11: Homing method to 17
230 break;
231 }
232 case 4: {
233 // Wait 10ms for the next command
234 if(get_sys_time_float() - last_time < 0.01)
235 break;
236
237 // Enable operation
238 static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
242 break;
243 }
244 case 5: {
245 // Wait 10ms for the next command
246 if(get_sys_time_float() - last_time < 0.01)
247 break;
248
249 // Start moving
250 static uint8_t data[] = { 0x40, 0x60, 0x00, 0x1F, 0x00}; // Set 0x6040.00 to 0x001F: Start moving
254 break;
255 }
256 case 6: {
257 // Check if homing is completed
259 // Continue initialization
262 }
263 // Timeout after 40 seconds
264 else if(get_sys_time_float() - last_time > 40.0) {
266 faulhaber.state = 0;
267 }
268 break;
269 }
270 case 7: {
271 // Wait 10ms for the next command
272 if(get_sys_time_float() - last_time < 0.01)
273 break;
274
275 // Set to velocity mode
276 static uint8_t data[] = { 0x60, 0x60, 0x00, 0x03 }; // Set 0x6060.00 to 0x03: Velocity mode
280 break;
281 }
282 case 8: {
283 // Wait 10ms for the next command
284 if(get_sys_time_float() - last_time < 0.01)
285 break;
286
287 // Enable operation
288 static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
292 break;
293 }
294 case 9: {
295 // Wait 10ms for the next command
296 if(get_sys_time_float() - last_time < 0.01)
297 break;
298
299 // Go to position mode
301 faulhaber.state = 0;
302 }
303 }
304 break;
305
306 /* FH_MODE_VELOCITY */
307 case FH_MODE_VELOCITY: {
308 // Request position and set the new velocity target
309 switch (faulhaber.state) {
310 case 0: {
311 // Request the position
312 uint8_t data[] = { 0x64, 0x60, 0x00}; // Get 0x6064.00: Get the actual position
315 break;
316 }
317 default: {
318 // Calculate the new velocity target
322
323 // Set the new velocity target
324 uint8_t data[] = { 0xFF, 0x60, 0x00, (faulhaber.target_velocity & 0xFF), ((faulhaber.target_velocity >> 8) & 0xFF), ((faulhaber.target_velocity >> 16) & 0xFF), ((faulhaber.target_velocity >> 24) & 0xFF) }; // Set 0x60FF.00 to [velocity]: Target velocity
326 faulhaber.state = 0;
327 break;
328 }
329 }
330 break;
331 }
332
333 /* FH_MODE_REQ_ERR */
334 case FH_MODE_REQ_ERR: {
335 switch(faulhaber.state) {
336 case 0: {
337 // Request the status code
338 uint8_t data[] = { 0x20, 0x23, 0x00}; // Get 0x2320.00: Get the error code
341 break;
342 }
343 case 1: {
344 // Request the status code
345 uint8_t data[] = { 0x21, 0x23, 0x00}; // Get 0x2321.00: Get the error mask
348 break;
349 }
350 case 2: {
351 // Request the status code
352 uint8_t data[] = { 0x01, 0x10, 0x00}; // Get 0x1001.00: Get the error mask
355 break;
356
357 }
358 default: {
359 // Do nothing and stop requesting
360 break;
361 }
362 }
363 break;
364 }
365
366 /* FH_MODE_RESET_ERR */
367 case FH_MODE_RESET_ERR: {
368 switch(faulhaber.state) {
369 case 0: {
370 static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0E, 0x00}; // Set 0x6040.00 to 0x000E: Try to start
373 break;
374 }
375 case 1: {
376 static uint8_t data[] = { 0x60, 0x60, 0x00, 0x03 }; // Set 0x6060.00 to 0x03: Velocity mode
379 break;
380 }
381 default: {
382 // Enable operation
383 static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
385 faulhaber.state = 0;
387 break;
388 }
389 }
390 break;
391 }
392
393 /* Do nothing */
394 default:
395 break;
396 }
397
398}
399
401{
402 // Process position message
403 if (p->cmd_code == 0x01 && p->data[0] == 0x64 && p->data[1] == 0x60 && p->data[2] == 0x00) {
404 faulhaber.real_position = p->data[3] | (p->data[4] << 8) | (p->data[5] << 16) | (p->data[6] << 24);
405
406 struct act_feedback_t feedback = {0};
408 0) - get_servo_min_FAULHABER(0)) * M_PI_2; // In radians
409 feedback.set.position = true;
410 feedback.idx = get_servo_idx_FAULHABER(0);
411
412 // Send ABI message
414 }
415 // Write requests
416 else if(p->cmd_code == 0x02) {
417 // Do nothing
418 }
419 // Parse the statuscode message
420 else if(p->cmd_code == 0x05) {
421 uint16_t status_code = p->data[0] | (p->data[1] << 8);
422
423 // Homing
424 if(!faulhaber.homing_completed && status_code&0x1000 && status_code&0x400)
426
427 // Position accepted
430
431 // Target reached
434
435 // If the drive got disabled
436 if(!(status_code&0x0001) || !(status_code&0x0002) || !(status_code&0x0004)) {
437 char error_msg[250];
438 int rc = snprintf(error_msg, 200, "[FH]%d %04X", p->cmd_code, status_code);
440 }
441 }
442 else {
443 // Unknown message
444 char error_msg[250];
445 int rc = snprintf(error_msg, 200, "[FH]%d ", p->cmd_code);
446 for(int i = 0; i < p->data_length; i++) {
447 rc += snprintf(error_msg + rc, 200 - rc, "%02X", p->data[i]);
448 }
449
450 if (rc > 0) {
452 }
453 }
454}
455
456
467
Main include for ABI (AirBorneInterface).
#define ACT_FEEDBACK_FAULHABER_ID
static void faulhaber_send_command(struct uart_periph *dev, uint8_t cmd_code, uint8_t *data, uint8_t data_length)
static struct uart_periph * faulhaber_dev
#define GET_DATA
#define GOT_FULL_PACKET
static uint8_t faulhaber_crc8(uint8_t u8Byte, uint8_t u8CRC)
void actuators_faulhaber_event(void)
struct faulhaber_t faulhaber
#define UINIT
#define GOT_LENGTH
#define GET_CRC
#define GOT_NODE_NB
#define FAULHABER_MAX_VELOCITY
#define Polynom
static void faulhaber_parser(struct faulhaber_parser_t *p, uint8_t c)
#define GET_EOF
static struct faulhaber_parser_t faulhaber_p
#define FAULHABER_P_GAIN
static void faulhaber_parse_msg(struct faulhaber_parser_t *p)
void actuators_faulhaber_periodic(void)
void actuators_faulhaber_init(void)
#define GOT_SOF
void actuators_faulhaber_SetMode(uint8_t mode)
float p_gain
The proportional gain of the velocity controller.
int32_t max_velocity
The maximum velocity of the controller.
int32_t real_position
The real position from the feedback of the controller.
#define ACTUATORS_FAULHABER_COMMAND_SCALE
bool target_reached
When the target position is reached.
enum faulhaber_modes_t mode
Current mode of the controller.
bool homing_completed
Once the homing is completed.
int32_t setpoint_position
The setpoint position controlled from the actuator.
int32_t target_velocity
The target velocity send to the controller.
uint8_t state
The state of the mode.
bool position_ready
Ready for receiving (new) positions.
@ FH_MODE_ERROR
@ FH_MODE_VELOCITY
@ FH_MODE_RESET_ERR
@ FH_MODE_REQ_ERR
@ FH_MODE_INIT
static float last_time
static float p[2][2]
void uart_put_byte(struct uart_periph *periph, long fd, uint8_t data)
Definition uart_arch.c:306
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
bool position
Position is set.
Definition actuators.h:48
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
float position
In radians.
Definition actuators.h:52
static uint8_t mode
mode holds the current sonar mode mode = 0 used at high altitude, uses 16 wave patterns mode = 1 used...
Definition sonar_bebop.c:65
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
Architecture independent timing functions.
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition sys_time.h:138
void WEAK uart_send_message(struct uart_periph *p, long fd)
Definition uart.c:170
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
UART peripheral.
Definition uart.h:72
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.