mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-26 16:30:07 +08:00
Uavcan actuators restyle and telemetry (#2698)
* [uavcan] Fix performance and restyle code * [uavcan] Add ESC telemetry
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
<description>
|
||||
UAVCan actuators
|
||||
</description>
|
||||
<define name="UAVCAN_ACTUATORS_USE_CURRENT" value="TRUE" description="Enable the usage of the current sensing in the ESC telemetry"/>
|
||||
</doc>
|
||||
<dep>
|
||||
<depends>uavcan</depends>
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
<description>
|
||||
UAVCan interface for transmitting/receiving uavcan messages on CAN busses
|
||||
</description>
|
||||
<configure name="UAVCAN_USE_CAN1" value="FALSE" description="Enable UAVCAN on CAN1 interface"/>
|
||||
<configure name="UAVCAN_USE_CAN2" value="FALSE" description="Enable UAVCAN on CAN2 interface"/>
|
||||
<define name="UAVCAN_NODE_ID" value="100" description="The UAVCAN node ID of the AP"/>
|
||||
<define name="UAVCAN_BAUDRATE" value="1000000" description="The baudrate of the CAN interface"/>
|
||||
<configure name="UAVCAN_USE_CAN1" value="FALSE" description="Enable UAVCAN on CAN1 interface"/>
|
||||
<configure name="UAVCAN_USE_CAN2" value="FALSE" description="Enable UAVCAN on CAN2 interface"/>
|
||||
<define name="UAVCAN_NODE_ID" value="100" description="The UAVCAN node ID of the AP"/>
|
||||
<define name="UAVCAN_BAUDRATE" value="1000000" description="The baudrate of the CAN interface"/>
|
||||
</doc>
|
||||
<header>
|
||||
<file name="uavcan.h" dir="modules/uavcan"/>
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
telemetry="telemetry/highspeed_rotorcraft.xml"
|
||||
flight_plan="flight_plans/rotorcraft_basic.xml"
|
||||
settings="settings/rotorcraft_basic.xml"
|
||||
settings_modules="modules/guidance_indi_hybrid.xml modules/air_data.xml modules/ins_ekf2.xml modules/stabilization_indi_simple.xml modules/gps_ubx_ucenter.xml modules/gps.xml modules/imu_common.xml"
|
||||
settings_modules="modules/air_data.xml modules/gps.xml modules/gps_ubx_ucenter.xml modules/guidance_indi_hybrid.xml modules/guidance_rotorcraft.xml modules/imu_common.xml modules/ins_ekf2.xml modules/nav_basic_rotorcraft.xml modules/stabilization_indi_simple.xml"
|
||||
gui_color="blue"
|
||||
/>
|
||||
<aircraft
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/**
|
||||
* @file arch/chibios/modules/uavcan/uavcan.c
|
||||
* Interface from actuators to ChibiOS CAN driver using UAVCan
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uavcan.h"
|
||||
@@ -45,15 +45,15 @@ static uavcan_event *uavcan_event_hd = NULL;
|
||||
#define UAVCAN_CAN1_BAUDRATE UAVCAN_BAUDRATE
|
||||
#endif
|
||||
|
||||
static THD_WORKING_AREA(uavcan1_rx_wa, 1024*2);
|
||||
static THD_WORKING_AREA(uavcan1_tx_wa, 1024*2);
|
||||
static THD_WORKING_AREA(uavcan1_rx_wa, 1024 * 2);
|
||||
static THD_WORKING_AREA(uavcan1_tx_wa, 1024 * 2);
|
||||
|
||||
struct uavcan_iface_t uavcan1 = {
|
||||
.can_driver = &CAND1,
|
||||
.can_cfg = {
|
||||
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
|
||||
CAN_BTR_SJW(0) | CAN_BTR_TS2(1) |
|
||||
CAN_BTR_TS1(14) | CAN_BTR_BRP((STM32_PCLK1/18)/UAVCAN_CAN1_BAUDRATE - 1)
|
||||
CAN_BTR_TS1(14) | CAN_BTR_BRP((STM32_PCLK1 / 18) / UAVCAN_CAN1_BAUDRATE - 1)
|
||||
},
|
||||
.thread_rx_wa = uavcan1_rx_wa,
|
||||
.thread_rx_wa_size = sizeof(uavcan1_rx_wa),
|
||||
@@ -74,15 +74,15 @@ struct uavcan_iface_t uavcan1 = {
|
||||
#define UAVCAN_CAN2_BAUDRATE UAVCAN_BAUDRATE
|
||||
#endif
|
||||
|
||||
static THD_WORKING_AREA(uavcan2_rx_wa, 1024*2);
|
||||
static THD_WORKING_AREA(uavcan2_tx_wa, 1024*2);
|
||||
static THD_WORKING_AREA(uavcan2_rx_wa, 1024 * 2);
|
||||
static THD_WORKING_AREA(uavcan2_tx_wa, 1024 * 2);
|
||||
|
||||
struct uavcan_iface_t uavcan2 = {
|
||||
.can_driver = &CAND2,
|
||||
.can_cfg = {
|
||||
CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP,
|
||||
CAN_BTR_SJW(0) | CAN_BTR_TS2(1) |
|
||||
CAN_BTR_TS1(14) | CAN_BTR_BRP((STM32_PCLK1/18)/UAVCAN_CAN2_BAUDRATE - 1)
|
||||
CAN_BTR_TS1(14) | CAN_BTR_BRP((STM32_PCLK1 / 18) / UAVCAN_CAN2_BAUDRATE - 1)
|
||||
},
|
||||
.thread_rx_wa = uavcan2_rx_wa,
|
||||
.thread_rx_wa_size = sizeof(uavcan2_rx_wa),
|
||||
@@ -97,7 +97,8 @@ struct uavcan_iface_t uavcan2 = {
|
||||
/*
|
||||
* Receiver thread.
|
||||
*/
|
||||
static THD_FUNCTION(uavcan_rx, p) {
|
||||
static THD_FUNCTION(uavcan_rx, p)
|
||||
{
|
||||
event_listener_t el;
|
||||
CANRxFrame rx_msg;
|
||||
CanardCANFrame rx_frame;
|
||||
@@ -106,8 +107,9 @@ static THD_FUNCTION(uavcan_rx, p) {
|
||||
chRegSetThreadName("uavcan_rx");
|
||||
chEvtRegister(&iface->can_driver->rxfull_event, &el, EVENT_MASK(0));
|
||||
while (true) {
|
||||
if (chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(100)) == 0)
|
||||
if (chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(100)) == 0) {
|
||||
continue;
|
||||
}
|
||||
chMtxLock(&iface->mutex);
|
||||
|
||||
// Wait until a CAN message is received
|
||||
@@ -116,12 +118,11 @@ static THD_FUNCTION(uavcan_rx, p) {
|
||||
const uint32_t timestamp = TIME_I2US(chVTGetSystemTimeX());
|
||||
memcpy(rx_frame.data, rx_msg.data8, 8);
|
||||
rx_frame.data_len = rx_msg.DLC;
|
||||
if(rx_msg.IDE) {
|
||||
if (rx_msg.IDE) {
|
||||
rx_frame.id = CANARD_CAN_FRAME_EFF | rx_msg.EID;
|
||||
} else {
|
||||
rx_frame.id = rx_msg.SID;
|
||||
}
|
||||
|
||||
// Let canard handle the frame
|
||||
canardHandleRxFrame(&iface->canard, &rx_frame, timestamp);
|
||||
}
|
||||
@@ -133,7 +134,8 @@ static THD_FUNCTION(uavcan_rx, p) {
|
||||
/*
|
||||
* Transmitter thread.
|
||||
*/
|
||||
static THD_FUNCTION(uavcan_tx, p) {
|
||||
static THD_FUNCTION(uavcan_tx, p)
|
||||
{
|
||||
event_listener_t txc, txe, txr;
|
||||
struct uavcan_iface_t *iface = (struct uavcan_iface_t *)p;
|
||||
uint8_t err_cnt = 0;
|
||||
@@ -146,40 +148,38 @@ static THD_FUNCTION(uavcan_tx, p) {
|
||||
while (true) {
|
||||
eventmask_t evts = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_MS2I(100));
|
||||
// Succesfull transmit
|
||||
if (evts == 0)
|
||||
if (evts == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Transmit error
|
||||
if(evts & EVENT_MASK(1))
|
||||
{
|
||||
if (evts & EVENT_MASK(1)) {
|
||||
chEvtGetAndClearFlags(&txe);
|
||||
continue;
|
||||
}
|
||||
|
||||
chMtxLock(&iface->mutex);
|
||||
for (const CanardCANFrame* txf = NULL; (txf = canardPeekTxQueue(&iface->canard)) != NULL;) {
|
||||
for (const CanardCANFrame *txf = NULL; (txf = canardPeekTxQueue(&iface->canard)) != NULL;) {
|
||||
CANTxFrame tx_msg;
|
||||
tx_msg.DLC = txf->data_len;
|
||||
memcpy(tx_msg.data8, txf->data, 8);
|
||||
tx_msg.EID = txf->id & CANARD_CAN_EXT_ID_MASK;
|
||||
tx_msg.IDE = CAN_IDE_EXT;
|
||||
tx_msg.RTR = CAN_RTR_DATA;
|
||||
if (canTransmit(iface->can_driver, CAN_ANY_MAILBOX, &tx_msg, TIME_IMMEDIATE) == MSG_OK) {
|
||||
if (!canTryTransmitI(iface->can_driver, CAN_ANY_MAILBOX, &tx_msg)) {
|
||||
err_cnt = 0;
|
||||
canardPopTxQueue(&iface->canard);
|
||||
} else {
|
||||
// After 5 retries giveup
|
||||
if(err_cnt >= 5) {
|
||||
// After 5 retries giveup and clean full queue
|
||||
if (err_cnt >= 5) {
|
||||
err_cnt = 0;
|
||||
canardPopTxQueue(&iface->canard);
|
||||
while (canardPeekTxQueue(&iface->canard)) { canardPopTxQueue(&iface->canard); }
|
||||
continue;
|
||||
}
|
||||
|
||||
// Timeout - just exit and try again later
|
||||
chMtxUnlock(&iface->mutex);
|
||||
err_cnt++;
|
||||
canardPopTxQueue(&iface->canard); //FIXME (This needs to be here, don't know why)
|
||||
chThdSleepMilliseconds(err_cnt * 5);
|
||||
chThdSleepMilliseconds(++err_cnt);
|
||||
chMtxLock(&iface->mutex);
|
||||
continue;
|
||||
}
|
||||
@@ -191,33 +191,35 @@ static THD_FUNCTION(uavcan_tx, p) {
|
||||
/**
|
||||
* Whenever a valid and 'accepted' transfer is received
|
||||
*/
|
||||
static void onTransferReceived(CanardInstance* ins, CanardRxTransfer* transfer) {
|
||||
static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
|
||||
{
|
||||
struct uavcan_iface_t *iface = (struct uavcan_iface_t *)ins->user_reference;
|
||||
|
||||
// Go through all registered callbacks and call function callback if found
|
||||
for(uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
|
||||
if(transfer->data_type_id == ev->data_type_id)
|
||||
for (uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
|
||||
if (transfer->data_type_id == ev->data_type_id) {
|
||||
ev->cb(iface, transfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we should accept this transfer
|
||||
*/
|
||||
static bool shouldAcceptTransfer(const CanardInstance* ins __attribute__((unused)),
|
||||
uint64_t* out_data_type_signature,
|
||||
static bool shouldAcceptTransfer(const CanardInstance *ins __attribute__((unused)),
|
||||
uint64_t *out_data_type_signature,
|
||||
uint16_t data_type_id,
|
||||
CanardTransferType transfer_type __attribute__((unused)),
|
||||
uint8_t source_node_id __attribute__((unused))) {
|
||||
uint8_t source_node_id __attribute__((unused)))
|
||||
{
|
||||
|
||||
// Go through all registered callbacks and return signature if found
|
||||
for(uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
|
||||
if(data_type_id == ev->data_type_id) {
|
||||
for (uavcan_event *ev = uavcan_event_hd; ev; ev = ev->next) {
|
||||
if (data_type_id == ev->data_type_id) {
|
||||
*out_data_type_signature = ev->data_type_signature;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No callback found return
|
||||
return false;
|
||||
}
|
||||
@@ -225,14 +227,15 @@ static bool shouldAcceptTransfer(const CanardInstance* ins __attribute__((unused
|
||||
/**
|
||||
* Initialize uavcan interface
|
||||
*/
|
||||
static void uavcanInitIface(struct uavcan_iface_t *iface) {
|
||||
static void uavcanInitIface(struct uavcan_iface_t *iface)
|
||||
{
|
||||
// Initialize mutexes/events for multithread locking
|
||||
chMtxObjectInit(&iface->mutex);
|
||||
chEvtObjectInit(&iface->tx_request);
|
||||
|
||||
// Initialize canard
|
||||
canardInit(&iface->canard, iface->canard_memory_pool, sizeof(iface->canard_memory_pool),
|
||||
onTransferReceived, shouldAcceptTransfer, iface);
|
||||
onTransferReceived, shouldAcceptTransfer, iface);
|
||||
// Update the uavcan node ID
|
||||
canardSetLocalNodeID(&iface->canard, iface->node_id);
|
||||
|
||||
@@ -240,8 +243,8 @@ static void uavcanInitIface(struct uavcan_iface_t *iface) {
|
||||
canStart(iface->can_driver, &iface->can_cfg);
|
||||
|
||||
// Start the receiver and transmitter thread
|
||||
chThdCreateStatic(iface->thread_rx_wa, iface->thread_rx_wa_size, NORMALPRIO + 8, uavcan_rx, (void*)iface);
|
||||
chThdCreateStatic(iface->thread_tx_wa, iface->thread_tx_wa_size, NORMALPRIO + 7, uavcan_tx, (void*)iface);
|
||||
chThdCreateStatic(iface->thread_rx_wa, iface->thread_rx_wa_size, NORMALPRIO + 8, uavcan_rx, (void *)iface);
|
||||
chThdCreateStatic(iface->thread_tx_wa, iface->thread_tx_wa_size, NORMALPRIO + 7, uavcan_tx, (void *)iface);
|
||||
iface->initialized = true;
|
||||
}
|
||||
|
||||
@@ -253,7 +256,7 @@ void uavcan_init(void)
|
||||
#if UAVCAN_USE_CAN1
|
||||
uavcanInitIface(&uavcan1);
|
||||
#endif
|
||||
#if UAVCAN_USE_CAN2
|
||||
#if UAVCAN_USE_CAN2
|
||||
uavcanInitIface(&uavcan2);
|
||||
#endif
|
||||
}
|
||||
@@ -264,9 +267,9 @@ void uavcan_init(void)
|
||||
void uavcan_bind(uint16_t data_type_id, uint64_t data_type_signature, uavcan_event *ev, uavcan_callback cb)
|
||||
{
|
||||
// Configure the event
|
||||
ev->data_type_id = data_type_id,
|
||||
ev->data_type_signature = data_type_signature,
|
||||
ev->cb = cb,
|
||||
ev->data_type_id = data_type_id;
|
||||
ev->data_type_signature = data_type_signature;
|
||||
ev->cb = cb;
|
||||
ev->next = uavcan_event_hd;
|
||||
|
||||
// Switch the head
|
||||
@@ -276,15 +279,17 @@ void uavcan_bind(uint16_t data_type_id, uint64_t data_type_signature, uavcan_eve
|
||||
/**
|
||||
* Broadcast an uavcan message to a specific interface
|
||||
*/
|
||||
void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id, uint8_t priority, const void* payload,
|
||||
uint16_t payload_len) {
|
||||
if(!iface->initialized) return;
|
||||
void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id,
|
||||
uint8_t priority, const void *payload,
|
||||
uint16_t payload_len)
|
||||
{
|
||||
if (!iface->initialized) { return; }
|
||||
|
||||
chMtxLock(&iface->mutex);
|
||||
canardBroadcast(&iface->canard,
|
||||
data_type_signature,
|
||||
data_type_id, &iface->transfer_id,
|
||||
priority, payload, payload_len);
|
||||
data_type_signature,
|
||||
data_type_id, &iface->transfer_id,
|
||||
priority, payload, payload_len);
|
||||
chMtxUnlock(&iface->mutex);
|
||||
chEvtBroadcast(&iface->tx_request);
|
||||
}
|
||||
|
||||
@@ -46,16 +46,16 @@ struct uavcan_iface_t {
|
||||
|
||||
uint8_t node_id;
|
||||
CanardInstance canard;
|
||||
uint8_t canard_memory_pool[1024*2];
|
||||
uint8_t canard_memory_pool[1024 * 2];
|
||||
|
||||
uint8_t transfer_id;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
/** Generic uavcan callback definition */
|
||||
typedef void (*uavcan_callback)(struct uavcan_iface_t *iface, CanardRxTransfer* transfer);
|
||||
typedef void (*uavcan_callback)(struct uavcan_iface_t *iface, CanardRxTransfer *transfer);
|
||||
|
||||
/** Main uavcan event structure for registering/calling callbacks */
|
||||
/** Main uavcan event structure for registering/calling callbacks */
|
||||
struct uavcan_event_t {
|
||||
uint16_t data_type_id;
|
||||
uint64_t data_type_signature;
|
||||
@@ -75,7 +75,7 @@ extern struct uavcan_iface_t uavcan2;
|
||||
/** uavcan external functions */
|
||||
void uavcan_init(void);
|
||||
void uavcan_bind(uint16_t data_type_id, uint64_t data_type_signature, uavcan_event *ev, uavcan_callback cb);
|
||||
void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id, uint8_t priority,
|
||||
const void* payload, uint16_t payload_len);
|
||||
void uavcan_broadcast(struct uavcan_iface_t *iface, uint64_t data_type_signature, uint16_t data_type_id,
|
||||
uint8_t priority, const void *payload, uint16_t payload_len);
|
||||
|
||||
#endif /* MODULES_UAVCAN_ARCH_H */
|
||||
@@ -21,12 +21,17 @@
|
||||
/**
|
||||
* @file subsystems/actuators/actuators_uavcan.c
|
||||
* UAVCan actuators using RAWCOMMAND message and ESC_STATUS telemetry
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "actuators_uavcan.h"
|
||||
#include "subsystems/electrical.h"
|
||||
|
||||
/* By default enable the usage of the current sensing in the ESC telemetry */
|
||||
#ifndef UAVCAN_ACTUATORS_USE_CURRENT
|
||||
#define UAVCAN_ACTUATORS_USE_CURRENT TRUE
|
||||
#endif
|
||||
|
||||
/* uavcan ESC status telemetry structure */
|
||||
struct actuators_uavcan_telem_t {
|
||||
float voltage;
|
||||
@@ -55,66 +60,120 @@ static struct actuators_uavcan_telem_t uavcan2_telem[SERVOS_UAVCAN2_NB];
|
||||
#define UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_SIGNATURE (0x217F5C87D7EC951DULL)
|
||||
#define UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_MAX_SIZE ((285 + 7)/8)
|
||||
|
||||
/* private variables */
|
||||
static bool actuators_uavcan_initialized = false;
|
||||
static uavcan_event esc_status_ev;
|
||||
|
||||
|
||||
#if PERIODIC_TELEMETRY
|
||||
#include "subsystems/datalink/telemetry.h"
|
||||
|
||||
static void actuators_uavcan_send_esc(struct transport_tx *trans, struct link_device *dev)
|
||||
{
|
||||
/*static uint8_t esc_idx = 0;
|
||||
float power = uavcan_telem[esc_idx].current * uavcan_telem[esc_idx].voltage;
|
||||
float rpm = uavcan_telem[esc_idx].rpm;
|
||||
float energy = uavcan_telem[esc_idx].energy;
|
||||
pprz_msg_send_ESC(trans, dev, AC_ID, &uavcan_telem[esc_idx].current, &electrical.vsupply, &power,
|
||||
&rpm, &uavcan_telem[esc_idx].voltage, &energy, &esc_idx);
|
||||
static uint8_t esc_idx = 0;
|
||||
|
||||
// Find the correct telemetry
|
||||
uint8_t max_id = 0;
|
||||
uint8_t offset = 0;
|
||||
struct actuators_uavcan_telem_t *telem = NULL;
|
||||
#ifdef SERVOS_UAVCAN1_NB
|
||||
if (esc_idx >= max_id && esc_idx < max_id + SERVOS_UAVCAN1_NB) {
|
||||
offset = max_id;
|
||||
telem = uavcan1_telem;
|
||||
}
|
||||
max_id += SERVOS_UAVCAN1_NB;
|
||||
#endif
|
||||
#ifdef SERVOS_UAVCAN2_NB
|
||||
if (esc_idx >= max_id && esc_idx < max_id + SERVOS_UAVCAN2_NB) {
|
||||
offset = max_id;
|
||||
telem = uavcan2_telem;
|
||||
}
|
||||
max_id += SERVOS_UAVCAN2_NB;
|
||||
#endif
|
||||
|
||||
// Safety check
|
||||
if (telem == NULL) {
|
||||
esc_idx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t i = esc_idx - offset;
|
||||
float power = telem[i].current * telem[i].voltage;
|
||||
float rpm = telem[i].rpm;
|
||||
float energy = telem[i].energy;
|
||||
pprz_msg_send_ESC(trans, dev, AC_ID, &telem[i].current, &electrical.vsupply, &power,
|
||||
&rpm, &telem[i].voltage, &energy, &esc_idx);
|
||||
esc_idx++;
|
||||
|
||||
if(esc_idx >= ACTUATORS_UAVCAN_NB)
|
||||
esc_idx = 0;*/
|
||||
if (esc_idx >= max_id) {
|
||||
esc_idx = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Whevener an ESC_STATUS message from the EQUIPMENT group is received
|
||||
*/
|
||||
static void actuators_uavcan_esc_status_cb(struct uavcan_iface_t *iface, CanardRxTransfer* transfer) {
|
||||
/*uint8_t esc_idx;
|
||||
static void actuators_uavcan_esc_status_cb(struct uavcan_iface_t *iface, CanardRxTransfer *transfer)
|
||||
{
|
||||
uint8_t esc_idx;
|
||||
uint16_t tmp_float;
|
||||
|
||||
canardDecodeScalar(transfer, 105, 5, false, (void*)&esc_idx);
|
||||
if(iface == &can2_iface)
|
||||
esc_idx += 10;
|
||||
if(esc_idx >= ACTUATORS_UAVCAN_NB)
|
||||
break;
|
||||
|
||||
canardDecodeScalar(transfer, 0, 32, false, (void*)&uavcan_telem[esc_idx].energy);
|
||||
canardDecodeScalar(transfer, 32, 16, true, (void*)&tmp_float);
|
||||
uavcan_telem[esc_idx].voltage = canardConvertFloat16ToNativeFloat(tmp_float);
|
||||
canardDecodeScalar(transfer, 48, 16, true, (void*)&tmp_float);
|
||||
uavcan_telem[esc_idx].current = canardConvertFloat16ToNativeFloat(tmp_float);
|
||||
canardDecodeScalar(transfer, 64, 16, true, (void*)&tmp_float);
|
||||
uavcan_telem[esc_idx].temperature = canardConvertFloat16ToNativeFloat(tmp_float);
|
||||
canardDecodeScalar(transfer, 80, 18, true, (void*)&uavcan_telem[esc_idx].rpm);
|
||||
struct actuators_uavcan_telem_t *telem = NULL;
|
||||
uint8_t max_id = 0;
|
||||
#ifdef SERVOS_UAVCAN1_NB
|
||||
if (iface == &uavcan1) {
|
||||
telem = uavcan1_telem;
|
||||
max_id = SERVOS_UAVCAN1_NB;
|
||||
}
|
||||
#endif
|
||||
#ifdef SERVOS_UAVCAN2_NB
|
||||
if (iface == &uavcan2) {
|
||||
telem = uavcan2_telem;
|
||||
max_id = SERVOS_UAVCAN2_NB;
|
||||
}
|
||||
#endif
|
||||
|
||||
canardDecodeScalar(transfer, 105, 5, false, (void *)&esc_idx);
|
||||
//Could not find the right interface
|
||||
if (esc_idx > max_id || telem == NULL || max_id == 0) {
|
||||
return;
|
||||
}
|
||||
canardDecodeScalar(transfer, 0, 32, false, (void *)&telem[esc_idx].energy);
|
||||
canardDecodeScalar(transfer, 32, 16, true, (void *)&tmp_float);
|
||||
telem[esc_idx].voltage = canardConvertFloat16ToNativeFloat(tmp_float);
|
||||
canardDecodeScalar(transfer, 48, 16, true, (void *)&tmp_float);
|
||||
telem[esc_idx].current = canardConvertFloat16ToNativeFloat(tmp_float);
|
||||
canardDecodeScalar(transfer, 64, 16, true, (void *)&tmp_float);
|
||||
telem[esc_idx].temperature = canardConvertFloat16ToNativeFloat(tmp_float);
|
||||
canardDecodeScalar(transfer, 80, 18, true, (void *)&telem[esc_idx].rpm);
|
||||
|
||||
#ifdef UAVCAN_ACTUATORS_USE_CURRENT
|
||||
// Update total current
|
||||
electrical.current = 0;
|
||||
for(uint8_t i = 0; i < ACTUATORS_UAVCAN_NB; ++i)
|
||||
electrical.current += uavcan_telem[i].current;*/
|
||||
#ifdef SERVOS_UAVCAN1_NB
|
||||
for (uint8_t i = 0; i < SERVOS_UAVCAN1_NB; ++i) {
|
||||
electrical.current += uavcan1_telem[i].current;
|
||||
}
|
||||
#endif
|
||||
#ifdef SERVOS_UAVCAN2_NB
|
||||
for (uint8_t i = 0; i < SERVOS_UAVCAN2_NB; ++i) {
|
||||
electrical.current += uavcan2_telem[i].current;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an uavcan interface
|
||||
*/
|
||||
void actuators_uavcan_init(struct uavcan_iface_t* iface __attribute__((unused)))
|
||||
void actuators_uavcan_init(struct uavcan_iface_t *iface __attribute__((unused)))
|
||||
{
|
||||
// Check if not already initialized (for multiple interfaces, needs only 1)
|
||||
if(actuators_uavcan_initialized) return;
|
||||
if (actuators_uavcan_initialized) { return; }
|
||||
|
||||
// Bind uavcan ESC_STATUS message from EQUIPMENT
|
||||
uavcan_bind(UAVCAN_EQUIPMENT_ESC_STATUS_ID, UAVCAN_EQUIPMENT_ESC_STATUS_SIGNATURE, &esc_status_ev, &actuators_uavcan_esc_status_cb);
|
||||
uavcan_bind(UAVCAN_EQUIPMENT_ESC_STATUS_ID, UAVCAN_EQUIPMENT_ESC_STATUS_SIGNATURE, &esc_status_ev,
|
||||
&actuators_uavcan_esc_status_cb);
|
||||
|
||||
// Configure telemetry
|
||||
#if PERIODIC_TELEMETRY
|
||||
@@ -128,18 +187,18 @@ void actuators_uavcan_init(struct uavcan_iface_t* iface __attribute__((unused)))
|
||||
/**
|
||||
* Commit actuator values to the uavcan interface
|
||||
*/
|
||||
void actuators_uavcan_commit(struct uavcan_iface_t* iface, int16_t *values, uint8_t nb)
|
||||
{
|
||||
void actuators_uavcan_commit(struct uavcan_iface_t *iface, int16_t *values, uint8_t nb)
|
||||
{
|
||||
uint8_t buffer[UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_MAX_SIZE];
|
||||
uint32_t offset = 0;
|
||||
|
||||
// Encode the values as 14-bit signed integers
|
||||
for(uint8_t i = 0; i < nb; i++) {
|
||||
for (uint8_t i = 0; i < nb; i++) {
|
||||
canardEncodeScalar(buffer, offset, 14, (void *)&values[i]);
|
||||
offset += 14;
|
||||
}
|
||||
|
||||
// Broadcast the raw command message on the interface
|
||||
uavcan_broadcast(iface, UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_SIGNATURE, UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID,
|
||||
CANARD_TRANSFER_PRIORITY_HIGH, buffer, (offset+7)/8);
|
||||
CANARD_TRANSFER_PRIORITY_HIGH, buffer, (offset + 7) / 8);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include BOARD_CONFIG
|
||||
|
||||
/* External functions */
|
||||
extern void actuators_uavcan_init(struct uavcan_iface_t* iface);
|
||||
extern void actuators_uavcan_commit(struct uavcan_iface_t* iface, int16_t *values, uint8_t nb);
|
||||
extern void actuators_uavcan_init(struct uavcan_iface_t *iface);
|
||||
extern void actuators_uavcan_commit(struct uavcan_iface_t *iface, int16_t *values, uint8_t nb);
|
||||
|
||||
#endif /* ACTUATORS_UAVCAN_H */
|
||||
Reference in New Issue
Block a user