PSL_2021 / servomotor_MX12_Lorenzo

Dependents:   PSL_ROBOT_lorenzo robot_lorenzo recepteur_mbed_os_6

MX12.h

Committer:
denis2nis
Date:
2021-11-04
Revision:
7:68983a9b0531
Parent:
6:177aead4eb6b
Child:
8:e74ef93ae660

File content as of revision 7:68983a9b0531:

/**  
* @file MX12.h  
* @brief this header file will contain all required  
*        definitions and basic utilities functions. 
* @details comming soon
*  
* 
*/ 
#ifndef MBED_MX12_H
#define MBED_MX12_H

#include "mbed.h"

#define MX12_DATA_MAX_SIZE 256
#define MX12_MAX_MOTOR_COUNT 16

/* Dynamixel protocol v1.0 : Instructions
 ******************************************/
#define PROTOCOL_INSTRUCTION_PING          0x01
#define PROTOCOL_INSTRUCTION_READ          0x02
#define PROTOCOL_INSTRUCTION_WRITE         0x03
#define PROTOCOL_INSTRUCTION_REG_WRITE     0x04
#define PROTOCOL_INSTRUCTION_ACTION        0x05
#define PROTOCOL_INSTRUCTION_FACTORY_RESET 0x06
#define PROTOCOL_INSTRUCTION_REBOOT        0x08
#define PROTOCOL_INSTRUCTION_SYNC_WRITE    0x83
#define PROTOCOL_INSTRUCTION_BULK_READ     0x92

/* Dynamixel protocol v1.0 : Contro table content
 ************************************************/
#define CONTROL_TABLE_MODEL_NUMBER            0
#define CONTROL_TABLE_FIRMWARE_VERSION        2 
#define CONTROL_TABLE_ID                      3
#define CONTROL_TABLE_BAUD_RATE               4
#define CONTROL_TABLE_RETURN_DELAY_TIME       5
#define CONTROL_TABLE_CW_ANGLE_LIMIT          6
#define CONTROL_TABLE_CCW_ANGLE_LIMIT         8
#define CONTROL_TABLE_TEMPERATURE_LIMIT      11
#define CONTROL_TABLE_MIN_VOLTAGE_LIMIT      12
#define CONTROL_TABLE_MAX_VOLTAGE_LIMIT      13
#define CONTROL_TABLE_MAX_TORQUE             14
#define CONTROL_TABLE_STATUS_RETURN_LEVEL    16
#define CONTROL_TABLE_ALARM_LED              17
#define CONTROL_TABLE_SHUTDOWN               18
#define CONTROL_TABLE_MULTITURN_OFFSET       20
#define CONTROL_TABLE_RESOLUTION_DIVIDER     22
#define CONTROL_TABLE_TORQUE_ENABLE          24
#define CONTROL_TABLE_LED                    25
#define CONTROL_TABLE_P_GAIN                 26
#define CONTROL_TABLE_I_GAIN                 27
#define CONTROL_TABLE_D_GAIN                 28
#define CONTROL_TABLE_GOAL_POSITION          30
#define CONTROL_TABLE_MOVING_SPEED           32
#define CONTROL_TABLE_TORQUE_LIMIT           34
#define CONTROL_TABLE_PRESENT_POSITION       36
#define CONTROL_TABLE_PRESENT_SPEED          38
#define CONTROL_TABLE_PRESENT_LOAD           40
#define CONTROL_TABLE_PRESENT_VOLTAGE        42
#define CONTROL_TABLE_PRESENT_TEMPERATURE    43
#define CONTROL_TABLE_REGISTRED_INSTRUCTION  44
#define CONTROL_TABLE_MOVING                 46
#define CONTROL_TABLE_LOCK                   47
#define CONTROL_TABLE_PUNCH                  48
#define CONTROL_TABLE_GOAL_ACCELERATION      73

/** 
 * @brief Class to communicate with Dynamixel MX12 servomotors. 
 *
 * @details
 *  The servomotors are daisy chained to a serial link of the target 
 *  microcontroller. The class ensures the initialization of serial link 
 *  and the management of communications. 
 *  Transmission of messages to the servomotors is blocking while 
 *  reception is non-blocking thanks to the use of an interrupt routine. 
 *
 * 
 * @author Titouan Soulard (creator and maintainer until April 2021)
 * @author Bruno Denis (Doxygen documentation and code rearrangement)
 *  
 * @see Control table of Dynamixel MX12 servomotor 
 * @see https://emanual.robotis.com/docs/en/dxl/mx/mx-12w/
 * @see Dynamixel protocol v1.0 manual
 * @see https://emanual.robotis.com/docs/en/dxl/protocol1/
 *
 * @warning 
 *    Error field of status packet if decoded by GetStatus(() function which
 *    returns an enumation type "Status". As several errors can be reported 
 *    simultaneously the type enum is not suitable (B. Denis 11/2021)
 */
class MX12 
{
    public:
    
