www.gusucode.com > Arduino_Engineering_Kit_Hardware_Support_18b 工具箱matlab源码程序 > Arduino_Engineering_Kit_Hardware_Support_18b/matlab/MATLABAddon/+arduinoioaddons/+arduino/MKRMotorCarrier.m

    classdef MKRMotorCarrier < arduinoio.LibraryBase & matlab.mixin.CustomDisplay
% MKRMotorCarrier Create an Arduino MKR motor carrier  device object.

% Copyright 2018 The MathWorks, Inc.

    properties(Access = private, Constant = true)
        CREATE_MOTOR_CARRIER = hex2dec('00')
        DELETE_MOTOR_CARRIER = hex2dec('01')
    end

    properties(SetAccess = immutable)
        I2CAddress
    end
    
    properties(Access = private)
        Bus
    end
    
    properties(Access = private)
        ResourceOwner = 'MKRMotorCarrier';
        MinI2CAddress = hex2dec('66');  
        MaxI2CAddress = hex2dec('66');  
    end
    
    properties(Access = {?arduinoioaddons.arduino.MKRDCMotor, ...
                       ?arduinoioaddons.arduino.MKRRotaryEncoder})
        EncoderExists = [false false];        
    end
    
    properties(Access = protected, Constant = true)
        LibraryName = 'Arduino/MKRMotorCarrier'
        DependentLibraries = {'Servo', 'I2C'}
        ArduinoLibraryHeaderFiles = 'MKRMotorCarrier/MKRMotorCarrier.h' 
        CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', 'MKRMotorCarrierBase.h')
        CppClassName = 'MKRMotorCarrierBase'
    end
    
    %% Constructor
    methods(Hidden, Access = public)
        function obj = MKRMotorCarrier(parentObj, varargin)
            obj.Parent = parentObj;           
            count = incrementResourceCount(obj.Parent, obj.ResourceOwner);
            if count > 1
                obj.localizedError('MATLAB:arduinoio:general:maxAddonLimit',...
                    num2str(1),...
                    obj.ResourceOwner,...
                    obj.Parent.Board);
            end
            
            try
                p = inputParser;
                addParameter(p, 'I2CAddress', hex2dec('66'));
%                 addParameter(p, 'PWMFrequency', 1600);
                parse(p, varargin{:});
            catch
                obj.localizedError('MATLAB:arduinoio:general:invalidNVPropertyName',...
                    obj.ResourceOwner, ...
                    arduinoio.internal.renderCellArrayOfCharVectorsToCharVector(p.Parameters, ', '));
            end
            
            address = validateAddress(obj, p.Results.I2CAddress);
            try
                i2cAddresses = getSharedResourceProperty(parentObj, obj.ResourceOwner, 'i2cAddresses');
            catch
                i2cAddresses = [];
            end
            if ismember(address, i2cAddresses)
                obj.localizedError('MATLAB:arduinoio:general:conflictI2CAddress', ...
                    num2str(address),...
                    dec2hex(address));
            end
            i2cAddresses = [i2cAddresses address];
            setSharedResourceProperty(parentObj, obj.ResourceOwner, 'i2cAddresses', i2cAddresses);
            obj.I2CAddress = address;
            
%             frequency = arduinoio.internal.validateDoubleParameterRanged('PWM frequency', p.Results.PWMFrequency, 0, 2^15-1, 'Hz');
%             obj.PWMFrequency = frequency;            
            configureI2C(obj);            
%             obj.ShieldSlotNum = getFreeResourceSlot(obj.Parent, obj.ResourceOwner);
            createMotorCarrier(obj);            
            setSharedResourceProperty(parentObj, 'I2C', 'I2CIsUsed', true);
        end
    end
    
    %% Destructor
    methods (Access=protected)
        function delete(obj)
            originalState = warning('off','MATLAB:class:DestructorError');
            try
                parentObj = obj.Parent;
                i2cAddresses = getSharedResourceProperty(parentObj, obj.ResourceOwner, 'i2cAddresses');
                if ~isempty(i2cAddresses)
                    if ~isempty(obj.I2CAddress) 
                        % Can be empty if failed during construction
                        i2cAddresses(i2cAddresses==obj.I2CAddress) = [];
                    end
                end
                setSharedResourceProperty(parentObj, obj.ResourceOwner, 'i2cAddresses', i2cAddresses);
                decrementResourceCount(obj.Parent, obj.ResourceOwner);
