diff --git a/source/Brick.m b/source/Brick.m index 4e643e65a4b868844f1f6cb52449ef69835e6328..901049505a36ea0c6949604bd759a33ff0450aa4 100644 --- a/source/Brick.m +++ b/source/Brick.m @@ -242,6 +242,12 @@ classdef Brick < handle % send the message through the brickIO write function brick.conn.write(cmd.msg); + % (MMI) When spamming the brick with commands, at some point, it will start + % behaving 'strange'. Sometimes, commands will be executed only with + % a delay, some commands may even be bypassed. + % (Maybe too many commands screw up the brick's internal command queue?..) + % Temporary workaround: Wait 5ms after each sent packet. + pause(0.005); if brick.debug > 0 fprintf('sent (hex): [ '); for ii=1:length(cmd.msg) @@ -1490,10 +1496,18 @@ classdef Brick < handle end % Implemented @ MMI - % WIP function outputReset(brick,layer,nos) - % Not sure what this does yet. - % Has something to do with outputRead + % Brick.outputReset Resets internal tacho count + % + % Brick.outputReset(layer,nos) clears a second tachometer which is used internally + % for, e.g., stopping with a tacholimit. + % + % Notes:: + % - layer is the usb chain layer (usuallly 0). + % - NOS is a bit field representing output 1 to 4 (0x01, 0x02, 0x04, 0x08). + % + % Example:: + % b.outputReset(0,MotorBitfield.MotorA) cmd = Command(); cmd.addHeaderDirectReply(42,0,0); diff --git a/source/EV3.m b/source/EV3.m index 4e8f5e351dae2c784e8dbcbf15ea940e86a95d4e..f263011d5f4a8e5a7b366cb124b88fe91f0d18c7 100644 --- a/source/EV3.m +++ b/source/EV3.m @@ -10,7 +10,7 @@ classdef EV3 < handle % motorA[,B,C,D] - % sensor1[,2,3,4] - % debug - - % batteryMode - Format in which batteryValue should be returned + % batteryMode - Mode for reading battery charge % Dependent % batteryValue - Current battery charge level % get-only @@ -23,7 +23,7 @@ classdef EV3 < handle % connect - Connects EV3-object and its Motors and Sensors to physical brick via bt or usb. % disconnect - Disconnects EV3-object and its Motors and Sensors from physical brick. % update - Updates all Motors and Sensors - % coupleMotors - Updates all Motors and Sensors to current status of their corresponding ports. + % coupleMotors - Creates and connects a SyncMotor-object using two chosen Motor-objects % beep - Plays a 'beep' tone on brick. % playTone - Plays tone on brick. % stopTone - Stops tone currently played. @@ -64,9 +64,14 @@ classdef EV3 < handle properties % Standard properties %% Modi + + %batteryMode - Mode for reading battery charge + % -> 'Percentage' / 'Voltage' + % See also EV3.BATTERYVALUE batteryMode = 'Percentage'; %% Debug + debug; end @@ -79,7 +84,8 @@ classdef EV3 < handle brick = 0; % Brick object from sub-layer class Brick -> used as interface to the % physical brick. - %% Motors & Sensors + %% Motors and Sensors + motorA; motorB; motorC; @@ -148,11 +154,14 @@ classdef EV3 < handle ev3.brick = 0; ev3.isConnected = 0; - error('EV3::connect: Aborted connection.'); + % error('EV3::connect: Aborted connection.'); end end % Interpret arguments + if nargin < 3 + error('EV3::connect: Wrong number of input arguments.'); + end beep = 0; if strcmpi(varargin{1}, 'beep') if strcmpi(varargin{2}, 'on') @@ -265,8 +274,7 @@ classdef EV3 < handle %% System functions function syncMotor = coupleMotors(ev3, varargin) - %coupleMotors Creates a SyncMotor-object for synced use of motor1 and motor2, using parameters - % of motor1. + %coupleMotors Creates and connects a SyncMotor-object using two chosen Motor-objects. % % Notes % * Right now only possible if connection to Brick has been established. @@ -279,11 +287,12 @@ classdef EV3 < handle % % Example % b = EV3(); b.connect('ioType', 'bt', 'serPort', '/dev/rfcomm0'); - % sync = b.coupleMotors('AB'); % Couple motors A and B with parameters of + % sync = b.coupleMotors('AB'); % Couple motors A and B using parameters of % % Motor-object motorA. - % sync = b.coupleMotor('CD', 'useMotorParams', 0, 'power', 50, 'debug', 'on'); - % % Couple motors C and D with default resp. given - % % parameters. + % sync2 = b.coupleMotors('CD', 'useMotorParams', 0, 'power', 50, 'debug', 'on'); + % % Couple motors C and D with new object being + % % initialized with default resp. given parameters. + % if ~ev3.isConnected error('EV3::update: No brick connected.'); @@ -551,6 +560,7 @@ classdef EV3 < handle bat = ev3.getBattery(); end + %% Display %% Display function display(ev3) % WIP @@ -585,4 +595,4 @@ classdef EV3 < handle end end end -end \ No newline at end of file +end diff --git a/source/Motor.m b/source/Motor.m index 4bc300963b6e29af50f4cfc0f3da8ef4fc84f481..f0866b121227fe600173e860d879742d5bdade67 100644 --- a/source/Motor.m +++ b/source/Motor.m @@ -37,7 +37,7 @@ classdef Motor < handle % stop - Stops the motor. :) % waitFor - Stops execution of program as long as motor is running with tacholimit. % isRunning - Returns whether motor is running (WITH TACHOLIMIT) or not. - % %% reset - ?? + % reset - Resets internal tacho count % resetTachoCount - Resets tacho count to 0 (if running without tacholimit). % togglePolarity - Switches the direction in which the motor turns. % setProperties - Sets multiple Motor properties at once using MATLAB's inputParser. @@ -115,8 +115,8 @@ classdef Motor < handle limitMode; %mode - Device mode at port, used as tacho mode (i.e. what tachoCount should return) - % There is also DeviceMode.Motor.Speed, but this is only used internally. - % -> DeviceMode.Motor.Degrees / DeviceMode.Motor.Rotations + % -> DeviceMode.Motor.Degrees / DeviceMode.Motor.Rotations + % (DeviceMode.Motor.Speed is also defined, but this is only used internally.) mode; %debug - Debug turned on or off @@ -548,25 +548,37 @@ classdef Motor < handle end end -% function reset(motor) -% if ~motor.isConnected -% error(['Motor::reset: Motor-Object not connected to brick handle.',... -% 'You have to call motor.connect(brick) first!']); -% elseif ~motor.motorAtPort -% error('Motor::reset: No physical motor connected to Port %s',... -% motor.port); -% end -% -% motor.brick.outputReset(0, motor.port_); -% -% if motor.debug -% fprintf('(DEBUG) Motor::reset: Called outputReset on Port %s\n',... -% motor.port); -% end -% end + function reset(motor) + %reset Resets internal tacho count + % The internal tacho count is used for positioning the motor. For example, when the + % motor is running with a tacho limit, internally it uses another counter than the + % one read by tachoCount. This internal tacho count needs to be reset if you + % physically change the motor's position. + % See also MOTOR.RESETTACHOCOUNT + + if ~motor.isConnected + error(['Motor::reset: Motor-Object not connected to brick handle.',... + 'You have to call motor.connect(brick) first!']); + elseif ~motor.motorAtPort + error('Motor::reset: No physical motor connected to Port %s',... + motor.port); + end + + motor.brick.outputReset(0, motor.port_); + + if motor.debug + fprintf('(DEBUG) Motor::reset: Called outputReset on Port %s\n',... + motor.port); + end + end function resetTachoCount(motor) - %resetTachoCount Resets tacho count to 0 if running without tacholimit. + %resetTachoCount Resets tacho count to 0 if running without tacholimit + % Compared to motor.reset, this resets the 'sensor mode' tacho count, a second + % tacho counter. This counter is used for reading the tacho count with inputRead + % and outputGetCount (via motor.tachoCount). + % See also MOTOR.RESET + if ~motor.isConnected error(['Motor::resetTachoCount: Motor-Object not connected to brick handle.',... 'You have to call motor.connect(brick) first!']); diff --git a/source/Sensor.m b/source/Sensor.m index 427b1b86e11c8703e902cb5ddf9b7dd792f4cd79..f5ad914e43674ac8341a724a3428d3362f375239 100644 --- a/source/Sensor.m +++ b/source/Sensor.m @@ -142,9 +142,10 @@ classdef Sensor < handle sensor.brick = 0; % Note: actual deleting is done in EV3::disconnect. sensor.isConnected = 0; + sensor.sensorAtPort = 0; - status = DeviceMode.Error.Undefined; - type = DeviceMode.Error.Undefined; + sensor.status = DeviceMode.Error.Undefined; + sensor.type = DeviceMode.Error.Undefined; end function update(sensor) diff --git a/source/btBrickIO.m b/source/btBrickIO.m index 5b6c6907c19ef68bbc84880fd98bbc7b41477116..3b9163f2872f39dd2e153594771681ffa0cfb3d5 100644 --- a/source/btBrickIO.m +++ b/source/btBrickIO.m @@ -127,13 +127,6 @@ classdef btBrickIO < BrickIO fprintf('btBrickIO write\n'); end fwrite(brickIO.handle,wmsg); - - % (MMI) When spamming the brick with commands, at some point, it will start - % behaving 'strange'. Sometimes, commands will be executed only with - % a delay, some commands may even be bypassed. - % (Maybe too many commands screw up the brick's internal command queue?..) - % Temporary workaround: Wait 5ms after each sent packet. - pause(0.005); end end end \ No newline at end of file diff --git a/source/hidapi.m b/source/hidapi.m index 7a76372635d29e7fac1682a37a69a382c5b2cf8b..fe1fd000042cd84c608d224ceee575b699e6eaff 100644 --- a/source/hidapi.m +++ b/source/hidapi.m @@ -222,19 +222,12 @@ classdef hidapi < handle % wmsg does not need to be the max packet size. Uncommenting this doesn't affect % anything, and I would prefer sending short messages over long ones. % Further testing may be required, so for now I don't change a thing. - wmsg(end+(hid.nWriteBuffer-length(wmsg))) = 0; + %wmsg(end+(hid.nWriteBuffer-length(wmsg))) = 0; % create a unit8 pointer pbuffer = libpointer('uint8Ptr', uint8(wmsg)); % write the message [res,h] = calllib(hid.slib,'hid_write',hid.handle,wmsg,length(wmsg)); - % (MMI) When spamming the brick with commands, at some point, it will start - % behaving 'strange'. Sometimes, commands will be executed only with - % a delay, some commands may even be bypassed. - % (Maybe too many commands screw up the brick's internal command queue?..) - % Temporary workaround: Wait 5ms after each sent packet. - pause(0.005); - % check the response if res ~= length(wmsg) fprintf('hidapi write error: wrote %d, sent %d\n',(length(wmsg)-1),res); diff --git a/source/str2brake.m b/source/str2brake.m index dd2dc9f0df8590bd84e0c4787b3459b46df8cefe..1a2c621b2632d86d9a37f85ee072eb58706ed357 100644 --- a/source/str2brake.m +++ b/source/str2brake.m @@ -6,9 +6,10 @@ function brake = str2brake(inp) elseif strcmpi(inp, 'Brake') brake = BrakeMode.Brake; else - error('str2brake: Given parameter is not a valid brake mode.'); + error(['str2brake: Given parameter %s is not a valid brake mode. ',... + '(''Brake'' or ''Coast'')'], inp); end else error('str2brake: Given parameter is not a string.'); end -end \ No newline at end of file +end diff --git a/source/usbBrickIO.m b/source/usbBrickIO.m index e2d287f562d4180e94c42173e4e5fd78d5f6eb7b..2c6de0c295a9287a538ce93fc46884ec014f6b85 100644 --- a/source/usbBrickIO.m +++ b/source/usbBrickIO.m @@ -113,10 +113,26 @@ classdef usbBrickIO < BrickIO end % read from the usb handle rmsg = brickIO.handle.read; + + % (MMI) Sometimes, right after connecting via usb, the returned packets are of no + % recognized format. To avoid dealing with those for now, they are simply discarded + % and a new packet is requested. + % This workaround is NOT safe as you can see. It is just temporary and works most + % of the times. + for i=0:5 + if rmsg(5) ~= 2 && rms(5) ~= 4 + rmsg = brickIO.handle.read; + end + pause(0.005); + end + % get the number of read bytes nLength = double(typecast(uint8(rmsg(1:2)),'uint16')); % format the read message (2 byte length plus message) - rmsg = rmsg(1:nLength+2); + if nLength+2 < length(rmsg) % If not, there has been an error -> dealt with in higher layer + rmsg = rmsg(1:nLength+2); + end + end function write(brickIO,wmsg)