Skip to content

Commit

Permalink
添加了很多驱动模块,但是暂时无法使用,有待进一步修改
Browse files Browse the repository at this point in the history
  • Loading branch information
ComerLater committed Aug 29, 2024
1 parent aa96deb commit b05ebc2
Show file tree
Hide file tree
Showing 199 changed files with 37,258 additions and 3 deletions.
53 changes: 53 additions & 0 deletions apps/peripheral/actuator/pwm_out/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
############################################################################
#
# Copyright (c) 2015-2020 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################

set(PARAM_PREFIX PWM_MAIN)

if(CONFIG_BOARD_IO)
set(PARAM_PREFIX PWM_AUX)
endif()

px4_add_module(
MODULE drivers__pwm_out
MAIN pwm_out
COMPILE_FLAGS
-DPARAM_PREFIX="${PARAM_PREFIX}"
SRCS
PWMOut.cpp
PWMOut.hpp
MODULE_CONFIG
module.yaml
DEPENDS
arch_io_pins
mixer_module
)
5 changes: 5 additions & 0 deletions apps/peripheral/actuator/pwm_out/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
menuconfig DRIVERS_PWM_OUT
bool "pwm_out"
default n
---help---
Enable support for pwm_out
336 changes: 336 additions & 0 deletions apps/peripheral/actuator/pwm_out/PWMOut.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
/****************************************************************************
*
* Copyright (c) 2012-2022 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/

#include "PWMOut.hpp"

#include <px4_platform_common/sem.hpp>

PWMOut::PWMOut() :
OutputModuleInterface(MODULE_NAME, px4::wq_configurations::hp_default)
{
_pwm_mask = ((1u << DIRECT_PWM_OUTPUT_CHANNELS) - 1);
_mixing_output.setMaxNumOutputs(DIRECT_PWM_OUTPUT_CHANNELS);

// Getting initial parameter values
update_params();
}

PWMOut::~PWMOut()
{
/* make sure servos are off */
up_pwm_servo_deinit(_pwm_mask);

perf_free(_cycle_perf);
perf_free(_interval_perf);
}

bool PWMOut::update_pwm_out_state(bool on)
{
if (on && !_pwm_initialized && _pwm_mask != 0) {

for (int timer = 0; timer < MAX_IO_TIMERS; ++timer) {
_timer_rates[timer] = -1;

uint32_t channels = io_timer_get_group(timer);

if (channels == 0) {
continue;
}

char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_TIM%u", _mixing_output.paramPrefix(), timer);

int32_t tim_config = 0;
param_t handle = param_find(param_name);
param_get(handle, &tim_config);

if (tim_config > 0) {
_timer_rates[timer] = tim_config;

} else if (tim_config == -1) { // OneShot
_timer_rates[timer] = 0;

} else {
_pwm_mask &= ~channels; // don't use for pwm
}
}

int ret = up_pwm_servo_init(_pwm_mask);

if (ret < 0) {
PX4_ERR("up_pwm_servo_init failed (%i)", ret);
return false;
}

_pwm_mask = ret;

// set the timer rates
for (int timer = 0; timer < MAX_IO_TIMERS; ++timer) {
uint32_t channels = _pwm_mask & up_pwm_servo_get_rate_group(timer);

if (channels == 0) {
continue;
}

ret = up_pwm_servo_set_rate_group_update(timer, _timer_rates[timer]);

if (ret != 0) {
PX4_ERR("up_pwm_servo_set_rate_group_update failed for timer %i, rate %i (%i)", timer, _timer_rates[timer], ret);
_timer_rates[timer] = -1;
_pwm_mask &= ~channels;
}
}

_pwm_initialized = true;

// disable unused functions
for (unsigned i = 0; i < _num_outputs; ++i) {
if (((1 << i) & _pwm_mask) == 0) {
_mixing_output.disableFunction(i);
}
}
}

up_pwm_servo_arm(on, _pwm_mask);
return true;
}

bool PWMOut::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
unsigned num_outputs, unsigned num_control_groups_updated)
{
/* output to the servos */
if (_pwm_initialized) {
for (size_t i = 0; i < num_outputs; i++) {
if (!_mixing_output.isFunctionSet(i)) {
// do not run any signal on disabled channels
outputs[i] = 0;
}

if (_pwm_mask & (1 << i)) {
up_pwm_servo_set(i, outputs[i]);
}
}
}

/* Trigger all timer's channels in Oneshot mode to fire
* the oneshots with updated values.
*/
if (num_control_groups_updated > 0) {
up_pwm_update(_pwm_mask);
}

return true;
}

