A Roboteq controller c++ interface to allow a Brushless motor control on a CAN bus. Used for a FBL2360 reference.

Dependencies:   CAN_FIFO_Triporteur

RoboteqController.cpp

Committer:
zephyrcare
Date:
2018-05-29
Revision:
4:1ee0a235c997
Parent:
3:a03c91082856
Child:
6:f9c4795448c1

File content as of revision 4:1ee0a235c997:

#include "RoboteqController.h"

const uint16_t RoboteqController::RPDO_ID[4] = {0x200, 0x300, 0x400, 0x500};   // RPDO msg IDs to send data to the controller

RoboteqController::RoboteqController(){
}

RoboteqController::RoboteqController(ControllerCAN* controller, uint8_t node_id, uint8_t mot_num, bool TPDO_enabled) : 
                    PeripheralCAN(controller),
                    node_id(node_id), mot_num(mot_num),
                    Id_CSS_REQ(SDO_REQUEST+node_id), Id_CSS_ANS(SDO_ANSWER+node_id),
                    Id_TPDO1(ID_TPDO1+node_id),Id_TPDO2(ID_TPDO2+node_id), Id_TPDO3(ID_TPDO3+node_id), Id_TPDO4(ID_TPDO4+node_id) {
    PeripheralCAN::addIdRead(&Id_CSS_REQ);
    PeripheralCAN::addIdRead(&Id_CSS_ANS);
    
    // If TPDO is enabled, make TPDO message readable
    if(TPDO_enabled){
        PeripheralCAN::addIdRead(&Id_TPDO1);
        PeripheralCAN::addIdRead(&Id_TPDO2);
        PeripheralCAN::addIdRead(&Id_TPDO3);
        PeripheralCAN::addIdRead(&Id_TPDO4);
    }
}

RoboteqController::~RoboteqController(){}
    

void RoboteqController::update(const unsigned short& Id, const CANMessage& msg){
    SDOMessage SDOmsg;
    
    /* Treatment of the controller answer */
    if(Id == Id_CSS_ANS){
        CANMsg2SDO(msg, SDOmsg);
        
        switch(SDOmsg.idx){
            case qBS: // Brushless speed in rpm
                speed = (int16_t) (SDOmsg.data[1] << 8) + SDOmsg.data[0];
            break;
            //case 
            //..
        }
    }
    else if (Id == Id_TPDO1){
        TPDO_receive(1, msg);
    }
    else if (Id == Id_TPDO2){
        TPDO_receive(2, msg);
    }
    else if (Id == Id_TPDO3){
        TPDO_receive(3, msg);
    }
    else if (Id == Id_TPDO4){
        TPDO_receive(4, msg);
    }
}

void RoboteqController::SDO_query(uint8_t n, uint16_t idx, uint8_t sub_idx){
    char buffer[8];
    
    buffer[0] = (CSS_QUERY << 4) + (n << 2);
    buffer[1] = idx;
    buffer[2] = (idx >> 8);
    buffer[3] = sub_idx;
    
    // Clear bytes 4-7 because no data are  uploaded (it's a query)
    for(int i = 4 ; i < 7 ; i++){
        buffer[i] = 0;
    }
    
    writeOnCAN(Id_CSS_REQ, buffer, 8);
}

void RoboteqController::SDO_command(uint8_t n, uint16_t idx, uint8_t sub_idx, uint8_t *data){
    char msg[8];
    
    msg[0] = (CSS_CMD << 4) + (n << 2);
    msg[1] = idx;
    msg[2] = (idx >> 8);
    msg[3] = sub_idx;
    
    // Load bytes 4-7 from data array
    for(int i = 0 ; i < 4-n ; i++){
        msg[4+i] = *(data+i);
    }
    
    writeOnCAN(Id_CSS_REQ, msg, 8);
}

void RoboteqController::CANMsg2SDO(const CANMessage& CANmsg, SDOMessage& SDOmsg){
    SDOmsg.css = (CANmsg.data[0] & 0xF0 >> 4);
    SDOmsg.n = (CANmsg.data[0] & 0x0F >> 2);
    SDOmsg.idx = CANmsg.data[1] + (CANmsg.data[2] << 8);
    SDOmsg.subindex = CANmsg.data[3];
    SDOmsg.data[0] = CANmsg.data[4];
    SDOmsg.data[1] = CANmsg.data[5];
    SDOmsg.data[2] = CANmsg.data[6];
    SDOmsg.data[3] = CANmsg.data[7];
}

void RoboteqController::RPDO_send(uint8_t n, int32_t user_var1, int32_t user_var2){
    char buffer[8];
    
    buffer[0] = user_var1;
    buffer[1] = (user_var1 >> 8);
    buffer[2] = (user_var1 >> 16);
    buffer[3] = (user_var1 >> 24);
    
    buffer[4] = user_var2;
    buffer[5] = (user_var2 >> 8);
    buffer[6] = (user_var2 >> 16);
    buffer[7] = (user_var2 >> 24);
    
    writeOnCAN(RPDO_ID[n-1] + node_id, buffer, 8);
}

void RoboteqController::TPDO_parse(const CANMessage& CANmsg, int32_t* p_user_var1, int32_t* p_user_var2){
    *p_user_var1 = CANmsg.data[0] + (CANmsg.data[1] << 8) + (CANmsg.data[2] << 16) + (CANmsg.data[3] << 24);
    *p_user_var2 = CANmsg.data[4] + (CANmsg.data[5] << 8) + (CANmsg.data[6] << 16) + (CANmsg.data[7] << 24);
}

void RoboteqController::TPDO_receive(uint8_t n, const CANMessage& CANmsg){
    /* Nothing to do, use the following structure in a redefinition :
    if (n == 1){
        // User defined section
    }
    else if (n == 2){
        // User defined section
    }
    else if (n == 3){
        // User defined section
    }
    else if (n == 4){
        // User defined section
    }
    */
}


void RoboteqController::sendCommand(uint32_t cmd){
    uint8_t data[4];
    
    data[0] = cmd;
    data[1] = (cmd>>8);
    data[2] = (cmd>>16);
    data[3] = (cmd>>24);
    
    SDO_command(0, cCANGO, mot_num, data);
}