Title: 2. Textual user interface NQC (Not quite C)
12. Textual user interface NQC (Not quite C)
- C-like programs translated into CRX-bytecode
- Composed of
- Global variables
- Task blocks
- Inline functions
- subroutines
2NQC Programming
- Youll be programming your robot in NQC (Not
Quite C). - Youll use the BricxCC (Bricx Control Centre) as
your development environment. - When you first fire up BricxCC (by double
clicking on the BricxCC icon) it looks for the
RCX brick. - It will find it, because you will have switched
it on (using the red On-Off button) and placed it
with its infra-red windows facing the IR tower
and a few centimetres away from it.
3 1
2
Click on RCX2, then OK
4Youll get this. You should also get another
window
5If you dont, press F9 once or twice until you do
6 File, New gets you a programming window
7 Copy and paste the text file trusty from your
email
8And save it locally as trusty (a .nqc file)
91
2
Click on Compile to compile, and on Download to
put it into the RCX.
10If your program wont compile
- You will get helpful error messages below the
program - If you cant sort out the errors by yourself,
call Renzo, the GTA
11Tasks
- task name( )
-
- // the task 's code is placed here
-
- name any legal identifier.
- 1 task - named "main" - started when program is
run. - Maximum number of tasks on RCX 10
- The body of a task consists of a list of
statements. - Tasks started and stopped start and stop
statements - StopAllTasks stops all currently running tasks.
12NQC/RCX basics Motors
- Motor connections A, B, and C are known as OUT_A,
OUT_B, and OUT_C - You set the direction of a motor by
- OnFwd (OUT_A) or OnRev(OUT_B)
- You set the power of a motor by
- SetPower (OUT_A, x) where x runs from 0 to 7
- You turn a motor off by
- Off(OUT_B)
13In robotC
- pragma config(Motor, motorA,
RightMotor, tmotorNormal, PIDControl, ) - pragma config(Motor, motorB,
LeftMotor, tmotorNormal, PIDControl, ) - //!!Code automatically generated by 'ROBOTC'
configuration wizard !!// - void rightTurn(int turnTime)
-
- motorRightMotor -100
- motorLeftMotor 100
- wait10Msec(turnTime)
-
- void leftTurn(int turnTime)
-
- motorRightMotor 100
- motorLeftMotor -100
- wait10Msec(turnTime)
-
sub turn_around() OnRev(OUT_C) Wait(400)
OnFwd(OUT_AOUT_C)
This in NQC
14In robotC
- pragma config(Motor, motorA,
RightMotor, tmotorNormal, PIDControl, ) - pragma config(Motor, motorB,
LeftMotor, tmotorNormal, PIDControl, ) - //!!Code automatically generated by 'ROBOTC'
configuration wizard !!// - void rightTurn(int turnTime)
-
- motorRightMotor -100
- motorLeftMotor 100
- wait10Msec(turnTime)
-
- void leftTurn(int turnTime)
-
- motorRightMotor 100
- motorLeftMotor -100
- wait10Msec(turnTime)
-
15NQC/RCX basics Subroutines
- There are several ways of avoiding having to
write out long strings of repetitive chunks of
code. - One is to use subroutines.
- The format of a subroutine is
- sub subroutinename ( ) code goes here
- And you call it in the main body of your code by
- subroutinename ( )
- (Semicolons are used as separators for
expressions etc.)
16Subroutines
- sub turn_around()
- OnRev(OUT_C) Wait(400)
- OnFwd(OUT_AOUT_C)
-
- task main()
- OnFwd(OUT_AOUT_C)
- Wait(100)
- turn_around()
- Wait(200)
- turn_around()
- Wait(100)
- turn_around()
- Off(OUT_AOUT_C)c
17Subroutines
- Subroutines allow a single copy of some code to
be shared between several different callers
(space efficient). - Restrictions
- First of all, subroutines cannot use any
arguments. - A subroutine cannot call another subroutine.
- Maximum number of subroutines 8 for the RCX
- If calling from multiple tasks no local
variables or perform calculations that require
temporary variables (this restriction is lifted
for the Scout and RCX2).
18NQC/RCX basics Control structures
- while (true) stuff
- will execute stuff forever.
- if (condition) do_something_simple
- will do_something_simple if the condition is
true - if (condition) do_something_simple
- else do_something_else
- will do_something_else if the condition is not
true
19Control structures
- If-statementsif (condition) consequenceif
(condition) consequence else alternative - While-statementswhile (condition) body
- Repeat-statements repeat (expression) body
- Switch-statementswitch (expression) body
- Until-macro define until (c) while (! (c ))
20Inline function, call by reference
- void turn_around(int turntime)
- OnRev(OUT_C) Wait(turntime)
- OnFwd(OUT_AOUT_C)
- task main()
- OnFwd(OUT_AOUT_C)
- Wait(100)
- turn_around(200)
- Wait(200)
- turn_around(50)
- Wait(100)
- turn_around(300)
- Off(OUT_AOUT_C)
task main() int count0 while (countlt5)
PlaySound(SOUND_CLICK)
Wait(count20) increment(count)
void increment(int n) n
21(Inline) Functions
- void name( argument_list )
- // body of the function
- Functions cannot return a value void is related
to C - Argument list empty, or 1 argument
definitions. - Arguments type followed by its name.
- All values are 16 bit signed integers.
- 4 different argument classes
Type Meaning Restriction
int Pass by value None
int Pass by reference Only variables may be used
const int Pass by value Only constant may be used
const int Pass by reference Function cannot modify argument
22Playing preprogrammed sounds tones
- task music()
- while (true)
- PlayTone(262,40) Wait(50)
- PlayTone(294,40) Wait(50)
- PlayTone(330,40) Wait(50)
- PlayTone(294,40) Wait(50)
-
- task main()
- start music
- while(true)
- OnFwd(OUT_AOUT_C) Wait(300)
- OnRev(OUT_AOUT_C) Wait(300)
-
task main() PlaySound(0) Wait(100)
PlaySound(1) Wait(100) PlaySound(2)
Wait(100) PlaySound(3) Wait(100)
PlaySound(4) Wait(100) PlaySound(5)
Wait(100)
23Variables
- All variables of the same type 16 bit signed
integers. - Declarations int variableinitial value ,
variable initial value - Examples
- int x // declare x
- int y, z // declare y and z
- int a 1, b // declare a and b, initialize a
to 1 - Global variables declared at the program
scopeUsed within tasks, functions, subroutines.
Max 32 - Local variables within tasks, functions, and
sometimes within subroutines. Max 0 _at_ RCX, 16
_at_RCX2 - Local variables may be declared in a compound
statement, following a
24NQC/RCX basics Variables
All variables are integers. You have to declare
them, otherwise the compiler will moan. int
thing at the beginning of your program will let
you use the integer variable thing anywhere. If
you declare it within some curly brackets (as
part of an expression or subroutine etc.) it
wont work if you try to use it outside the
brackets (and the compiler will complain).
25NQC/RCX basics Constants
You can give constants meaningful names instead
of numbers by defining them at the start of your
program define MONKEY_SCORE 25 means you can
write MONKEY_SCORE in your code instead of just
25, and so you will be able to distinguish it
from all the other constants that might be 25
for example, SLAMMER_RECORD
26Arrays
- Arrays exist only for RCX2
27Assignments
- SyntaxVariable operator expression
- Operators
- Set variable to expression
- Add expression to variable
- - Subtract expression from variable
- Multiple variable by expression
- / Divide variable by expression
- Bitwise AND expression into variable
- Bitwise OR expression into variable
- Set variable to absolute value of expression
- - Set variable to sign (-1,1,0) of expression
28Built-in API
- SetPower(outputs, power)
Function - Sets the power level of the specified outputs.
- Power should result in a value between 0 and 7.
- OUT_LOW, OUT_HALF, OUT_FULL may also be
used.Examples - SetPower( OUT_A, OUT _FULL) // A full power
- SetPower( OUT_B, x )
- OnFwd(outputs)
Function - Set outputs to forward direction and turn them
on. - Outputs is one or more of OUT_A, OUT_B, and OUT_C
added together. - Example OnFwd (OUT_A )
29 30Sensor Types
NXT brick
Old RCX
31Sensor Modes
32Sensor Type/Mode Combinations
33Setting Sensor Type and Mode
- SetSensor(sensor, configuration)
- Set the type and mode to the specified
configuration(constant containing both type and
mode info). - Example
- SetSensor (SENSOR_1, SENSOR_TOUCH)
- SetSensorType(sensor, type)
- Set type (one of the predefined sensor type
constants). - Example SetSensorType(SENSOR_1, SENSOR_TYPE
_TOUCH ) - SetSensorMode(sensor, mode)
- Set mode (one of the predefined sensor mode
constants)Optional slope parameter for Boolean
conversion.
34Reading out sensors, Wait
- SensorValue(n)
- Returns the processed sensor reading for sensor
n, where n is 0, 1, or 2. This is the same value
that is returned by the sensor names - (e.g. SENSOR_1).
- Example x SensorValue(0) // readsensor_1
- Wait(time)
- Make a task sleep for specified amount of time
(in 1/100 s). Argument may be an expression or a
constant. - Wait(100) // wait 1 second
- Wait(Random (100)) // wait random time up to 1
second
For more information refer to the NQC programmers
manual
35Example of motor control in NQC
- // speed.nqc -- sets motor power, goes forward,
waits, - // goes backwards
- task main( )
-
- SetPower(OUT_AOUT_C,2)
- OnFwd(OUT_AOUT_C)
- Wait(400)
- OnRev(OUT_AOUT_C)
- Wait(400)
- Off(OUT_AOUT_C)
- sets motor power,
- goes forward, waits,
- goes backwards
36Robots moves in a Spiral
- // spiral.nqc -- Uses repeat variables to make
robot// move in a spiral - define TURN_TIME 100
- int move_time // define a variable
- task main()
-
- move_time 20 // set the initial
value - repeat(50)
-
- OnFwd(OUT_AOUT_C)
- Wait(move_time) // use the variable
for sleeping - OnRev(OUT_C)
- Wait(TURN_TIME)
- move_time 5 // increase the
variable -
- Off(OUT_AOUT_C)
37Use of touch sensors
Declare that SENSOR_1 is touch sensor
- // Use of touch sensors
- task main()
- SetSensor(SENSOR_1,SENSOR_TOUCH)
- OnFwd(OUT_AOUT_C)
- while (true)
- if (SENSOR_1 1)
- OnRev(OUT_AOUT_C) Wait(30)
- OnFwd(OUT_A) Wait(30)
- OnFwd(OUT_AOUT_C)
-
-
Go forward with speed OUT_A OUT_C
Go backward with speed OUT_A OUT_C
38Use of light sensor
- // Use of a light sensor to make robot go forward
until - // it "sees" black, then turn until it's over
white - define THRESHOLD 37
- task main()
- SetSensor(SENSOR_2,SENSOR_LIGHT)
- OnFwd(OUT_AOUT_C)
- while (true)
- if (SENSOR_2 lt THRESHOLD)
- OnRev(OUT_C)
- Wait(10)
- until (SENSOR_2 gt THRESHOLD)
- OnFwd(OUT_AOUT_C)
-
39NQC/RCX basics Sensors
- Sensor connections 1, 2, and 3 are known as
SENSOR_1, SENSOR_2, and SENSOR_3 - You have to tell each sensor connection what sort
of sensor is plugged into it. - For the light sensor, its just a matter of
- SetSensor (SENSOR_2, SENSOR_LIGHT)
40NQC/RCX basics Tasks
- NQC can run several tasks at the same time.
(Unfortunately you have to be careful to ensure
that tasks do not conflict, especially over
resources.) - The format of a task is
- task taskname( ) task instructions etc go here
- Every program must contain a task called main
- task ( ) main stuff
41Tasking
- task main()
- SetSensor(SENSOR_1,SENSOR_TOUCH)
- start check_sensors
- start move_square
- task move_square()
- while (true)
- OnFwd(OUT_AOUT_C) Wait(100)
- OnRev(OUT_C) Wait(85)
- task check_sensors()
- while (true)
- if (SENSOR_1 1)
- stop move_square
- OnRev(OUT_AOUT_C) Wait(50)
- OnFwd(OUT_A) Wait(85)
- start move_square
Starts two tasks described below
42Macros
define turn_right(s,t) SetPower(OUT_AOUT_C,s)O
nFwd(OUT_A)OnRev(OUT_C)Wait(t) define
turn_left(s,t) SetPower(OUT_AOUT_C,s)OnRev(OUT
_A)OnFwd(OUT_C)Wait(t) define forwards(s,t)
SetPower(OUT_AOUT_C,s)OnFwd(OUT_AOUT_C)Wait(t
) define backwards(s,t) SetPower(OUT_AOUT_C,s
)OnRev(OUT_AOUT_C)Wait(t) task main()
forwards(1,200) turn_left(7,85)
forwards(4,100) backwards(1,200)
forwards(7,100) turn_right(4,85)
forwards(1,200) Off(OUT_AOUT_C)
43EXAMPLE The trusty.nqc program
Its straight from the Knudsen book. Well skip
through some basics, and then go through the
program.
44trusty.nqc
int state define BOTH_ON 3 define LEFT_ON
1 define RIGHT_ON 2 define BOTH_OFF 0 define
INDETERMINATE 255 define DARK2 35 define
LIGHT2 40 define DARK3 40 define LIGHT3
45 define POWER 4
45trusty.nqc
int state THIS IS THE DECLARATION OF THE
VARIABLE WE WILL USE TO REPRESENT ALL THE
DIFFERENT MEANINGFUL COMBINATIONS OF SENSOR STATES
46trusty.nqc
define BOTH_ON 3 define LEFT_ON 1 define
RIGHT_ON 2 define BOTH_OFF 0 define
INDETERMINATE 255 THESE ARE THE VALUES THE
VARIABLE state CAN TAKE. BOTH_ON MEANS BOTH
SENSORS ON THE TRACK, ETC. INDETERMINATE MEANS AT
LEAST ONE SENSOR IS ON THE BORDERLINE
47trusty.nqc
define DARK2 35 define LIGHT2 40 define DARK3
40 define LIGHT3 45 THESE ARE THE SENSOR INPUT
VALUES FOR DECIDING WHETHER A SENSOR IS ON OR OFF
THE LINE, OR ON THE BORDERLINE
48Sensor tip
- If the sensor port is correctly configured, you
can read the value of a sensor directly from the
LCD display on the RCX. - Press VIEW.
- You will see a little pointing to input 1.
- The number on the LCD will be the current input
of the sensor connected to input 1. - Press VIEW again.
- The will move round one place to input 2.
- Keep on pressing and it will go 3, A, B, C, and
then out of VIEW mode.
49trusty.nqc
define POWER 4 THIS SETS THE POWER LEVEL THAT
WILL BE USED FOR MOTORS THAT ARE ON.
50trusty.nqc
task main() initialize() while
(true) if (state BOTH_ON)
OnFwd(OUT_A OUT_C) else if
(state LEFT_ON) Off(OUT_A)
OnFwd(OUT_C)
else if (state RIGHT_ON)
Off(OUT_C) OnFwd(OUT_A)
51trusty.nqc
task main() initialize() while
(true) CODE HERE THIS
STARTS THE MAIN TASK, INITIALIZES EVERYTHING
USING THE SUBROUTINE INITIALIZE, AND EXECUTES THE
CODE IN THE MIDDLE
52trusty.nqc
if (state BOTH_ON) OnFwd(OUT_A
OUT_C) else if (state LEFT_ON)
Off(OUT_A)
OnFwd(OUT_C) else if
(state RIGHT_ON)
Off(OUT_C) OnFwd(OUT_A) THIS
GOES FORWARD FOR BOTH_ON, TURNS LEFT FOR LEFT_ON,
AND TURNS RIGHT FOR RIGHT_ON
53trusty.nqc
sub initialize() SetSensor (SENSOR_2,
SENSOR_LIGHT) SetSensor (SENSOR_3,
SENSOR_LIGHT) SetPower (OUT_A OUT_C,
POWER) OnFwd(OUT_A OUT_C) start
watcher THIS IS THE SUBROUTINE initialize.
IT SETS THE SENSOR INPUTS CORRECTLY, STARTS THE
ROBOT GOING FORWARD, AND STARTS THE TASK watcher.
54trusty.nqc
task watcher() while (true)
if (SENSOR_2 lt DARK2) if
(SENSOR_3 lt DARK3) state BOTH_ON
else if (SENSOR_3 gt LIGHT3) state LEFT_ON
else state INDETERMINATE
else if (SENSOR_2 gt LIGHT2)
if (SENSOR_3 lt DARK3) state RIGHT_ON
else if (SENSOR_3 gt LIGHT3) state
BOTH_OFF else state
INDETERMINATE else state
INDETERMINATE
55trusty.nqc
task watcher() while (true) ONCE
STARTED, WATCHER KEEPS ON RUNNING FOR EVER
56trusty.nqc
if (SENSOR_2 lt DARK2) if (SENSOR_3 lt DARK3)
state BOTH_ON else if (SENSOR_3 gt LIGHT3)
state LEFT_ON else state INDETERMINATE IF
BOTH SENSORS ARE BELOW THEIR INDIVIDUAL DARK
THRESHOLD, state IS SET TO BOTH_ON. IF THE SENSOR
ON THE LEFT IS DARK, AND THE SENSOR ON THE RIGHT
IS ABOVE ITS LIGHT THRESHOLD, state IS SET TO
LEFT_ON. IF THE SENSOR ON THE LEFT IS DARK, AND
THE SENSOR ON THE RIGHT IS BETWEEN ITS LIGHT AND
DARK THRESHOLD, state IS SET TO INDETERMINATE
57trusty.nqc
else if (SENSOR_2 gt LIGHT2) if (SENSOR_3 lt
DARK3) state RIGHT_ON else if (SENSOR_3 gt
LIGHT3) state BOTH_OFF else state
INDETERMINATE THIS SORTS OUT RIGHT_ON AND
BOTH_OFF, AND ANOTHER KIND OF INDETERMINATE
58trusty.nqc
else state INDETERMINATE AND THIS CATCHES THE
CASE WHERE BOTH SENSORS ARE BETWEEN
THRESHOLDS THATS ALL YOU NEED OFF YOU GO
59How can I find out more?
Books Core Lego Mindstorms Programming by Brian
Bagnold Good intro to Mindstorms and to
LeJos Web Too many sites to list. Just Google
any mixture of mindstorms, lego, robot, sensors,
java, nqc, rcx. Lots of good stuff, and most
sites have links to lots of others.
60sources Owen Holland Peter Marwedel