void PWMOut::Run()
{
if (should_exit()) {
ScheduleClear();
_mixing_output.unregister();

exit_and_cleanup();
return;
}

perf_begin(_cycle_perf);
perf_count(_interval_perf);

_mixing_output.update();

/* update PWM status if armed or if disarmed PWM values are set */
bool pwm_on = true;

if (_pwm_on != pwm_on) {
if (update_pwm_out_state(pwm_on)) {
_pwm_on = pwm_on;
}
}

// check for parameter updates
if (_parameter_update_sub.updated()) {
// clear update
parameter_update_s pupdate;
_parameter_update_sub.copy(&pupdate);

// update parameters from storage
update_params();
}

// check at end of cycle (updateSubscriptions() can potentially change to a different WorkQueue thread)
_mixing_output.updateSubscriptions(true);

perf_end(_cycle_perf);
_first_update_cycle = false;
}

int PWMOut::task_spawn(int argc, char *argv[])
{
PWMOut *instance = new PWMOut();

if (!instance) {
PX4_ERR("alloc failed");
return -1;
}

_object.store(instance);
_task_id = task_id_is_work_queue;
instance->ScheduleNow();
return 0;
}

void PWMOut::update_params()
{
uint32_t previously_set_functions = 0;

for (size_t i = 0; i < _num_outputs; i++) {
previously_set_functions |= (uint32_t)_mixing_output.isFunctionSet(i) << i;
}

updateParams();

// Automatically set PWM configuration when a channel is first assigned
if (!_first_update_cycle) {
for (size_t i = 0; i < _num_outputs; i++) {
if ((previously_set_functions & (1u << i)) == 0 && _mixing_output.functionParamHandle(i) != PARAM_INVALID) {
int32_t output_function;

if (param_get(_mixing_output.functionParamHandle(i), &output_function) == 0) {
// Servos need PWM rate 50Hz and disramed value 1500us
if (output_function >= (int)OutputFunction::Servo1
&& output_function <= (int)OutputFunction::ServoMax) { // Function got set to a servo
int32_t val = 1500;
PX4_INFO("Setting channel %i disarmed to %i", (int) val, i);
param_set(_mixing_output.disarmedParamHandle(i), &val);

// If the whole timer group was not set previously, then set the pwm rate to 50 Hz
for (int timer = 0; timer < MAX_IO_TIMERS; ++timer) {

uint32_t channels = io_timer_get_group(timer);

if ((channels & (1u << i)) == 0) {
continue;
}

if ((channels & previously_set_functions) == 0) { // None of the channels was set
char param_name[17];
snprintf(param_name, sizeof(param_name), "%s_TIM%u", _mixing_output.paramPrefix(), timer);

int32_t tim_config = 0;
param_t handle = param_find(param_name);

if (param_get(handle, &tim_config) == 0 && tim_config == 400) {
tim_config = 50;
PX4_INFO("setting timer %i to %i Hz", timer, (int) tim_config);
param_set(handle, &tim_config);
}
}
}
}

// Motors need a minimum value that idles the motor and have a deadzone at the top of the range
if (output_function >= (int)OutputFunction::Motor1
&& output_function <= (int)OutputFunction::MotorMax) { // Function got set to a motor
int32_t val = 1100;
PX4_INFO("Setting channel %i minimum to %i", (int) val, i);
param_set(_mixing_output.minParamHandle(i), &val);
val = 1900;
PX4_INFO("Setting channel %i maximum to %i", (int) val, i);
param_set(_mixing_output.maxParamHandle(i), &val);
}
}
}
}
}
}

int PWMOut::custom_command(int argc, char *argv[])
{
return print_usage("unknown command");
}

int PWMOut::print_status()
{
perf_print_counter(_cycle_perf);
perf_print_counter(_interval_perf);
_mixing_output.printStatus();

if (_pwm_initialized) {
for (int timer = 0; timer < MAX_IO_TIMERS; ++timer) {
if (_timer_rates[timer] >= 0) {
PX4_INFO_RAW("Timer %i: rate: %3i", timer, _timer_rates[timer]);
uint32_t channels = _pwm_mask & up_pwm_servo_get_rate_group(timer);

if (channels > 0) {
PX4_INFO_RAW(" channels: ");

for (uint32_t channel = 0; channel < _num_outputs; ++channel) {
if ((1 << channel) & channels) {
PX4_INFO_RAW("%" PRIu32 " ", channel);
}
}
}

PX4_INFO_RAW("\n");
}
}
}

return 0;
}

int PWMOut::print_usage(const char *reason)
{
if (reason) {
PX4_WARN("%s\n", reason);
}

PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
This module is responsible for driving the output pins. For boards without a separate IO chip
(eg. Pixracer), it uses the main channels. On boards with an IO chip (eg. Pixhawk), it uses the AUX channels, and the
px4io driver is used for main ones.
)DESCR_STR");

PRINT_MODULE_USAGE_NAME("pwm_out", "driver");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();

return 0;
}

extern "C" __EXPORT int pwm_out_main(int argc, char *argv[])
{
return PWMOut::main(argc, argv);
}
Loading

0 comments on commit b05ebc2

Please sign in to comment.