LEGO Mindstorms NXT Matlab Functions Overview
This document is a tutorial on how to use the functions that come with the RWTH - Mindstorms NXT Toolbox.
In this section we've got:
To communicate with the NXT via bluetooth, we have to use the SPP (serial port profile), which basically works like a virtual serial port. This is why we can send and receive data from within MATLAB through the serial port commands.
To handle different connections or bluetooth adapters on different computers easily, a certain ini-file with settings for the MATLAB functions must be present in the current directory (or one that can be found through path settings).
The ini-file format looks like this
SerialPort=COM3 BaudRate=57600 DataBits=8
The serial settings should be self explaining. Explanation of the send-pause-values will follow later on. The TimeOut parameter only has an effect when using Windows. It sets the period the bluetooth stack should wait when it is "missing data". The MATLAB-internal default value of 10 causes annoying freezes in certain robot programs on certain computers (a direct cause is not yet found). By setting 2 (the toolbox default value), one should get a fairly stable experience with very rare execution pauses of 2 seconds. Smaller timeout values can lead to real packet loss which has not been examined yet.
To create a bluetooth configuration ini-file, a standard editor can be used. A more comfortable way is to use the GUI-guided program:
The following functions work under Windows as well as Linux, with one big exception: The returned handle will be a serial struct in Windows, but a simple scalar file handle in Linux. All the internal functions take care of this, but if you should want to access fields like .BytesAvailable of the handle, you can only do so in Windows, i.e. you must check the operating system using if ispc to avoid errors in Linux.
Now first have a look how to obtain a handle to a bluetooth connection.
% Before we open a handle, we clean up to avoid errors: BT_CloseAllHandles('bluetooth.ini'); % This only closes all open serial ports matching the COM-port from the % ini-file. More drastical is to close all open COM-ports like this: BT_CloseAllHandles;
Now we can open a connection. Make sure the bluetooth dongle is connected to the NXT brick (using the according software or scripts) before calling this.
h = BT_OpenHandle('bluetooth.ini', 'check');
The optional argument 'check' causes the function so send a keep-alive-packet and to wait for the answer before returning a valid handle. This is very comfortable as it detects a malfunctioning / closed bluetooth connection before the execution of other program code.
Set the global default handle, so that later on, whenever we're calling functions, we don't have to pass the handle every time.
BT_SetDefaultHandle(h); % This is self-explanatory handle = BT_GetDefaultHandle;
To close an open connection / handle, just call
BT_CloseHandle(h); % although this would also do the trick: BT_CloseAllHandles('bluetooth.ini');
In this section we've got:
These functions are very "low level" and you should usually not use them on your own, unless you're implementing new NXT functions. All the already implemented NXT functions make use of these.
First we've got
packet = BT_CreatePacket(CommandType, Command, ReplyMode, ContentBytes);
where ReplyMode either has to be 'reply' or 'dontreply', specifying wether we want an answer from the NXT or not. This command essentially creates the binary data for a packet, taking care of payload size and similar things. For more details see inside the "Bluetooth Engine Demo" file.
Now it's getting interesting. We've got two functions to send and receive data respectively. Because the LEGO NXT brick has a 30ms latency when switching from transmit to receive mode, we can expect a 60ms latency for a whole sensor reading request.
Very important is that the NXT can apparently lose packets / commands, because the input buffer (or queue) is of limited size. As we do not know any more details about this, the send and receive functions have the option to wait between subsequent send operations (i.e. to be less "aggressive"). This is where the earlier mentioned settings from the ini file come in:
In this case we demand a 10ms delay between two consecutive send operations. On the other hand, a 30ms pause is required between each send and receive operation (and vice versa receive and send). This should give the NXT enough time so switch between bluetooth transmission modes without loosing any packets.
Note: The functions are "intelligent" and only pause execution if it is necessary. So if you only try to send a packet once every second, you will not notice this automatic delay, as it is not required.
% for this function, we always have to specify a valid serial port handle BT_SendPacket(packet, handle);
Receiving packets is as easy. Make sure you have requested one before you try to collect something.
[type cmd statusbyte content] = BT_CollectPacket(handle);
The statusbyte will be checked automatically by this function, and if it contains an error message, an according warning will be issued. You can disable the automatic status byte check by calling BT_CollectPacket(handle, 'dontcheck'). There is really just one special situation where this is needed: NXT_LSGetStatus (see documentation and function code).
BT_CollectPacket exactly retrieves one packet from the internal receive buffer. It does so by checking the length of the packet (first two bytes) and then only reads the amount of data that belongs to this specific packet. Be very careful though: If you call it without previously requesting data, there will be nothing to collect, hence the function will return nothing after a timeout or crash, depending on your bluetooth adapter. Even worse, under Linux it will block without the possibility to break until you physically turn off the bluetooth device.
In this section we've got:
All functions beginning with NXT_ are basically just ported from the official LEGO NXT Bluetooth Protocol and Direct Commands documentation.
Specify a name up to 15 chars long (preferrably no spaces) to name your brick. This can be read out by bluetooth adapters (and later on in a MATLAB function as well, NXT_GetDeviceInfo, once it will be implemented). This name will also show up in your bluetooth adapter software when browsing for devices.
To keep the NXT from turning off automatically, send a keep-alive packet from time to time (if needed):
If you're interested in the internal sleep time limit setting, just request it:
[status SleepTimeLimit] = NXT_SendKeepAlive('reply'); % To see after how many minutes the NXT will shut down: minutes = SleepTimeLimit / 1000 / 60;
So how much energy does my bot have left?
voltage = NXT_GetBatteryLevel; % actually, the unit is milli volts, so voltage = voltage / 1000; % :-)
Every function that retrieves (i.e. "gets") values from the NXT is internally split into two parts. But this doesn't have to concern you right now. Note how we called the functions without passing a blutooth handle - we simply set the default handle at the beginning of our program or session.
These are the interesting ones:
- NXT_StartProgram, NXT_StopProgram
- NXT_LSWrite, NXT_LSGetStatus, NXT_LSRead
This section only covers the syntax, for details what the functions do please consider the official LEGO documentation or the function help.
% frequency is in Hz, duration in ms NXT_PlayTone(frequency, duration);
% the common way would be this NXT_SetInputMode(InputPort, SensorTypeDesc, SensorModeDesc, 'dontreply'); % but if you want an acknowledgement (usually not needed), then use status = NXT_SetInputMode(InputPort, SensorTypeDesc, SensorModeDesc, 'reply'); % note: the statusbyte will be automatically checked anyway (and a warning % issued if necessary), but you can still check the status now to handle the % consequences properly...
NXT_ResetInputScaledValue(port); % in this function there is no way to request an acknowledgement...
% only call this after you've set a proper input mode data = NXT_GetInputValues(port); % simple function, heavy output: out.Port % from what port out.Valid % is this sensorreading valid? if not, well... discard? out.Calibrated % for future use of NXT firmware out.TypeByte % sensor type out.TypeName % sensor type, but human readable out.ModeByte % sensor mode out.ModeName % sensor mode, human readable out.RawADVal % raw digital value, do nut use out.NormalizedADVal % use THIS, normalized value, 10bits, between 0 and 1023 out.ScaledVal % use this, depends on the input mode you set out.CalibratedVal % for future use of NXT firmware
% Notation as seen in the Direct Commands doc: % true = relative = BlockTachoCount, false = absolute = RotationCount NXT_ResetMotorPosition(port, true);
% more lines for better readability NXT_SetOutputState(whatmotor, ... % port 20, ... % power true, ... % motoron? true, ... % brake? 'SPEED', ... % regulation 0, ... % turnratio 'RUNNING', ... % runstate 0, ... % tacho limit (0 = forever) 'dontreply'); % replymode
out = NXT_GetOutputState(port); % just like with GetInputValues: simple call, complex output: out.Port % motornumber out.Power % power out.Mode % complete mode-byte (bitfield), see below for easier usage out.ModeIsMOTORON % boolean, state of MOTORON bit (false means motor has no power) out.ModeIsBRAKE % boolean, state of electronic braking (improves motor performance) out.ModeIsREGULATED % boolean, if set, see RegModeName, if not set, reg mode will be IDLE out.RegModeByte % regulation mode, binary out.RegModeName % name of regulation mode: IDLE, SPEED, or SYNC out.TurnRatio % turn ratio, 0 = straight forward out.RunStateByte % run state, binary out.RunStateName % name of run state: IDLE, RUNNING, RAMPUP or RAMPDOWN out.TachoLimit % current tacho limit (we'll call it AngleLimit later on) out.TachoCount % TachoCount = internal cumulative motor-degree-counter. out.BlockTachoCount % motor-degree-counter, resettable using "ResetMotorPosition relative" out.RotationCount % motor-degree-counter, resettable using "ResetMotorPosition absolute"
To execute "real" Mindstorms programs on the NXT (i.e. programs that you created using the official LEGO software and stored it locally on the NXT), you can call this function:
NXT_StartProgram('MyDemo.rxe'); % the file extension '.rxe' can be omitted, it will then be automatically added
Stopping the currently running program can be accomplished with
There are three more NXT direct commands: NXT_LSGetStatus, NXT_LSWrite, NXT_LSRead. They all have one purpose: Address digital sensors that use the I²C-Protocol. An example is the ultrasonic sensor, and for more documentation you might want to see the sourcecode of OpenUltrasonic and GetUltrasonic.
The idea is to send data (containing I²C payload) first with NXT_LSWrite. Then check the sensor status in a loop using NXT_LSGetStatus until it is ready, i.e. until the status byte reports no error and all requested bytes are available. Those bytes can then be received using NXT_LSRead.
In this section we've got:
The functions mentioned above provide an easy and simple way to access all sensors. The ultrasonic sensor uses a digital interface and has to be handled in a different way internally, but using these high level functions, you won't see a difference. The only thing worth mentioning: GetUltrasonic is about 1.5 up to 2 times slower than the other Get* functions (because internally 3 or sometimes 4 packets are needed instead of just 2).
The Open* functions use NXT_SetInputMode, while Get* calls NXT_GetInputValues. CloseSensor is necessary to turn off a specific sensor, e.g. turn off the light sensor's red LED in active mode. This will save power.
You can use raw port numbers starting with 0 just as seen in the official Mindstorms documentation, or you can use the named constants SENSOR_1 to SENSOR_4 for better readability. So let's open a few sensors:
OpenSwitch(SENSOR_1); OpenSound(SENSOR_2, 'DB'); % have to specify mode, DB or DBA OpenLight(SENSOR_3, 'ACTIVE'); % have to specify mode, ACTIVE or INACTIVE OpenUltrasonic(SENSOR_4);
Sensors are ready to be used now, very easy:
if GetSwitch(SENSOR_1) % always specify port number! % the touch sensor is "pressed" now, do something end%if if GetSound(SENSOR_2) < 100 % remember, values range from 0 to 1023 % quite silent right now end%if if GetLight(SENSOR_3) > 1000 % VERY bright sunshine :-) end%if if GetUltrasonic(SENSOR_4) < 30 % unit is cm % we seem close to a wall end%if
Note that it is possible to use NXT_SetInputMode with a custom mode you like instead of Open*, and the Get-functions will still work (this is not true for the ultrasonic sensor, but it has totally different modes anyway). Internally they just return the .NormalizedADVal value. This makes it possible to automatically count claps and still use the simple functions. Example:
% your old code looks like this OpenSound(SENSOR_2, 'DB'); % do something while(something) % note how you continously have to poll the sensor if GetSound(SENSOR_2) > 700 ClapCount = ClapCount + 1; end%if end%while
% now replace OpenSound by this NXT_SetInputMode(SENSOR_2, 'SOUND_DB', 'PERIODCOUNTERMODE', 'dontreply'); NXT_ResetInputScaledValue(SENSOR_2); % this is needed if you want to start with 0 if GetSound(SENSOR_2) > 500 % GetSound still works! % hey, this is a loud atmosphere... end%if % we could do whatever we wanted here: pause(10) % take a little 10s nap data = NXT_GetInputValues(SENSOR_2); ClapCount = data.ScaledVal;
That was easy. The NXT did the counting for us. For more details about sensor modes see the LEGO documentation, but in a few words: A "transition" (TRANSITIONCNTMODE) is whenever the value (.NormalizedADVal) changes between the 45% threshold (45% of 1023 is 460). As "period" (PERIODCOUNTERMODE) counts when the value goes down from somewhere above 45%, and then changes back up. The "count" happens during the raising part. To see what exactly is happening try the GUI_WatchAnalogSensor tool.
The main point I wanted to make: As you can see, GetSound / GetLight etc. can peacefully coexist with the NXT_ functions.
Clean up when you are done!
% don't forget :-) CloseSensor(SENSOR_1); CloseSensor(SENSOR_2); CloseSensor(SENSOR_3); CloseSensor(SENSOR_4);
In this section we've got:
These functions provide a very high level and simple way to access almost all motor features. The idea behind this is as follows: First you specify the motor number (port) you want to work with. All successive commands then affect this current motor. Once you are done setting everything you need, you submit these changes and issue a send command.
Let's just walk through this
SetMotor(0); % first motor is active now
This is a great opportunity to show that all of these functions accept also strings as input for numbers, i.e.:
What's the point of this? Well, we now can use this fancy syntax:
Another option is to use symbolic constants for port numbers, that map to easy understandable port labels just as found on the NXT:
SetMotor(MOTOR_B); % identical to SetMotor(1);
In the end it's your choice which way you use to address the ports, however we recommend the usage of constants MOTOR_A, MOTOR_B and MOTOR_C.
GetMotor just returns the motor you previously set. It can be useful when mixing NXT_ functions inbetween (they need a motor port as input):
NXT_ResetMotorPosition(GetMotor, true); % good style, works with current motor
Now the active motor is set, and we can specify all the details we want. When we're done (i.e. when the motor should finally start spinning), we send.
% it's nice to arrange the commands like this SetMotor 0 SetPower 50 AngleLimit 360 SendMotorSettings
Voila, motor 0 should have made a full 360° turn by now...
To let the motor run forever (or until you change your mind and tell it something different), use an angle limit of 0:
SetMotor 0 SetPower 50 AngleLimit 0 % run till the end of time (or battery, for that matter) SendMotorSettings
If we want the motor to rotate at a constant speed as accurate as possible, we have to enable speed regulation. Like all the other commands, this affects the currently set motor only and the settings will only be applied with the SendMotorSettings command.
One noteworthy effect of the internal speed regulation is, that the motor will increase the power if the desired rotational speed cannot be met. Example: Consider you set a power of 20 without speed regulation, but your bot is so heavy that it does not move (although you can still hear the motors are trying to). If you enable speed regulation, the motor will internally increase its power until the wheels are moving, just like they would normally without a force acting against them. However, using speed regulation with a power of 100 does NOT give you more power. 100 percent is all that you can get.
Note: SpeedRegulation seems to somehow deteriorate the motor's precision when targeting small distances (small values for SetAngleLimit), so use with care.
For driving robots, the regulation mode "synchronization" is very interesting. It synchronizes two motors and they then act as if they were connected through an axle, so that the robot can drive straight forward. This is implemented using
SetMotor 1 SyncToMotor 2 SetPower 50 SendMotorSettings
In the example above our bot will start driving forward (assuming motor 1 and 2 are the ones with wheels). From the point on where you call SyncToMotor, all settings affect both synced motors (if one of them is set active of course). Even SendMotorSettings will internally send two packets to each of the motors, so that you can use them as if they were really connected.
Only with synced motors it is possible to drive curves or turn around:
SetMotor 1 SyncToMotor 2 SetPower 50 SetTurnRatio 100 SetAngleLimit 200 SendMotorSettings
The turn ratio command shifts power between synced motors. 100 means one motor is spinning forward and the other backwards, resulting in the maximal rotational effect possible. 50 means one motor is running and the other is stopped, and with values bewteen 1 and 49 you can get nice curves (both wheels spinning, but not at equal speed). Needless to say, 0 results in a straight forward direction. You can use negative values for opposite directions (i.e. left and right turning, but that depends on the robot model).
Ok, so now we want to turn off synchronisation
Note that a motor can only be synchronized to another motor or speed regulated at a time! We have to manually turn off synchronization, before enabling speed regulation again, and vice versa!
SyncToMotor off SpeedRegulation on
Note that the function StopMotor also resets motor regulation and synchronization. This is by design, see documentation.
We've got one special setting left:
SetPower 100 SetAngleLimit 1080 SetRampMode up
This uses the motor's runstate RAMPUP, which basically accelerates smoothly from the old power to the new power. It's only valid when you specify an angle limit. This is the rotational distance during which the motor will adjust the power to the new value.
To decelerate ("brake" smoothly) use
SetPower 0 SetAngleLimit 1080 SetRampMode down
or turn it off again (runstate RUNNING, "normal" movement), which is also the default setting:
Once we've seen all options for the SendMotorSettings, it's worth to know that you can also access all these options with one single line.
SendMotorSettings(MOTOR_A, 50, 360, 'off', MOTOR_B, 25, 'up')
This results in MOTOR_A being synced to MOTOR_B, both running with power 50, angle-limit 360 degrees, speed-regulation turned 'off', ramp-mode is 'up', and a turn-ratio of 25. Again it's your choice which way you like better, but it is clearly recommended to use the long version, whose syntax is better understandable.
Ok fine. Now we've got a very handy command here:
This will turn off power to the current motor, enabling the so called COAST mode, in which you can rotate the motor freely as you like. Of course I could've also written StopMotor(0, 'off'), but I wanted to demonstrate a possible use of GetMotor again (avoid too much hardcoding of motor numbers, or of any values at all if possible).
The other option is
This will actively stop and hold the motor at its current position. Try moving it, it is harder than you think ;-). Works like an emergency brake for driving robots. It consumes quite a lot of power, so you shouldn't leave your bot in this setting for too much time.
And finally we've got this handy version:
StopMotor all off % note the syntax, short for StopMotor('all', 'off')
The parameter all is special, not just because it is turning off (or braking) all motors, but because it does so at once. Internally only one packet is sent for all three motors, so you only have to expect one third of the lag (compared to sending three packets). Also, you can turn off the motors almost synchronously, compared to one by one with the usual sending delay. It's a nice command that can very often be found at the start or end of programs to ensure all motors are turned off and don't take any power...
So now we can control the motors, but how do we poll their rotation sensor? The answer is:
out = GetMotorSettings(MOTOR_C); % so lets look into the results: out.IsRunning % boolean, true if the motor "does something" out.Power % current power out.AngleLimit % current set angle limit, 0 means none set out.TurnRatio % current turn ratio out.SpeedRegulation % boolean, speed regulated or not? out.SyncToMotor % the motor this one is synced to. -1 means not synced out.TachoCount % internal, non-resettable rotation-counter (in degrees) out.Angle % current motor position, resettable using % ResetMotorAngle(port); out.MotorBrake % boolean, is electronic braking enabled? % (this has nothing to do with braking in a common % sense, just ignore it, should be turned on by % default anyway as it improves motor performance)
This should give us all information about the motor we need. Internally a NXT_GetOutputState is used of course. Note that the .Angle value is actually the NXT internal BlockTachoCount, which you can reset using ResetMotorAngle() or NXT_ResetMotorPosition(GetMotor, true) (i.e. what is called relative motor position in the official Mindstorms documentation).
The .TachoCount on the other hand is much like your car's mileage counter. It gives the total amount of degrees the motor has rotated since the NXT was turned on, and it is not resettable (it will however be resetted, when a new external program is started, which you can enforce using NXT_StartProgram). You can also set it back to zero if you turn the motor back exactly the amount it was turned forward :-). Restarting the NXT brick is a more comfortable way...
We have got yet one more very handy function for you. Suppose you've just set your motor to run a certain distance, i.e. using
SetMotor 0 SetPower 20 SetAngleLimit 360 SendMotorSettigns
Now power 20 is not very fast, so it will take some time for the motor until it has reached its angle limit. But how do you know when it's done? You could create a loop and constantly call GetMotorSettings to check wether .IsRunning is set or not. And this is exactly what WaitForMotor does.
SetMotor 0 SetPower 20 SetAngleLimit 360 SendMotorSettigns WaitForMotor(GetMotor) % you've seen me using GetMotor before... % if this WaitForMotor was not here, we would send the % PlaySound command DIRECTLY after starting the motor! % Try it for yourself. Basically our Matlab is "blocked" now and holds % execution, until the motor is done... NXT_PlaySound(440, 200)
This will play a short beep on the NXT immediately after the motor has reached its angle limit. Of course that does not mean that the motor has stopped already: It's currently in coast mode and will keep turning a short while. That is why, the following commands sequence is often used to try to stop at a certain position:
% ... SendMotorSettigns WaitForMotor(GetMotor) StopMotor(GetMotor, 'brake') % actively hold still pause(1) % do so for a short while % active braking has a high power consumption, so: StopMotor(GetMotor, 'off') % release motor
WaitForMotor has one more parameter that you can use. Imagine what happens with this code snippet:
SetMotor 0 SetPower 20 SetAngleLimit 0 % 0 means no angle limit = run forever SendMotorSettigns WaitForMotor(GetMotor)
See it? You've created an endless loop. Matlab will block till the end of time (or battery in this case), as the motor will not stop. Why should it, it has no angle limit set.
Something else can happen: You can set an angle limit, let's say a certain distance for a driving robot. But there is a wall, the bot can't go any further, and again: Endless loop, because the motor will not reach its angle limit.
The solution for this is a built-in timeout. Try:
or use this syntax if you like it better:
WaitForMotor 0 10
This time the function will only block for a maximum of 10 seconds. If the motor is done earlier, fine. Then the function will exit of course. But if it got stuck or is in an endless loop, after the timeout period (you can use fractions by the way, like 5.7) WaitForMotor will continue execution. The price for avoiding this endless loop / Matlab block: When specifying a timeout, you cannot be sure that the motor really has stopped, or wether it timed out. So take care of the consequences on your own (e.g. by reading .Angle to see wether the specified angle limit was met, or by checking .IsRunning to see if the motor is still blocked)...
The motor ports can also be used for other actuators besides the NXT motors. Lamps can be connected, too. The following function can be used to turn the lamp on and a short while later off.
SwitchLamp(MOTOR_C, 'on'); pause(1) SwitchLamp(MOTOR_C, 'off');
It is also possible to use 'all' as port-number, just like you've seen for StopMotor:
SwitchLamp all off
There is no secret behind SwitchLamp - it just sets power 100 for the specific output port. You could have used SendMotorSettings as well, but SwitchLamp is easier in this case and better to understand.
Actually there is not much to see in here, just mentioning:
You certainly know the very nice and handy Matlab functions tic and toc. They have one big disadvantage though: If you use them deep down in your functions, and then in some toplevel functions again that call those lower level functions, well: You start messing with tic and toc, and won't get useable results.
tic % do something % something else in here tic sometime = toc; % later on.... TotalElapsedTime = toc; % This DOESN'T work as intended, as you used tic again inbetween the % outside aligned functions, resetting the start of measurement (which was % certainly unwanted)
tictic(1); % do something % something else in here tictic(2) sometime = toctoc(2); % later on.... TotalElapsedTime = toctoc(1);
As you can see quickly, tictic and toctoc just take an index (or ID if you want to call it like that) as input, allowing several time-counters next to each other at one time. So we eliminated one problem, but now we have to keep track of the tictic-IDs we use. If I use tictic(3) in my function that calls your function, but your function uses ID 3 as well, we've got the same problem as before. So be careful. Probably best to use numbers above 100 in lowlevel functions, and stay away from this range in higher levels...
Very quickly, just to mention: We've got two functions that can help you converting numbers into the correct binary byte ordering (considering the little-endian format: LSB first, that the NXT uses). If you want more information, look it up in the documentation...
x = dec2wordbytes(-1, 1, 'signed'); % x is now a signed byte, 0xFF = 255 y = wordbytes2dec(bytearray, 4); % default is unsigned % y is now a 32bit unsigned integer
And finally an easy way to read data from ini files:
% [Bluetooth] Key= Filename ComPort = readFromIniFile(inisection, 'SerialPort', 'bluetooth.ini');
An important function gets its own chapter:
There are several ways in Matlab to display text in the command window, like disp or fprintf. However, we use our own creation textOut, mainly to have a general wrapper that we can modify.
Advantages: textOut supports writing to a logfile if desired and conditional output (basically turns it off for a while).
Very easy to use, the function takes a string as input (that is probably best to create with sprintf):
x = 'world'; y = 2007; textOut(sprintf('Hello %s, it is the year %d!\n', x, y)); % Results in: >> Hello world, it is the year 2007!
Note the '\n' at the end to finish the line. The use of sprintf might seem uncomfortable, but it is necessary.
Now the more advanced features:
global EnableLogging global Logfilename EnableLogging = true; Logfilename = 'logfile.txt'; textOut(sprintf('Whatever I say here will be logged to the file as well.\n'));
Two additional paramers now:
textOut(sprintf('Only appears in the command window\n'), 'screenonly'); textOut(sprintf('Only appears in the logfile, if logging enabled\n'), 'logonly');
And now the option you've all been waiting for: How do I shut it up? :-)
global DisableScreenOut DisableScreenOut = true; textOut(sprintf(['If logging is enabled, this goes to the logfile,', ... 'if not, this goes nowhere\n']));
And what do we see now? Right:
If you mess with this global variable, it is nice to get its state before and set it back afterwards, to improve compatibility with other functions:
global DisableScreenOut oldstate = DisableScreenOut; DisableScreenOut = true; % do your silent stuff in here DisableScreenOut = oldstate;
In this section there is just a list of global variables that are being used by our functions. PLEASE DO NOT EDIT THEM! If available, use appropriate Get and Set functions.
As seen above, in use by textOut, modifying is allowed:
global DisableScreenOut global EnableLogging global Logfilename
Used by tictic and toctoc, do not access or edit!
global ticticStart; % array of vectors / "clocks", whatever
Bluetooth internals. Do NOT access directly!
global BT_DefaultHandle % has its own Get and Set functions global BT_SendSendPause % read from ini file global BT_SendReceivePause % read from ini file global BT_LastSendTime % used by BT_Send and BT_Collect global BT_LastReceiveTime % used by BT_Send and BT_Collect
NXT / high level motor control internals. Do NOT access directly:
global NXTMOTOR_CurrentMotor % used by Get and SetMotor global NXTMOTOR_State % array of structs, used by almost everything global NXTMOTOR_LeftWheel % used later on for robot control in high level global NXTMOTOR_RightWheel % functions like TurnRobot...
These functions remain in the private subfolder of the modules work directory. M-files in this folder are only visible from the upper directory abd should only be called internally. The following functions are private because they are not supposed to be used, unless you are developing new NXT functions.
- initializeGlobalMotorStateVar initializes the NXTMOTOR_State struct, only for the first time. Set default values here (like the BRAKE bit)
- resetMotorRegulation is a little helper that sets a few values inside the NXTMOTOR_State struct sometimes when synchronisation mode is changed. Improves code readability...
Thank you for reading so far. Feel free to contact me here:
atorf (at) lfb.rwth-aachen.de
Linus Atorf, 23.11.2007 (Version 1.4, last change before toolbox release)