www.gusucode.com > Arduino_Engineering_Kit_Hardware_Support 工具箱matlab源码程序 > Arduino_Engineering_Kit_Hardware_Support/simulink/+motorcarrier/+blocks/mkrmotorcarrier_Encoder.m

    classdef mkrmotorcarrier_Encoder < matlab.System ...
        & coder.ExternalDependency ...
        & matlab.system.mixin.Propagates ...
        & matlab.system.mixin.internal.CustomIcon ...
        & matlab.system.mixin.internal.SampleTime
    %
    % Encoder - MKR Motor Carrier
    %
    
    % Copyright 2018 The MathWorks, Inc.
    
    %#codegen
    %#ok<*EMCA>
    
    properties (Nontunable)
        % Encoder - Encoder
        Encoder = '1';     
        % SlaveAddress_ - I2C Slave Address
        SlaveAddress_ = hex2dec('66');
        %SampleTime Sample time
        SampleTime = 0.1;
    end
    
    properties (Nontunable, Logical)
        % ShowSpeed - Show Speed output port
        ShowSpeed = false;
        % ResetOption - Reset at initialization
        ResetOption = true;        
    end
    
    properties(Constant, Hidden)
        EncoderSet = matlab.system.StringSet({'1', '2'});        
        
        % --------------Commands for Encoder at D11---------------------
          GET_RAW_COUNT_ENCODER							=    7    ;
          RESET_COUNT_ENCODER                           =    8    ;
          GET_OVERFLOW_UNDERFLOW_STATUS_ENCODER         =    9    ;
          GET_COUNT_PER_SECOND_ENCODER                  =    10   ;  
          SET_INTERRUPT_ON_COUNT_ENCODER                =    11   ;  
          SET_INTERRUPT_ON_VELOCITY_ENCODER             =    12   ;  
    end
    
    properties (Dependent,Hidden)
        Encoder_num
    end
        
    methods
        % Constructor
        function obj = mkrmotorcarrier_Encoder(varargin)
            coder.allowpcode('plain');
            setProperties(obj,nargin,varargin{:});
        end 
        
        function set.SampleTime(obj,sampleTime)
            coder.extrinsic('error');
            coder.extrinsic('message');
            
            validateattributes(sampleTime,{'numeric'},...
                {'nonnan', 'finite'},...
                '','''Sample time''');
            
            % Sample time must be a real scalar value or 2 element array.
            if ~isreal(sampleTime(1)) || numel(sampleTime) > 2
                error(message('arduino:build:InvalidSampleTimeNeedScalar'));
            end
            if numel(sampleTime) == 2 && sampleTime(1) > 0.0 && sampleTime(2) >= sampleTime(1)
                error(message('arduino:build:InvalidSampleTimeNeedSmallerOffset'));
            end
            if numel(sampleTime) == 2 && sampleTime(1) == -1.0 && sampleTime(2) ~= 0.0
                error(message('arduino:build:InvalidSampleTimeNeedZeroOffset'));
            end
            if numel(sampleTime) == 2 && sampleTime(1) == 0.0 && sampleTime(2) ~= 1.0
                error(message('arduino:build:InvalidSampleTimeNeedOffsetOne'));
            end
            obj.SampleTime = sampleTime;
        end
        
        function val = get.Encoder_num(obj)
            switch obj.Encoder
                case '1'
                    val = 0;
                case '2'
                    val = 1;
            end
        end
    end
    
    methods (Access = protected)
       % Set data in D11
        function D11_setData(obj, command, target, data) 
            % Convert int32 data to uint8 (Little Endian by default)
            data_uint8 = typecast(int32(data), 'uint8');
            % Data to write over I2C 
            final_data_to_write = [uint8(command), uint8(target), data_uint8];
            if coder.target('Rtw')% done only for code gen
                coder.cinclude('MW_arduinoI2C.h');
                coder.ceval('MW_i2cWriteLoop', uint8(obj.SlaveAddress_), 0, 0, ...
                         coder.rref(final_data_to_write), 6);
            elseif ( coder.target('RtwForRapid') || coder.target('RtwForSfun') )
            end
        end
        
        % Get data from D11
        function data = D11_getData(obj, command, target) 
            % First write the command and target over I2C
            final_data_to_write = [uint8(command), uint8(target)];
            % Number of bytes to read
            num_bytes_to_read = 5;
            % Allocate out
            out_raw = coder.nullcopy(uint8(zeros(1, num_bytes_to_read)));
            if coder.target('Rtw')% done only for code gen
                coder.cinclude('MW_arduinoI2C.h');
                coder.ceval('MW_i2cWriteLoop', uint8(obj.SlaveAddress_), 0, 0, ...
                         coder.rref(final_data_to_write), 2);
                % Read the 5 bytes (irq_status + int32 data) of data over I2C 
                coder.ceval('MW_i2cReadLoop', uint8(obj.SlaveAddress_),...
                    0, 0, uint8(num_bytes_to_read), coder.wref(out_raw));
            elseif ( coder.target('RtwForRapid') || coder.target('RtwForSfun') )
            end
            
            % Ignore the first irq_status byte received for the time being
            out = out_raw(2:end);
            % Concatenate received bytes to get int32 data
            data = typecast(out, 'int32');
        end
        
        function Encoder_resetCounter(obj)
            D11_setData(obj, uint8(obj.RESET_COUNT_ENCODER),...
                uint8(obj.Encoder_num), int32(0));
        end
        
        function out = Encoder_getRawCount(obj)
            out = D11_getData(obj, uint8(obj.GET_RAW_COUNT_ENCODER),...
                uint8(obj.Encoder_num));
        end
        
        function out = Encoder_getCountPerSecond(obj)
            out = D11_getData(obj, uint8(obj.GET_COUNT_PER_SECOND_ENCODER),...
                uint8(obj.Encoder_num));
        end
    end
    
    methods (Access=protected)
        function setupImpl(obj)            
            if coder.target('Rtw')                             
                % Reset the Encoder count if specified
                if obj.ResetOption
                   Encoder_resetCounter(obj);
                end
            else
                % Do nothing
            end
        end

        function releaseImpl(~)
            % Release resources, such as file handles           
        end
        
        function varargout =  stepImpl(obj)
            count       = int32(0); 
            speed       = int32(0); %counts per second
            if coder.target('Rtw')                
                count = Encoder_getRawCount(obj);
                if obj.ShowSpeed
                    % Encoder_getCountPerSecond returns counts per
                    % centisecond (0.01s) so multiplication factor of 100 
                    % for counts per second 
                    speed = Encoder_getCountPerSecond(obj) * 100; 
                end
            else
                % Do nothing
            end
            
            varargout{1} = count;
            varargout{2} = speed;
        end
    end
    
    methods (Access=protected)
        %% Define input properties
        function num = getNumInputsImpl(~)
            num = 0;
        end
        
        function num = getNumOutputsImpl(obj)
            if obj.ShowSpeed
                num = 2;           
            else
                num = 1;
            end
        end
        
        function varargout = getOutputNamesImpl(obj)
            varargout{1} = 'Position';
            if obj.ShowSpeed
                varargout{2} = 'Speed';
            end
        end
        
        function varargout= getOutputSizeImpl(obj)
            varargout{1} = [1,1];
            if obj.ShowSpeed
                varargout{2} = [1,1];
            end
        end
        
        function varargout= getOutputDataTypeImpl(obj)
            for N = 1 : obj.getNumOutputsImpl
               varargout{N} = 'int32';
           end
        end
        
        function varargout  = isOutputComplexImpl(obj)
           for N = 1 : obj.getNumOutputsImpl
               varargout{N} = false;
           end
        end
        
        function varargout   = isOutputFixedSizeImpl(obj)
           for N = 1 : obj.getNumOutputsImpl
               varargout{N} = true;
           end
        end
        
        function st = getSampleTimeImpl(obj)
            st = obj.SampleTime;
        end                
        
        function maskDisplayCmds = getMaskDisplayImpl(obj)          
            encoder_name = ['sprintf(''Encoder: %X'',' obj.Encoder ')'];
            if obj.ShowSpeed
                 names = getOutputNames(obj);
                 output_label = [ ...
                     ['port_label(''output'',1,''', names{1}, ''');',newline], ...
                     ['port_label(''output'',2,''', names{2}, ''');'],...
                     ];
                 maskDisplayCmds = [ ...
                    ['color(''white'');', newline]...                                     % Fix min and max x,y co-ordinates for autoscale mask units
                    ['plot([100,100,100,100],[100,100,100,100]);', newline]...
                    ['plot([0,0,0,0],[0,0,0,0]);', newline]...
                    ['sppkgroot = strrep(motorcarrier.internal.getSpPkgRootDir(),''\'',''/'');',newline]...
                    ['image(fullfile(sppkgroot,''resources'',''encoder.png''),''center'')',newline]...
                    ['color(''blue'');', newline] ...                                     % Drawing mask layout of the block
                    ['text(99, 92, ''ARDUINO'', ''horizontalAlignment'', ''right'');', newline] ...
                    ['color(''black'');', newline] ...
                    ['text(50,15,' encoder_name ',''horizontalAlignment'', ''center'');', newline], ...
                    output_label ,...
                    ];
            else
                 maskDisplayCmds = [ ...
                    ['color(''white'');', newline]...                                     % Fix min and max x,y co-ordinates for autoscale mask units
                    ['plot([100,100,100,100],[100,100,100,100]);', newline]...
                    ['plot([0,0,0,0],[0,0,0,0]);', newline]...
                    ['sppkgroot = strrep(motorcarrier.internal.getSpPkgRootDir(),''\'',''/'');',newline]...
                    ['image(fullfile(sppkgroot,''resources'',''encoder.png''),''center'')',newline]...
                    ['color(''blue'');', newline] ...                                     % Drawing mask layout of the block
                    ['text(99, 92, ''ARDUINO'', ''horizontalAlignment'', ''right'');', newline] ...
                    ['color(''black'');', newline] ...
                    ['text(50,15,' encoder_name ',''horizontalAlignment'', ''center'');', newline], ...
                    ];
            end
        end
             
    end
    
    methods (Static, Access=protected)
        function simMode = getSimulateUsingImpl(~)
            simMode = 'Interpreted execution';
        end
        
        function isVisible = showSimulateUsingImpl
            isVisible = false;
        end
        
        function groups = getPropertyGroupsImpl(~)
            % Define section for properties in System block dialog box.
            EncoderProp = matlab.system.display.internal.Property(...
                'Encoder', 'Description', 'Encoder');           
            SlaveAddressProp = matlab.system.display.internal.Property(...
                'SlaveAddress_', 'IsGraphical', false);
            ShowSpeedProp = matlab.system.display.internal.Property(...
                'ShowSpeed', 'Description', 'Show Speed output port');
            ResetOptionProp = matlab.system.display.internal.Property(...
                'ResetOption', 'Description', 'Reset count at initialization');
            SampleTimeProp = matlab.system.display.internal.Property(...
                'SampleTime', 'Description', 'Sample time');
            
            Group = matlab.system.display.Section(...
                'Title', 'Parameters', 'PropertyList', ...
                {EncoderProp, SlaveAddressProp,...
                ShowSpeedProp, ResetOptionProp,...
                SampleTimeProp,...
                });
            
            groups = Group;
        end
        % Note that this is ignored for the mask-on-mask
        function header = getHeaderImpl
            %getHeaderImpl Create mask header
            %   This only has an effect on the base mask.
            header = matlab.system.display.Header(mfilename('class'), ...
                'Title', 'Encoder', ...
                'Text', sprintf('Measure the rotation of a motor in ticks.\n\nThe block outputs the position and rotational speed of the motor. The position is measured in ticks and the speed is measured in ticks per second of int32 datatype.\n\nEvery increment in the tick count indicates a clockwise rotation and every decrement in the tick count indicates a counterclockwise rotation.'), ...
                'ShowSourceLink', false);
        end
    end
    
    methods (Static)
        function name = getDescriptiveName()
            name = 'MKR Motor Carrier Encoder';
        end
        
        function b = isSupportedContext(context)
            b = context.isCodeGenTarget('rtw');
        end
        
        function updateBuildInfo(buildInfo, context)
            if context.isCodeGenTarget('rtw')
                codertarget.arduinobase.internal.arduinoI2CWrite.updateBuildInfo(buildInfo, context);
            end
        end
    end
end