        /** Error status occurred during the operation of servomotor.
         *
         * @warning 
         *    Enumaration type is not suitable for all error status because
         *    it can denote only one error at a time (B. Denis 11/2021)
         */
        enum Status {
            InstructionError,  /**<  In case of sending an undefined instruction 
                                     or delivering the action instruction 
                                     without the Reg Write instruction */
            OverloadError,     /**<  When the current load cannot be controlled 
                                     by the set Torque */
            ChecksumError,     /**<  When the Checksum of the transmitted 
                                     Instruction Packet is incorrect */
            RangeError,        /**<  When an instruction is out of the range 
                                     for use */
            OverheatingError,  /**<  When internal temperature of servomotor 
                                     is out of the range of operating 
                                     temperature set in the Control table */
            AngleLimitError,   /**<  When Goal Position is written out of the 
                                     range from CW Angle Limit to CCW Angle 
                                     Limit */
            InputVoltageError, /**<  When the applied voltage is out of the 
                                     range of operating voltage set in the 
                                     Control table */
            Unknown,           /**<  Combination of several errors (Caution: 
                                     limit of enum approach to code errors) */
            Ok                 ///<  no error
        };
        
        /** State of packet parser to determine the meaning of reading byte
         *  into the received packet (satuts packet) according the Dynamixel
         *  protocol v1.0
         */
        enum ParsingState {
            Header,    ///< reading the two heading bytes
            Id,        ///< reading the servomotor ID byte
            Length,    ///< reading byte length of the instruction
            Data,      ///< reading parameters
            Checksum,  ///< reading one bytes checksum 
        };

        /** Enumeration of states of the acces methode of the master-slave 
         *  protocol of the communication between the robot controller (master) 
         *  and the servomotors (slaves).
         */
         enum SerialState {
            Writing, /**< Robot controller send an "instruction packet"
                          (request) to a servomotor */
            Reading, /**< Robot controller receive a "status packet" from a 
                          requested servomotor */
            Idle,    ///< Robot controller ready for a new cycle request-answer 
        };
        
        /**  type
         */
        struct Frame {
            unsigned char motorId;
            unsigned char length;
            unsigned char data[MX12_DATA_MAX_SIZE];
            unsigned char valid;
        };

        /** 
         */
        struct StateContext {
            unsigned char headingCount;
            unsigned char dataCount;
            unsigned char checksum;
        };
  
        /** Create MX12 instance
         *
         * @param tx board pin used for transmission in UART daisy chain link 
         *           to servomotors 
         * @param rx board pin used for reception in UART daisy chain link 
         *           to servomotors 
         * @param baud modulation rate of UART signal, unit: Baud
         *           to servomotors 
         */
        MX12(PinName tx, PinName rx, int baud=115200);
        
        /** Send desired speed to a specifc servomotor
         *
         * @param mot_id a unique value in the daisy chain network to identify
         *               each servomotor
         * @param speed a float between -1 and 1 that represents the percentage
         *              of maximum requested speed
         */
        void SetSpeed(unsigned char mot_id, float speed);
        
        char IsAvailable(void);
        
        /**
         * Build and send an instruction packet to a servomotor according
         * DYNAMIXEL Protocol 1.0 (online protocol documentation 
         * https://emanual.robotis.com/docs/en/dxl/protocol1/)
         *
         * @param[in] mot_id indicates the ID of the device (servomotor) that
         *            should receive the Instruction Packet and process it
         * @param[in] address data address in the "Control Table of RAM Area"
         *            of a servomotor MX12 
         *            (https://emanual.robotis.com/docs/en/dxl/mx/mx-12w/#control-table-of-ram-area).
         * @param[in] len if it is a write instruction, size in bytes 
         *            of the data to write in the "Control Table of RAM Area"
         * @param[in] data array of char containing parameter of Danamixel  
         *            protocol that are the instruction’s auxiliary data field
         *  
         * @see https://emanual.robotis.com/docs/en/dxl/protocol1/
         *
         * Packet sent
         * <PRE>
         * |Header1|Header2|Packet ID|Length|Instruction|Param1...ParamN|Checksum|
         * |-------|-------|---------|------|-----------|---------------|--------|
         * |  0xFF |  0xFF |Packet ID|Length|Instruction|Param1...ParamN| CHKSUM |
         * | cmd[0]| cmd[1]|  cmd[2] |cmd[3]|  cmd[4]   |cmd[5]...      |        |
         *                  \\__  ___/                    \\_  _/ \\__  __/
         *                     \/                          \/      \/
         *                   mot_id                      address   data
         *                                                        (len = N-1)
         * </PRE>
         */
        void rw(unsigned char mot_id, char address, char len, char *data);
        
        /**
         * 
         * @warning
         *    
         */
        void PrintSerial();
        
        /**
         * Get information from de Error byte of the last status packet
         * received from a servomotor
         *
         * @return 
         *    One of enum MX12::Status value to describe errors. 'Ok' is
         *    returns if no error occurred during the last operation of
         *    servomotor.
         * 
         * @warning 
         *    If a combination of several errors is reported the function
         *    returns 'Unknown' (B. Denis 11/2021)
         */
        MX12::Status GetStatus(void);

        /* function aivailaible in a previous version of the class 
         */
        // MX12::Status GetStatus(void);
        // void ReadPosition(unsigned char mot_id);
        // float GetPosition(unsigned char mot_id);
        
    private:
    
        UnbufferedSerial _mx12;
        MX12::ParsingState _pstate;
        MX12::SerialState _sstate;
        MX12::StateContext _scontext;
        MX12::Frame _current_frame;
                
        unsigned char _answer;
        unsigned char _stored_frame[MX12_DATA_MAX_SIZE];
        unsigned char _frame_pointer;
        
        /** Interupt Routine to read in data from UART daisy chain link
         *  (serial port)
         *
         */
        void _ReadCallback();
};

#endif /* MBED_MX12_H */