mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-25 23:46:04 +08:00
[actuators] Update controller faulhaber (#3347)
This commit is contained in:
@@ -4,20 +4,18 @@
|
||||
<doc>
|
||||
<description>
|
||||
Actuators Driver for the Faulhaber controller
|
||||
Currently initialization is done manually.
|
||||
Set mode to:
|
||||
- 2
|
||||
- 4
|
||||
- 2 (it will home slowly)
|
||||
- Wait until homing is finished!
|
||||
- Back to 1 and the wing will move
|
||||
Based on the velocity controller inside the MC5004 controller, a simple position controller is implemented.
|
||||
</description>
|
||||
<configure name="FAULHABER_DEV" value="UARTX" description="UART port (default UART4)"/>
|
||||
<define name="FAULHABER_P_GAIN" value="0.07" description="Proportional gain for the position controller"/>
|
||||
<define name="FAULHABER_MAX_VELOCITY" value="14000" description="Maximum velocity for the position controller"/>
|
||||
</doc>
|
||||
<settings>
|
||||
<dl_settings>
|
||||
<dl_settings NAME="Faulhaber">
|
||||
<dl_setting var="faulhaber.mode" min="0" step="1" max="4" shortname="mode" module="modules/actuators/actuators_faulhaber" handler="SetMode"/>
|
||||
<dl_setting var="faulhaber.mode" min="0" step="1" max="3" shortname="mode" values="INIT|VELOCITY|ERROR" module="modules/actuators/actuators_faulhaber" handler="SetMode"/>
|
||||
<dl_setting var="faulhaber.p_gain" min="0" step="0.001" max="1"/>
|
||||
<dl_setting var="faulhaber.max_velocity" min="0" step="100" max="100000"/>
|
||||
<dl_setting var="faulhaber.setpoint_position" min="0" step="1000" max="3600000"/>
|
||||
<dl_setting var="faulhaber.real_position" min="0" step="1000" max="3300000"/>
|
||||
</dl_settings>
|
||||
@@ -32,6 +30,7 @@
|
||||
<file name="actuators_faulhaber.h"/>
|
||||
</header>
|
||||
<init fun="actuators_faulhaber_init()"/>
|
||||
<!-- Controller runs at half the speed of the periodic -->
|
||||
<periodic fun="actuators_faulhaber_periodic()" freq="50"/>
|
||||
<event fun="actuators_faulhaber_event()" />
|
||||
<makefile target="!sim">
|
||||
|
||||
@@ -32,8 +32,19 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Proportional gain on the velocity for the position controller */
|
||||
#ifndef FAULHABER_P_GAIN
|
||||
#define FAULHABER_P_GAIN 0.07
|
||||
#endif
|
||||
|
||||
/* Maximum velocity for the position controller */
|
||||
#ifndef FAULHABER_MAX_VELOCITY
|
||||
#define FAULHABER_MAX_VELOCITY 14000
|
||||
#endif
|
||||
|
||||
static struct uart_periph *faulhaber_dev = &(FAULHABER_DEV);
|
||||
|
||||
/* Faulhaber message parser */
|
||||
struct faulhaber_parser_t {
|
||||
uint8_t state;
|
||||
uint8_t node_nb;
|
||||
@@ -160,145 +171,164 @@ void actuators_faulhaber_init(void)
|
||||
faulhaber.mode = FH_MODE_INIT;
|
||||
faulhaber.state = 0;
|
||||
faulhaber.setpoint_position = 0;
|
||||
faulhaber.target_position = 0;
|
||||
faulhaber.real_position = 0;
|
||||
faulhaber.homing_completed = false;
|
||||
faulhaber.position_ready = false;
|
||||
faulhaber.target_reached = false;
|
||||
faulhaber.p_gain = FAULHABER_P_GAIN;
|
||||
faulhaber.max_velocity = FAULHABER_MAX_VELOCITY;
|
||||
}
|
||||
|
||||
|
||||
void actuators_faulhaber_periodic(void)
|
||||
{
|
||||
static float last_time = 0;
|
||||
switch (faulhaber.mode) {
|
||||
|
||||
/* HOME MODE */
|
||||
case FH_MODE_HOME:
|
||||
switch (faulhaber.state) {
|
||||
/* Initialize and home the motor */
|
||||
case FH_MODE_INIT:
|
||||
switch(faulhaber.state) {
|
||||
case 0: {
|
||||
// Set the homing mode
|
||||
uint8_t data[] = { 0x60, 0x60, 0x00, 0x06 }; // Set 0x6060.00 to 0x06: Homing mode
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 4);
|
||||
// Start the controller boot timer
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// Check if the controller is ready, 5 seconds delay
|
||||
if (get_sys_time_float() - last_time < 5.0)
|
||||
break;
|
||||
|
||||
// Enable power on the motor
|
||||
static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0E, 0x00}; // Set 0x6040.00 to 0x000E: Try to start
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Set to homing mode
|
||||
static uint8_t data[] = { 0x60, 0x60, 0x00, 0x06 }; // Set 0x6060.00 to 0x06: Homing mode
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 4);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Set the homing method
|
||||
uint8_t data[] = { 0x98, 0x60, 0x00, 0x11 }; // Set 0x6098.00 to 0x11: Homing method to 17
|
||||
static uint8_t data[] = { 0x98, 0x60, 0x00, 0x11 }; // Set 0x6098.00 to 0x11: Homing method to 17
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 4);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
case 4: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Enable operation
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
|
||||
static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
case 5: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Start moving
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x1F, 0x00}; // Set 0x6040.00 to 0x001F: Start moving
|
||||
static uint8_t data[] = { 0x40, 0x60, 0x00, 0x1F, 0x00}; // Set 0x6040.00 to 0x001F: Start moving
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Goto position mode
|
||||
faulhaber.mode = FH_MODE_INIT;
|
||||
faulhaber.state = 0;
|
||||
case 6: {
|
||||
// Check if homing is completed
|
||||
if(faulhaber.homing_completed) {
|
||||
// Continue initialization
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
}
|
||||
// Timeout after 40 seconds
|
||||
else if(get_sys_time_float() - last_time > 40.0) {
|
||||
faulhaber.mode = FH_MODE_ERROR;
|
||||
faulhaber.state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Set to position mode
|
||||
static uint8_t data[] = { 0x60, 0x60, 0x00, 0x03 }; // Set 0x6060.00 to 0x03: Velocity mode
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 4);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Enable operation
|
||||
static uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
last_time = get_sys_time_float();
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
// Wait 10ms for the next command
|
||||
if(get_sys_time_float() - last_time < 0.01)
|
||||
break;
|
||||
|
||||
// Go to position mode
|
||||
faulhaber.mode = FH_MODE_VELOCITY;
|
||||
faulhaber.state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* POSITION MODE */
|
||||
case FH_MODE_POSITION:
|
||||
/* FH_MODE_VELOCITY */
|
||||
case FH_MODE_VELOCITY: {
|
||||
// Request position and set the new velocity target
|
||||
switch (faulhaber.state) {
|
||||
case 0: {
|
||||
uint8_t data[] = { 0x60, 0x60, 0x00, 0x01 }; // Set 0x6060.00 to 0x01: Position mode
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 4);
|
||||
// Request the position
|
||||
uint8_t data[] = { 0x64, 0x60, 0x00}; // Get 0x6064.00: Get the actual position
|
||||
faulhaber_send_command(faulhaber_dev, 0x01, data, 3);
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// Set the target position
|
||||
faulhaber.target_position = faulhaber.setpoint_position;
|
||||
uint8_t data[] = { 0x7A, 0x60, 0x00, (faulhaber.target_position & 0xFF), ((faulhaber.target_position >> 8) & 0xFF), ((faulhaber.target_position >> 16) & 0xFF), ((faulhaber.target_position >> 24) & 0xFF) }; // Set 0x607A.00 to 0x00000000: Target position 0
|
||||
default: {
|
||||
// Calculate the new velocity target
|
||||
int32_t poss_err = (faulhaber.setpoint_position - faulhaber.real_position);
|
||||
faulhaber.target_velocity = poss_err * faulhaber.p_gain;
|
||||
BoundAbs(faulhaber.target_velocity, faulhaber.max_velocity);
|
||||
|
||||
// Set the new velocity target
|
||||
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
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 7);
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// Enable operation
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Enable operation
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// Start moving
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x3F, 0x00}; // Set 0x6040.00 to 0x003F: Start moving
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
faulhaber.state++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
faulhaber.mode = FH_MODE_IDLE;
|
||||
faulhaber.state = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* FH_MODE_IDLE */
|
||||
case FH_MODE_IDLE: {
|
||||
// Move to the new position
|
||||
if (faulhaber.target_position != faulhaber.setpoint_position) {
|
||||
faulhaber.mode = FH_MODE_POSITION;
|
||||
faulhaber.state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Request the position
|
||||
uint8_t data[] = { 0x64, 0x60, 0x00}; // Get 0x6064.00: Get the actual position
|
||||
faulhaber_send_command(faulhaber_dev, 0x01, data, 3);
|
||||
faulhaber.state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case FH_MODE_ENABLE:
|
||||
switch (faulhaber.state) {
|
||||
case 0: {
|
||||
// Disable drive
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x80, 0x00}; // Set 0x6040.00 to 0x0007: Disable drive
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
faulhaber.state++;
|
||||
//break;
|
||||
}
|
||||
case 1: {
|
||||
// Disable drive
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x06, 0x00}; // Set 0x6040.00 to 0x0006: Disable drive
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
faulhaber.state++;
|
||||
//break;
|
||||
}
|
||||
case 2: {
|
||||
// Enable drive
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x07, 0x00}; // Set 0x6040.00 to 0x0007: Enable drive
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
faulhaber.state++;
|
||||
//break;
|
||||
}
|
||||
case 3: {
|
||||
// Execute
|
||||
uint8_t data[] = { 0x40, 0x60, 0x00, 0x0F, 0x00}; // Set 0x6040.00 to 0x000F: Execute
|
||||
faulhaber_send_command(faulhaber_dev, 0x02, data, 5);
|
||||
faulhaber.state++;
|
||||
//break;
|
||||
}
|
||||
default:
|
||||
faulhaber.mode = FH_MODE_INIT;
|
||||
faulhaber.state = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Do nothing */
|
||||
default:
|
||||
break;
|
||||
@@ -321,6 +351,22 @@ static void faulhaber_parse_msg(struct faulhaber_parser_t *p)
|
||||
// Send ABI message
|
||||
AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_FAULHABER_ID, &feedback, 1);
|
||||
}
|
||||
// Parse the statuscode message
|
||||
else if(p->cmd_code == 0x05) {
|
||||
uint16_t status_code = p->data[0] | (p->data[1] << 8);
|
||||
|
||||
// Homing
|
||||
if(!faulhaber.homing_completed && status_code&0x1000 && status_code&0x400)
|
||||
faulhaber.homing_completed = true;
|
||||
|
||||
// Position accepted
|
||||
if(!faulhaber.position_ready && status_code&0x1000)
|
||||
faulhaber.position_ready = true;
|
||||
|
||||
// Target reached
|
||||
if(!faulhaber.target_reached && status_code&0x400)
|
||||
faulhaber.target_reached = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,19 +31,24 @@
|
||||
|
||||
enum faulhaber_modes_t {
|
||||
FH_MODE_INIT,
|
||||
FH_MODE_IDLE,
|
||||
FH_MODE_HOME,
|
||||
FH_MODE_POSITION,
|
||||
FH_MODE_ENABLE
|
||||
FH_MODE_VELOCITY,
|
||||
FH_MODE_ERROR
|
||||
};
|
||||
|
||||
struct faulhaber_t {
|
||||
enum faulhaber_modes_t mode;
|
||||
uint8_t state;
|
||||
enum faulhaber_modes_t mode; ///< Current mode of the controller
|
||||
uint8_t state; ///< The state of the mode
|
||||
|
||||
float p_gain; ///< The proportional gain of the velocity controller
|
||||
int32_t max_velocity; ///< The maximum velocity of the controller
|
||||
|
||||
int32_t setpoint_position;
|
||||
int32_t target_position;
|
||||
int32_t real_position;
|
||||
int32_t setpoint_position; ///< The setpoint position controlled from the actuator
|
||||
int32_t real_position; ///< The real position from the feedback of the controller
|
||||
int32_t target_velocity; ///< The target velocity send to the controller
|
||||
|
||||
bool homing_completed; ///< Once the homing is completed
|
||||
bool position_ready; ///< Ready for receiving (new) positions
|
||||
bool target_reached; ///< When the target position is reached
|
||||
};
|
||||
extern struct faulhaber_t faulhaber;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user