%                 clearResourceSlot(parentObj, obj.ResourceOwner, obj.ShieldSlotNum);
                deleteMotorCarrier(obj);
            catch
                % Do not throw errors on destroy.
                % This may result from an incomplete construction.
            end
            warning(originalState.state, 'MATLAB:class:DestructorError');
        end
    end
    
    %% Public methods
    methods (Access = public)
        function servoObj = servo(obj, motornum, varargin)
            %   Attach a servo motor to the specified port on MKR Motor
            %   Carrier
            %
            %   Syntax:
            %   s = servo(mcObj, motornum)
            %   s = servo(mcObj, motornum,Name,Value)
            %
            %   Description:
            %   s = servo(mcObj, motornum)Creates a servo motor object connected to the specified port on the MKR Motor Carrier
            %   s = servo(mcObj, motornum,Name,Value) Creates a servo motor object with additional options specified by one or more Name-Value pair arguments.
            %
            %   Example:
            %       a = arduino('COM7', 'Uno', 'Libraries', 'Arduino/MKRMotorCarrier');
            %       mcObj = addon(a, 'Arduino/MKRMotorCarrier');
            %       s = servo(mcObj,1);
            %
            %   Input Arguments:
            %   mcObj      - Arduino MKR motor carrier object
            %   motornum - Port number the motor is connected to on the carrier (numeric)
            %
            %   Name-Value Pair Input Arguments:
            %   Specify optional comma-separated pairs of Name,Value arguments. Name is the argument name and Value is the corresponding value. 
            %   Name must appear inside single quotes (' '). You can specify several name and value pair arguments in any order as Name1,Value1,...,NameN,ValueN.
            %   See also dcmotor
            
            try
                servoObj = arduinoioaddons.arduino.MKRServo(obj, motornum, varargin{:});
            catch e
                throwAsCaller(e);
            end
        end
        
        function dcmotorObj = dcmotor(obj, motornum, varargin)
            %   Attach a DC motor to the specified port on MKR Motor Carrier
            %
            %   Syntax:
            %   dcm = dcmotor(mcObj, motornum)
            %   dcm = dcmotor(mcObj, motornum,Name,Value)
            %
            %   Description:
            %   dcm = dcmotor(mcObj, motornum)            Creates a dcmotor motor object connected to the specified port on the Arduino MKR motor carrier.
            %   dcm = dcmotor(mcObj, motornum,Name,Value) Creates a dcmotor motor object with additional options specified by one or more Name-Value pair arguments.
            %
            %   Example:
            %       a = arduino('COM7', 'Uno', 'Libraries', 'Arduino/MKRMotorCarrier');
            %       mcObj = addon(a, 'Arduino/MKRMotorCarrier');
            %       dcm = dcmotor(mcObj,1);
            %
            %   Example:
            %       a = arduino('COM7', 'Uno', 'Libraries', 'Arduino/MKRMotorCarrier');
            %       mcObj = addon(a, 'Arduino/MKRMotorCarrier');
            %       dcm = dcmotor(mcObj,1,'DutyCycle',0.2);
            %
            %   Input Arguments:
            %   mcObj     -Arduino MKR motor carrier object
            %   motornum - Port number the motor is connected to on the carrier (numeric)
            %
            %   Name-Value Pair Input Arguments:
            %   Specify optional comma-separated pairs of Name,Value arguments. Name is the argument name and Value is the corresponding value. 
            %   Name must appear inside single quotes (' '). You can specify several name and value pair arguments in any order as Name1,Value1,...,NameN,ValueN.
            %
            %   NV Pair:
            %   'DutyCycle' - The dutycycle of the motor that ranges from -1 to 1 (numeric, 
            %                     default 0.
            %
            %   See also servo
            
            try
                dcmotorObj = arduinoioaddons.arduino.MKRDCMotor(obj, motornum, varargin{:});
            catch e
                throwAsCaller(e);
            end            
        end     
        function encoderObj = rotaryEncoder(obj, Channel, varargin)
            try
               encoderObj = arduinoioaddons.arduino.MKRRotaryEncoder(obj,Channel,varargin{:});
            catch e
               throwAsCaller(e);
            end
        end      
     end
    
    %% Private methods
    methods (Access = private)
        function createMotorCarrier(obj)        
            commandID = obj.CREATE_MOTOR_CARRIER;
%             frequency = typecast(uint16(obj.PWMFrequency), 'uint8');
            data = uint8(obj.I2CAddress);
            sendCommandCustom(obj, obj.LibraryName, commandID, data);
        end
        
        function deleteMotorCarrier(obj)
            commandID = obj.DELETE_MOTOR_CARRIER;
            
            params = [];
            sendCommandCustom(obj, obj.LibraryName, commandID, params);
        end
    end
    
    %% Helper method to related classes
    methods (Access = {?arduinoioaddons.arduino.MKRServo, ...
                       ?arduinoioaddons.arduino.MKRDCMotor, ...
                       ?arduinoioaddons.arduino.MKRRotaryEncoder})
        function output = sendCarrierCommand(obj, commandID, inputs, timeout)
            switch nargin
                case 3
                    output = sendCommandCustom(obj, obj.LibraryName, commandID, inputs);
                case 4
                    output = sendCommandCustom(obj, obj.LibraryName, commandID, inputs, timeout);
                otherwise
            end
        end
    end
    
    methods(Access = private)
        function addr = validateAddress(obj, address)
            % accept string type address but convert to character vector
            if isstring(address)
                address = char(address);
            end
            if ~ischar(address)
                try
                    addr = arduinoio.internal.validateIntParameterRanged('address', address, obj.MinI2CAddress, obj.MaxI2CAddress);
                    return;
                catch
                    printableAddress = false;
                    try
                        printableAddress = (numel(num2str(address)) == 1);
                    catch
                    end
                    
                    if printableAddress
                        obj.localizedError('MATLAB:arduinoio:general:invalidI2CAddress', num2str(address), num2str(obj.MinI2CAddress), num2str(obj.MaxI2CAddress));
                    else
                        obj.localizedError('MATLAB:arduinoio:general:invalidI2CAddressType');
                    end
                end

            else            
                tmpAddr = address;
                
                try
                    index = strfind(lower(tmpAddr), '0x');
                    if index == 1
                        tmpAddr = tmpAddr(3:end);
                    elseif strcmpi(tmpAddr(end), 'h')
                        tmpAddr(end) = [];
                    end
                    addressInDec = hex2dec(tmpAddr);
                catch 
                    obj.localizedError('MATLAB:arduinoio:general:invalidI2CAddress', address, num2str(obj.MinI2CAddress), num2str(obj.MaxI2CAddress));
                end
            
                if addressInDec < obj.MinI2CAddress || addressInDec > obj.MaxI2CAddress
                    obj.localizedError('MATLAB:arduinoio:general:invalidI2CAddress', address, num2str(obj.MinI2CAddress), num2str(obj.MaxI2CAddress));
                end
            end
            
            addr = addressInDec;
        end
    
        function configureI2C(obj)
            parentObj = obj.Parent;
            I2CTerminals = parentObj.getI2CTerminals();
            
            if ~strcmp(parentObj.Board, 'Due')
                obj.Bus = 0;
                resourceOwner = '';
                sda = parentObj.getPinsFromTerminals(I2CTerminals(obj.Bus*2+1)); sda = sda{1};
                configurePinResource(parentObj, sda, resourceOwner, 'I2C', false);
                scl = parentObj.getPinsFromTerminals(I2CTerminals(obj.Bus*2+2)); scl = scl{1};
                configurePinResource(parentObj, scl, resourceOwner, 'I2C', false);
                obj.Pins = {sda scl};
            else
                obj.Bus = 1;
                obj.Pins = {'SDA1', 'SCL1'};
            end
        end
    end
    
    %% Protected methods
    methods(Access = protected)
        function output = sendCommandCustom(obj, libName, commandID, inputs, timeout)
            if nargin > 4
                [output, ~] = sendCommand(obj, libName, commandID, inputs, timeout);
            else
                [output, ~] = sendCommand(obj, libName, commandID, inputs);
            end
        end
        
        function displayScalarObject(obj)
            header = getHeader(obj);
            disp(header);
            
            % Display main options
            pins = [obj.Pins{1} '(SDA), ' obj.Pins{2} '(SCL)'];
            fprintf('            Pins: %-15s\n', pins);
            fprintf('      I2CAddress: %-1d (0x%02s)\n', obj.I2CAddress, dec2hex(obj.I2CAddress));
            fprintf('\n');
                  
            % Allow for the possibility of a footer.
            footer = getFooter(obj);
            if ~isempty(footer)
                disp(footer);
            end
        end
    end
end