123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681 |
- /*
- * This file is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This file is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Eugene Shamaev, Siddharth Bharat Purohit
- */
- #include <AP_Common/AP_Common.h>
- #include <AP_HAL/AP_HAL.h>
- #if HAL_WITH_UAVCAN
- #include "AP_UAVCAN.h"
- #include <GCS_MAVLink/GCS.h>
- #include <AP_Motors/AP_Motors.h> //电机类
- #include <AP_BoardConfig/AP_BoardConfig.h>
- #include <AP_BoardConfig/AP_BoardConfig_CAN.h>
- #include <uavcan/transport/can_acceptance_filter_configurator.hpp>
- #include <uavcan/equipment/actuator/ArrayCommand.hpp>
- #include <uavcan/equipment/actuator/Command.hpp>
- #include <uavcan/equipment/actuator/Status.hpp>
- #include <uavcan/equipment/esc/RawCommand.hpp>
- #include <uavcan/equipment/esc/Status.hpp>
- //#include <uavcan/equipment/esc/Status1.hpp>
- //#include <uavcan/equipment/esc/Status2.hpp>
- //#include <uavcan/equipment/esc/Status3.hpp>
- //#include <uavcan/equipment/esc/Status4.hpp>
- //#include <uavcan/equipment/esc/Status5.hpp>
- #include <uavcan/equipment/esc/RPMCommand.hpp>
- #include <uavcan/equipment/indication/LightsCommand.hpp>
- #include <uavcan/equipment/indication/SingleLightCommand.hpp>
- #include <uavcan/equipment/indication/BeepCommand.hpp>
- #include <uavcan/equipment/indication/RGB565.hpp>
- #include <ardupilot/indication/SafetyState.hpp>
- #include <ardupilot/indication/Button.hpp>
- #include <AP_Baro/AP_Baro_UAVCAN.h>
- #include <AP_RangeFinder/AP_RangeFinder_UAVCAN.h>
- #include <AP_GPS/AP_GPS_UAVCAN.h>
- #include <AP_BattMonitor/AP_BattMonitor_UAVCAN.h>
- #include <AP_Compass/AP_Compass_UAVCAN.h>
- #include <AP_Airspeed/AP_Airspeed_UAVCAN.h>
- #include <SRV_Channel/SRV_Channel.h>
- #include <AP_OpticalFlow/AP_OpticalFlow_HereFlow.h>
- #define LED_DELAY_US 50000
- extern const AP_HAL::HAL& hal;
- #define debug_uavcan(level_debug, fmt, args...) do { if ((level_debug) <= AP::can().get_debug_level_driver(_driver_index)) { printf(fmt, ##args); }} while (0)
- // Translation of all messages from UAVCAN structures into AP structures is done
- // in AP_UAVCAN and not in corresponding drivers.
- // The overhead of including definitions of DSDL is very high and it is best to
- // concentrate in one place.
- // table of user settable CAN bus parameters
- const AP_Param::GroupInfo AP_UAVCAN::var_info[] = {
- // @Param: NODE
- // @DisplayName: UAVCAN node that is used for this network
- // @Description: UAVCAN node should be set implicitly
- // @Range: 1 250
- // @User: Advanced
- AP_GROUPINFO("NODE", 1, AP_UAVCAN, _uavcan_node, 10),
- // @Param: SRV_BM
- // @DisplayName: RC Out channels to be transmitted as servo over UAVCAN
- // @Description: Bitmask with one set for channel to be transmitted as a servo command over UAVCAN
- // @Bitmask: 0: Servo 1, 1: Servo 2, 2: Servo 3, 3: Servo 4, 4: Servo 5, 5: Servo 6, 6: Servo 7, 7: Servo 8, 8: Servo 9, 9: Servo 10, 10: Servo 11, 11: Servo 12, 12: Servo 13, 13: Servo 14, 14: Servo 15
- // @User: Advanced
- AP_GROUPINFO("SRV_BM", 2, AP_UAVCAN, _servo_bm, 0),
- // @Param: ESC_BM
- // @DisplayName: RC Out channels to be transmitted as ESC over UAVCAN
- // @Description: Bitmask with one set for channel to be transmitted as a ESC command over UAVCAN
- // @Bitmask: 0: ESC 1, 1: ESC 2, 2: ESC 3, 3: ESC 4, 4: ESC 5, 5: ESC 6, 6: ESC 7, 7: ESC 8, 8: ESC 9, 9: ESC 10, 10: ESC 11, 11: ESC 12, 12: ESC 13, 13: ESC 14, 14: ESC 15, 15: ESC 16
- // @User: Advanced
- AP_GROUPINFO("ESC_BM", 3, AP_UAVCAN, _esc_bm, 0),
- // @Param: SRV_RT
- // @DisplayName: Servo output rate
- // @Description: Maximum transmit rate for servo outputs
- // @Range: 1 200
- // @Units: Hz
- // @User: Advanced
- AP_GROUPINFO("SRV_RT", 4, AP_UAVCAN, _servo_rate_hz, 50),
- AP_GROUPEND
- };
- // this is the timeout in milliseconds for periodic message types. We
- // set this to 1 to minimise resend of stale msgs
- #define CAN_PERIODIC_TX_TIMEOUT_MS 2
- // publisher interfaces
- static uavcan::Publisher<uavcan::equipment::esc::RPMCommand>* vesc_rpm[MAX_NUMBER_OF_CAN_DRIVERS];
- static uavcan::Publisher<uavcan::equipment::actuator::ArrayCommand>* act_out_array[MAX_NUMBER_OF_CAN_DRIVERS];
- static uavcan::Publisher<uavcan::equipment::esc::RawCommand>* esc_raw[MAX_NUMBER_OF_CAN_DRIVERS];
- static uavcan::Publisher<uavcan::equipment::indication::LightsCommand>* rgb_led[MAX_NUMBER_OF_CAN_DRIVERS];
- static uavcan::Publisher<uavcan::equipment::indication::BeepCommand>* buzzer[MAX_NUMBER_OF_CAN_DRIVERS];
- static uavcan::Publisher<ardupilot::indication::SafetyState>* safety_state[MAX_NUMBER_OF_CAN_DRIVERS];
- // subscribers
- // handler SafteyButton
- UC_REGISTRY_BINDER(ButtonCb, ardupilot::indication::Button);
- static uavcan::Subscriber<ardupilot::indication::Button, ButtonCb> *safety_button_listener[MAX_NUMBER_OF_CAN_DRIVERS];
- struct ESCTelemetryData thruster_init = {0,0.0,0.0,0.0,0,0,0};
- //struct ESCTelemetryData thruster[6]={thruster_init,thruster_init,thruster_init,thruster_init,thruster_init,thruster_init};
- AP_UAVCAN::AP_UAVCAN() :
- _node_allocator()
- {
- AP_Param::setup_object_defaults(this, var_info);
- _singleton = this;
- for (uint8_t i = 0; i < UAVCAN_SRV_NUMBER; i++) {
- _SRV_conf[i].esc_pending = false;
- _SRV_conf[i].servo_pending = false;
- }
- for(uint8_t i = 0; i < 6; i++)
- {
- thruster[i]=thruster_init;
- }
-
- debug_uavcan(2, "AP_UAVCAN constructed\n\r");
- }
- AP_UAVCAN::~AP_UAVCAN()
- {
- }
- static void esc_status_st_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::Status>&msg,uint8_t mgr )
- {//接收到的数据在这里处理,打印出来
- AP_UAVCAN &uavcan = AP::uavcan();//6自由度电机计算出来的PWM
- uint8_t i = msg.esc_index;
- uavcan.thruster[i].error_count = msg.error_count;
- uavcan.thruster[i].voltage = (float)msg.voltage;
- uavcan.thruster[i].current = (float)msg.current;
- uavcan.thruster[i].temperature = (float)msg.temperature-273.15;
- uavcan.thruster[i].rpm = (int32_t)msg.rpm;
- uavcan.thruster[i].power_rating_pct= (uint8_t)msg.power_rating_pct;
-
-
- static uint8_t cnt = 0;
- cnt++;
- if (cnt>50)
- {
-
- gcs().send_text(MAV_SEVERITY_INFO, "motor_index = %d %d %d %d .",(int)i,(int)uavcan.thruster[i].rpm,(int)uavcan.thruster[i].power_rating_pct,(int)uavcan.thruster[i].esc_index);
- gcs().send_text(MAV_SEVERITY_INFO, "motor %x %f %f %f.",(int)uavcan.thruster[i].error_count,(float)uavcan.thruster[i].voltage,(float)uavcan.thruster[i].current,(float)uavcan.thruster[i].temperature);
- cnt=0;
- }
- /*uint8_t i = msg.esc_index;
- thruster[i].error_count = msg.error_count;
- thruster[i].voltage = (float)msg.voltage;
- thruster[i].current = (float)msg.current;
- thruster[i].temperature = (float)msg.temperature;
- thruster[i].rpm = (int32_t)msg.rpm;
- thruster[i].power_rating_pct= (uint8_t)msg.power_rating_pct;
-
- static uint8_t cnt = 0;
- cnt++;
- if (cnt>50)
- {
-
- gcs().send_text(MAV_SEVERITY_WARNING, "motor %x %f %f %f.",(int)thruster[i].error_count,(float)thruster[i].voltage,(float)thruster[i].current,(float)thruster[i].temperature);
- gcs().send_text(MAV_SEVERITY_WARNING, "motor_index = 0 %d %d %d .",(int)thruster[i].rpm,(int)thruster[i].power_rating_pct,(int)thruster[i].esc_index);
- cnt=0;
- }*/
-
- }
- static void esc_status_st_cb0(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::Status>&msg ){
- esc_status_st_cb(msg,0);
- }
- static void esc_status_st_cb1(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::Status>&msg ){
- esc_status_st_cb(msg,1);
- }
- static void (*esc_status_st_cb_arr[2])(const uavcan::ReceivedDataStructure<uavcan::equipment::esc::Status>&msg )
- ={esc_status_st_cb0,esc_status_st_cb1};
- AP_UAVCAN *AP_UAVCAN::get_uavcan(uint8_t driver_index)
- {
- if (driver_index >= AP::can().get_num_drivers() ||
- AP::can().get_protocol_type(driver_index) != AP_BoardConfig_CAN::Protocol_Type_UAVCAN) {
- return nullptr;
- }
- return static_cast<AP_UAVCAN*>(AP::can().get_driver(driver_index));
- }
- void AP_UAVCAN::init(uint8_t driver_index, bool enable_filters)
- {
- if (_initialized) {
- debug_uavcan(2, "UAVCAN: init called more than once\n\r");
- return;
- }
- _driver_index = driver_index;
- AP_HAL::CANManager* can_mgr = hal.can_mgr[driver_index];
- if (can_mgr == nullptr) {
- debug_uavcan(2, "UAVCAN: init called for inexisting CAN driver\n\r");
- return;
- }
- if (!can_mgr->is_initialized()) {
- debug_uavcan(1, "UAVCAN: CAN driver not initialized\n\r");
- return;
- }
- uavcan::ICanDriver* driver = can_mgr->get_driver();
- if (driver == nullptr) {
- debug_uavcan(2, "UAVCAN: can't get UAVCAN interface driver\n\r");
- return;
- }
- _node = new uavcan::Node<0>(*driver, SystemClock::instance(), _node_allocator);
- if (_node == nullptr) {
- debug_uavcan(1, "UAVCAN: couldn't allocate node\n\r");
- return;
- }
- if (_node->isStarted()) {
- debug_uavcan(2, "UAVCAN: node was already started?\n\r");
- return;
- }
- uavcan::NodeID self_node_id(_uavcan_node);
- _node->setNodeID(self_node_id);
- char ndname[20];
- snprintf(ndname, sizeof(ndname), "org.ardupilot:%u", driver_index);
- uavcan::NodeStatusProvider::NodeName name(ndname);
- _node->setName(name);
- uavcan::protocol::SoftwareVersion sw_version; // Standard type uavcan.protocol.SoftwareVersion
- sw_version.major = AP_UAVCAN_SW_VERS_MAJOR;
- sw_version.minor = AP_UAVCAN_SW_VERS_MINOR;
- _node->setSoftwareVersion(sw_version);
- uavcan::protocol::HardwareVersion hw_version; // Standard type uavcan.protocol.HardwareVersion
- hw_version.major = AP_UAVCAN_HW_VERS_MAJOR;
- hw_version.minor = AP_UAVCAN_HW_VERS_MINOR;
- const uint8_t uid_buf_len = hw_version.unique_id.capacity();
- uint8_t uid_len = uid_buf_len;
- uint8_t unique_id[uid_buf_len];
- if (hal.util->get_system_id_unformatted(unique_id, uid_len)) {
- uavcan::copy(unique_id, unique_id + uid_len, hw_version.unique_id.begin());
- }
- _node->setHardwareVersion(hw_version);
- int start_res = _node->start();
- if (start_res < 0) {
- debug_uavcan(1, "UAVCAN: node start problem, error %d\n\r", start_res);
- return;
- }
- //Start Servers
- #ifdef HAS_UAVCAN_SERVERS
- _servers.init(*_node);
- #endif
- // Roundup all subscribers from supported drivers
- AP_GPS_UAVCAN::subscribe_msgs(this);
- AP_Compass_UAVCAN::subscribe_msgs(this);
- AP_Baro_UAVCAN::subscribe_msgs(this);
- AP_BattMonitor_UAVCAN::subscribe_msgs(this);
- AP_Airspeed_UAVCAN::subscribe_msgs(this);
- AP_OpticalFlow_HereFlow::subscribe_msgs(this);
- AP_RangeFinder_UAVCAN::subscribe_msgs(this);
- auto *node= get_node();
- uavcan::Subscriber<uavcan::equipment::esc::Status>* esc_status;
- esc_status = new uavcan::Subscriber<uavcan::equipment::esc::Status>(*node);
- const int esc_status_res = esc_status->start(esc_status_st_cb_arr[_driver_index]);//定义回调函数用于接收
- if (esc_status_res<0)
- {
- return;
- }
-
- vesc_rpm[driver_index] = new uavcan::Publisher<uavcan::equipment::esc::RPMCommand>(*_node);
- vesc_rpm[driver_index]->setTxTimeout(uavcan::MonotonicDuration::fromMSec(2));
- vesc_rpm[driver_index]->setPriority(uavcan::TransferPriority::OneLowerThanHighest);
- act_out_array[driver_index] = new uavcan::Publisher<uavcan::equipment::actuator::ArrayCommand>(*_node);
- act_out_array[driver_index]->setTxTimeout(uavcan::MonotonicDuration::fromMSec(2));
- act_out_array[driver_index]->setPriority(uavcan::TransferPriority::OneLowerThanHighest);
- esc_raw[driver_index] = new uavcan::Publisher<uavcan::equipment::esc::RawCommand>(*_node);
- esc_raw[driver_index]->setTxTimeout(uavcan::MonotonicDuration::fromMSec(2));
- esc_raw[driver_index]->setPriority(uavcan::TransferPriority::OneLowerThanHighest);
- rgb_led[driver_index] = new uavcan::Publisher<uavcan::equipment::indication::LightsCommand>(*_node);
- rgb_led[driver_index]->setTxTimeout(uavcan::MonotonicDuration::fromMSec(20));
- rgb_led[driver_index]->setPriority(uavcan::TransferPriority::OneHigherThanLowest);
- buzzer[driver_index] = new uavcan::Publisher<uavcan::equipment::indication::BeepCommand>(*_node);
- buzzer[driver_index]->setTxTimeout(uavcan::MonotonicDuration::fromMSec(20));
- buzzer[driver_index]->setPriority(uavcan::TransferPriority::OneHigherThanLowest);
- safety_state[driver_index] = new uavcan::Publisher<ardupilot::indication::SafetyState>(*_node);
- safety_state[driver_index]->setTxTimeout(uavcan::MonotonicDuration::fromMSec(20));
- safety_state[driver_index]->setPriority(uavcan::TransferPriority::OneHigherThanLowest);
- safety_button_listener[driver_index] = new uavcan::Subscriber<ardupilot::indication::Button, ButtonCb>(*_node);
- if (safety_button_listener[driver_index]) {
- safety_button_listener[driver_index]->start(ButtonCb(this, &handle_button));
- }
- _led_conf.devices_count = 0;
- if (enable_filters) {
- configureCanAcceptanceFilters(*_node);
- }
- /*
- * Informing other nodes that we're ready to work.
- * Default mode is INITIALIZING.
- */
- _node->setModeOperational();
- // Spin node for device discovery
- _node->spin(uavcan::MonotonicDuration::fromMSec(5000));
- snprintf(_thread_name, sizeof(_thread_name), "uavcan_%u", driver_index);
- if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_UAVCAN::loop, void), _thread_name, 4096, AP_HAL::Scheduler::PRIORITY_CAN, 0)) {
- _node->setModeOfflineAndPublish();
- debug_uavcan(1, "UAVCAN: couldn't create thread\n\r");
- return;
- }
- _initialized = true;
- debug_uavcan(2, "UAVCAN: init done\n\r");
- }
- void AP_UAVCAN::loop(void)
- {
- while (true) {
- if (!_initialized) {
- hal.scheduler->delay_microseconds(1000);
- continue;
- }
- const int error = _node->spin(uavcan::MonotonicDuration::fromMSec(1));
- if (error < 0) {
- hal.scheduler->delay_microseconds(100);
- continue;
- }
- uint32_t now = AP_HAL::micros();
- uint32_t servo_period_us = 1000000UL / unsigned(_servo_rate_hz.get());
- if (now - _SRV_last_send_us >= servo_period_us){
- _SRV_last_send_us = now;
- const AP_Motors6DOF &motors6dof = AP::motors6dof();//6自由度电机计算出来的PWM
- uavcan::equipment::esc::RPMCommand msg;
- msg.rpm.push_back(motors6dof.motor_to_can[0]);
- msg.rpm.push_back(motors6dof.motor_to_can[1]);
- msg.rpm.push_back(motors6dof.motor_to_can[2]);
- msg.rpm.push_back(motors6dof.motor_to_can[3]);
- msg.rpm.push_back(motors6dof.motor_to_can[4]);
- msg.rpm.push_back(motors6dof.motor_to_can[5]);
- vesc_rpm[_driver_index]->broadcast(msg);
- }
- }
- }
- ///// SRV output /////
- void AP_UAVCAN::SRV_send_actuator(void)
- {
- uint8_t starting_servo = 0;
- bool repeat_send;
- WITH_SEMAPHORE(SRV_sem);
- do {
- repeat_send = false;
- uavcan::equipment::actuator::ArrayCommand msg;
- uint8_t i;
- // UAVCAN can hold maximum of 15 commands in one frame
- for (i = 0; starting_servo < UAVCAN_SRV_NUMBER && i < 15; starting_servo++) {
- uavcan::equipment::actuator::Command cmd;
- /*
- * Servo output uses a range of 1000-2000 PWM for scaling.
- * This converts output PWM from [1000:2000] range to [-1:1] range that
- * is passed to servo as unitless type via UAVCAN.
- * This approach allows for MIN/TRIM/MAX values to be used fully on
- * autopilot side and for servo it should have the setup to provide maximum
- * physically possible throws at [-1:1] limits.
- */
- if (_SRV_conf[starting_servo].servo_pending && ((((uint32_t) 1) << starting_servo) & _servo_bm)) {
- cmd.actuator_id = starting_servo + 1;
- // TODO: other types
- cmd.command_type = uavcan::equipment::actuator::Command::COMMAND_TYPE_UNITLESS;
- // TODO: failsafe, safety
- cmd.command_value = constrain_float(((float) _SRV_conf[starting_servo].pulse - 1000.0) / 500.0 - 1.0, -1.0, 1.0);
- msg.commands.push_back(cmd);
- i++;
- }
- }
- if (i > 0) {
- act_out_array[_driver_index]->broadcast(msg);
- if (i == 15) {
- repeat_send = true;
- }
- }
- } while (repeat_send);
- }
- void AP_UAVCAN::SRV_send_esc(void)
- {
- static const int cmd_max = uavcan::equipment::esc::RawCommand::FieldTypes::cmd::RawValueType::max();
- uavcan::equipment::esc::RawCommand esc_msg;
- uint8_t active_esc_num = 0, max_esc_num = 0;
- uint8_t k = 0;
- WITH_SEMAPHORE(SRV_sem);
- // find out how many esc we have enabled and if they are active at all
- for (uint8_t i = 0; i < UAVCAN_SRV_NUMBER; i++) {
- if ((((uint32_t) 1) << i) & _esc_bm) {
- max_esc_num = i + 1;
- if (_SRV_conf[i].esc_pending) {
- active_esc_num++;
- }
- }
- }
- // if at least one is active (update) we need to send to all
- if (active_esc_num > 0) {
- k = 0;
- for (uint8_t i = 0; i < max_esc_num && k < 20; i++) {
- if ((((uint32_t) 1) << i) & _esc_bm) {
- // TODO: ESC negative scaling for reverse thrust and reverse rotation
- float scaled = cmd_max * (hal.rcout->scale_esc_to_unity(_SRV_conf[i].pulse) + 1.0) / 2.0;
- scaled = constrain_float(scaled, 0, cmd_max);
- esc_msg.cmd.push_back(static_cast<int>(scaled));
- } else {
- esc_msg.cmd.push_back(static_cast<unsigned>(0));
- }
- k++;
- }
- esc_raw[_driver_index]->broadcast(esc_msg);
- }
- }
- void AP_UAVCAN::SRV_push_servos()
- {
- WITH_SEMAPHORE(SRV_sem);
- for (uint8_t i = 0; i < NUM_SERVO_CHANNELS; i++) {
- // Check if this channels has any function assigned
- if (SRV_Channels::channel_function(i)) {
- _SRV_conf[i].pulse = SRV_Channels::srv_channel(i)->get_output_pwm();
- _SRV_conf[i].esc_pending = true;
- _SRV_conf[i].servo_pending = true;
- }
- }
- _SRV_armed = hal.util->safety_switch_state() != AP_HAL::Util::SAFETY_DISARMED;
- }
- ///// LED /////
- void AP_UAVCAN::led_out_send()
- {
- uint64_t now = AP_HAL::micros64();
- if ((now - _led_conf.last_update) < LED_DELAY_US) {
- return;
- }
- uavcan::equipment::indication::LightsCommand msg;
- {
- WITH_SEMAPHORE(_led_out_sem);
- if (_led_conf.devices_count == 0) {
- return;
- }
- uavcan::equipment::indication::SingleLightCommand cmd;
- for (uint8_t i = 0; i < _led_conf.devices_count; i++) {
- cmd.light_id =_led_conf.devices[i].led_index;
- cmd.color.red = _led_conf.devices[i].red >> 3;
- cmd.color.green = _led_conf.devices[i].green >> 2;
- cmd.color.blue = _led_conf.devices[i].blue >> 3;
- msg.commands.push_back(cmd);
- }
- }
- rgb_led[_driver_index]->broadcast(msg);
- _led_conf.last_update = now;
- }
- bool AP_UAVCAN::led_write(uint8_t led_index, uint8_t red, uint8_t green, uint8_t blue)
- {
- if (_led_conf.devices_count >= AP_UAVCAN_MAX_LED_DEVICES) {
- return false;
- }
- WITH_SEMAPHORE(_led_out_sem);
- // check if a device instance exists. if so, break so the instance index is remembered
- uint8_t instance = 0;
- for (; instance < _led_conf.devices_count; instance++) {
- if (_led_conf.devices[instance].led_index == led_index) {
- break;
- }
- }
- // load into the correct instance.
- // if an existing instance was found in above for loop search,
- // then instance value is < _led_conf.devices_count.
- // otherwise a new one was just found so we increment the count.
- // Either way, the correct instance is the current value of instance
- _led_conf.devices[instance].led_index = led_index;
- _led_conf.devices[instance].red = red;
- _led_conf.devices[instance].green = green;
- _led_conf.devices[instance].blue = blue;
- if (instance == _led_conf.devices_count) {
- _led_conf.devices_count++;
- }
- return true;
- }
- // buzzer send
- void AP_UAVCAN::buzzer_send()
- {
- uavcan::equipment::indication::BeepCommand msg;
- WITH_SEMAPHORE(_buzzer.sem);
- uint8_t mask = (1U << _driver_index);
- if ((_buzzer.pending_mask & mask) == 0) {
- return;
- }
- _buzzer.pending_mask &= ~mask;
- msg.frequency = _buzzer.frequency;
- msg.duration = _buzzer.duration;
- buzzer[_driver_index]->broadcast(msg);
- }
- // buzzer support
- void AP_UAVCAN::set_buzzer_tone(float frequency, float duration_s)
- {
- WITH_SEMAPHORE(_buzzer.sem);
- _buzzer.frequency = frequency;
- _buzzer.duration = duration_s;
- _buzzer.pending_mask = 0xFF;
- }
- // SafetyState send
- void AP_UAVCAN::safety_state_send()
- {
- ardupilot::indication::SafetyState msg;
- uint32_t now = AP_HAL::millis();
- if (now - _last_safety_state_ms < 500) {
- // update at 2Hz
- return;
- }
- _last_safety_state_ms = now;
- switch (hal.util->safety_switch_state()) {
- case AP_HAL::Util::SAFETY_ARMED:
- msg.status = ardupilot::indication::SafetyState::STATUS_SAFETY_OFF;
- break;
- case AP_HAL::Util::SAFETY_DISARMED:
- msg.status = ardupilot::indication::SafetyState::STATUS_SAFETY_ON;
- break;
- default:
- // nothing to send
- return;
- }
- safety_state[_driver_index]->broadcast(msg);
- }
- /*
- handle Button message
- */
- void AP_UAVCAN::handle_button(AP_UAVCAN* ap_uavcan, uint8_t node_id, const ButtonCb &cb)
- {
- switch (cb.msg->button) {
- case ardupilot::indication::Button::BUTTON_SAFETY: {
- AP_BoardConfig *brdconfig = AP_BoardConfig::get_singleton();
- if (brdconfig && brdconfig->safety_button_handle_pressed(cb.msg->press_time)) {
- AP_HAL::Util::safety_state state = hal.util->safety_switch_state();
- if (state == AP_HAL::Util::SAFETY_ARMED) {
- hal.rcout->force_safety_on();
- } else {
- hal.rcout->force_safety_off();
- }
- }
- break;
- }
- }
- }
- AP_UAVCAN *AP_UAVCAN::_singleton;
- namespace AP {
- AP_UAVCAN &uavcan()
- {
- return *AP_UAVCAN::get_singleton();
- }
- };
- #endif // HAL_WITH_UAVCAN
|