Page tree
Skip to end of metadata
Go to start of metadata

Introduction

In this article we will extend functionality of a UAVCAN node from previous tutorial. For pragmatic purposes we will make something that can be used - UAVCAN to RCPWM converter.

Goal

Our goal is to make Zubax Babel act as UAVCAN node and receive RCPWM values via CAN and then convert them to RCPWM signal.

Couple words about RCPWM. RCPWM is the most widespread way of interaction in hobby RC world. All servos and almost all motor controllers support it(and there are lots and lots of other devices that communicate this way). Without doubt it is very old, slow and limited interface and today it must be replaced with something better like UAVCAN. But this is legacy and we have to deal with it. From physical standpoint RCPWM is just PWM signal with period of 20mS and the infromation is coded in pulse widthm which may vary from 1 mS to 2 mS with neutral value 1.5 mS. To generate that we will use timers that are available on Zubax Babel according to datasheet where we can find detailed pinout:


We will use TIM12_CH1, TIM12_CH2, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4, utilizing all available pins.

Implementation

We will base our project on the code from Basic tutorial end add lacking functions. Firstly we should add support of a new message type to shouldAcceptTransfer  and its appropriate handler to onTransferReceived

shouldAcceptTransfer
bool shouldAcceptTransfer(const CanardInstance* ins,
                          uint64_t* out_data_type_signature,
                          uint16_t data_type_id,
                          CanardTransferType transfer_type,
                          uint8_t source_node_id)
{
    if ((transfer_type == CanardTransferTypeRequest) &&
        (data_type_id == UAVCAN_GET_NODE_INFO_DATA_TYPE_ID))
    {
        *out_data_type_signature = UAVCAN_GET_NODE_INFO_DATA_TYPE_SIGNATURE;
        return true;
    }

    if(data_type_id == UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID)
    {
        *out_data_type_signature = UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_SIGNATURE;
        return true;
    }
   
    return false;
}


onTransferReceived
void onTransferReceived(CanardInstance* ins, CanardRxTransfer* transfer)
{
    if ((transfer->transfer_type == CanardTransferTypeRequest) &&
    (transfer->data_type_id == UAVCAN_GET_NODE_INFO_DATA_TYPE_ID))
    {
        canard_get_node_info_handle(transfer);
    } 
    
    if(transfer->data_type_id == UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID)
    { 
        canard_rawcmd_handle(transfer);
    }
}

We added support of UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_ID, message that contains all values needed to generate RCPWM signal. UAVCAN GUI Tool starts to broadcast these messages when ESC Management panel is opened. 

Now its handler's turn, where RCPWM values are passed to MCU timers

canard_rawcmd_handle
void canard_rawcmd_handle(CanardRxTransfer* transfer)
{
    int16_t ar[6] = {0,0,0,0,0,0};
    int offset = 0;
    for(int i = 0; i<6; i++)
    {
        if(canardDecodeScalar(transfer, offset, 14, true, &ar[i])<14) {break;}
        offset += 14;
    }
    rcpwm_update(ar);
}

const rcpwm_t rcpwm_outputs[] = 
{
    {TIM12, 1, "TIM12_CH1_PA4"},
    {TIM12, 2, "TIM12_CH1_PA5"},
    {TIM3,  1, "TIM3_CH1_PA6"},
    {TIM3,  2, "TIM3_CH2_PB0"},
    {TIM3,  3, "TIM3_CH3_PB6"},
    {TIM3,  4, "TIM3_CH4_PB7"}
};

void rcpwm_update(int16_t ar[6])
{
    for(char i = 0; i < 6; i++ )
    {
        uint32_t val = RCPWM_NEUTRAL_uS;
        ar[i] = ar[i] * RCPWM_MAGNITUDE_uS / UAVCAN_EQUIPMENT_ESC_RAWCOMMAND_MAX_VALUE;
        val += ar[i];
        TIM_SetCompare(rcpwm_outputs[i].timer,rcpwm_outputs[i].channel, uS_to_ticks(val));
    }
}


static void TIM_SetCompare(TIM_TypeDef* TIMx, uint8_t ch, uint32_t Compare)
{
    if(ch == 1)  
    {
        TIMx->CCR1 = Compare;
        return;
    }
    if(ch == 2)  
    {
        TIMx->CCR2 = Compare;
        return;
    }
    if(ch == 3)  
    {
        TIMx->CCR3 = Compare;
        return;
    }
    if(ch == 4)  
    {
        TIMx->CCR4 = Compare;
        return;
    }
}

And that's it. Now its time to open UAVCAN GUI Tool and go to ESC Management panel

Our device supports up to six channels, so increase number of channels and try moving sliders. 

If you connect oscilloscope Babel you may see something like this:

Or you may connect servos and see them moving after the slider in ESC panel.



  • No labels