mirror of https://github.com/ArduPilot/ardupilot
HAL_PX4: improved oneshot support
this now supports oneshot properly on both IO and FMU
This commit is contained in:
parent
ebd89bd078
commit
c9dfccfb26
|
@ -102,6 +102,14 @@ void PX4RCOutput::set_freq_fd(int fd, uint32_t chmask, uint16_t freq_hz)
|
||||||
// we can't set this per channel
|
// we can't set this per channel
|
||||||
if (freq_hz > 50) {
|
if (freq_hz > 50) {
|
||||||
// we're being asked to set the alt rate
|
// we're being asked to set the alt rate
|
||||||
|
if (_output_mode == MODE_PWM_ONESHOT) {
|
||||||
|
/*
|
||||||
|
set a 1Hz update for oneshot. This periodic output will
|
||||||
|
never actually trigger, instead we will directly trigger
|
||||||
|
the pulse after each push()
|
||||||
|
*/
|
||||||
|
freq_hz = 1;
|
||||||
|
}
|
||||||
if (ioctl(fd, PWM_SERVO_SET_UPDATE_RATE, (unsigned long)freq_hz) != 0) {
|
if (ioctl(fd, PWM_SERVO_SET_UPDATE_RATE, (unsigned long)freq_hz) != 0) {
|
||||||
hal.console->printf("RCOutput: Unable to set alt rate to %uHz\n", (unsigned)freq_hz);
|
hal.console->printf("RCOutput: Unable to set alt rate to %uHz\n", (unsigned)freq_hz);
|
||||||
return;
|
return;
|
||||||
|
@ -160,10 +168,6 @@ void PX4RCOutput::set_freq(uint32_t chmask, uint16_t freq_hz)
|
||||||
if (freq_hz > 400) {
|
if (freq_hz > 400) {
|
||||||
freq_hz = 400;
|
freq_hz = 400;
|
||||||
}
|
}
|
||||||
if (freq_hz == 400) {
|
|
||||||
// remember mask for fast channels
|
|
||||||
_fast_channel_mask = chmask;
|
|
||||||
}
|
|
||||||
uint32_t primary_mask = chmask & ((1UL<<_servo_count)-1);
|
uint32_t primary_mask = chmask & ((1UL<<_servo_count)-1);
|
||||||
uint32_t alt_mask = chmask >> _servo_count;
|
uint32_t alt_mask = chmask >> _servo_count;
|
||||||
if (primary_mask && _pwm_fd != -1) {
|
if (primary_mask && _pwm_fd != -1) {
|
||||||
|
@ -267,6 +271,11 @@ void PX4RCOutput::write(uint8_t ch, uint16_t period_us)
|
||||||
if (ch >= _max_channel) {
|
if (ch >= _max_channel) {
|
||||||
_max_channel = ch + 1;
|
_max_channel = ch + 1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
only mark an update is needed if there has been a change, or we
|
||||||
|
are in oneshot mode. In oneshot mode we always need to send the
|
||||||
|
output
|
||||||
|
*/
|
||||||
if (period_us != _period[ch] ||
|
if (period_us != _period[ch] ||
|
||||||
_output_mode == MODE_PWM_ONESHOT) {
|
_output_mode == MODE_PWM_ONESHOT) {
|
||||||
_period[ch] = period_us;
|
_period[ch] = period_us;
|
||||||
|
@ -478,44 +487,18 @@ void PX4RCOutput::push()
|
||||||
if (_output_mode == MODE_PWM_ONESHOT) {
|
if (_output_mode == MODE_PWM_ONESHOT) {
|
||||||
// run timer immediately in oneshot mode
|
// run timer immediately in oneshot mode
|
||||||
_send_outputs();
|
_send_outputs();
|
||||||
if (_fast_channel_mask != 0) {
|
|
||||||
// this is a crude way of triggering immediate output
|
|
||||||
_trigger_fast_output();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PX4RCOutput::_timer_tick(void)
|
void PX4RCOutput::_timer_tick(void)
|
||||||
{
|
{
|
||||||
if (_output_mode != MODE_PWM_ONESHOT) {
|
if (_output_mode != MODE_PWM_ONESHOT) {
|
||||||
|
/* in oneshot mode the timer does nothing as the outputs are
|
||||||
|
* sent from push() */
|
||||||
_send_outputs();
|
_send_outputs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
trigger immediate output on fast channels. This only works on FMU,
|
|
||||||
not IO. It takes advantage of the way the rate update works on FMU
|
|
||||||
to trigger a oneshot output
|
|
||||||
*/
|
|
||||||
void PX4RCOutput::_trigger_fast_output(void)
|
|
||||||
{
|
|
||||||
uint32_t primary_mask = _fast_channel_mask & ((1UL<<_servo_count)-1);
|
|
||||||
uint32_t alt_mask = _fast_channel_mask >> _servo_count;
|
|
||||||
if (_alt_fd == -1) {
|
|
||||||
// we're on a FMU only board
|
|
||||||
if (primary_mask) {
|
|
||||||
set_freq_fd(_pwm_fd, primary_mask, 400);
|
|
||||||
set_freq_fd(_pwm_fd, primary_mask, 51);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we're on a board with px4io
|
|
||||||
if (alt_mask) {
|
|
||||||
set_freq_fd(_alt_fd, alt_mask, 400);
|
|
||||||
set_freq_fd(_alt_fd, alt_mask, 51);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
enable sbus output
|
enable sbus output
|
||||||
*/
|
*/
|
||||||
|
@ -548,8 +531,15 @@ void PX4RCOutput::set_output_mode(enum output_mode mode)
|
||||||
_output_mode = mode;
|
_output_mode = mode;
|
||||||
if (_output_mode == MODE_PWM_ONESHOT) {
|
if (_output_mode == MODE_PWM_ONESHOT) {
|
||||||
ioctl(_pwm_fd, PWM_SERVO_SET_ONESHOT, 1);
|
ioctl(_pwm_fd, PWM_SERVO_SET_ONESHOT, 1);
|
||||||
|
if (_alt_fd != -1) {
|
||||||
|
ioctl(_alt_fd, PWM_SERVO_SET_ONESHOT, 1);
|
||||||
|
}
|
||||||
|
set_freq(0xFFFF, 51);
|
||||||
} else {
|
} else {
|
||||||
ioctl(_pwm_fd, PWM_SERVO_SET_ONESHOT, 0);
|
ioctl(_pwm_fd, PWM_SERVO_SET_ONESHOT, 0);
|
||||||
|
if (_alt_fd != -1) {
|
||||||
|
ioctl(_alt_fd, PWM_SERVO_SET_ONESHOT, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@ private:
|
||||||
orb_advert_t _actuator_armed_pub = NULL;
|
orb_advert_t _actuator_armed_pub = NULL;
|
||||||
uint16_t _esc_pwm_min = 0;
|
uint16_t _esc_pwm_min = 0;
|
||||||
uint16_t _esc_pwm_max = 0;
|
uint16_t _esc_pwm_max = 0;
|
||||||
uint16_t _fast_channel_mask;
|
|
||||||
|
|
||||||
void _init_alt_channels(void);
|
void _init_alt_channels(void);
|
||||||
void _publish_actuators(void);
|
void _publish_actuators(void);
|
||||||
|
@ -70,6 +69,4 @@ private:
|
||||||
bool _corking;
|
bool _corking;
|
||||||
enum output_mode _output_mode = MODE_PWM_NORMAL;
|
enum output_mode _output_mode = MODE_PWM_NORMAL;
|
||||||
void _send_outputs(void);
|
void _send_outputs(void);
|
||||||
|
|
||||||
void _trigger_fast_output();
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue