NXT sound sensor detects the intensity of sound in the surrounding area; louder sound – higher the intensity.
Our first goal is to set up the sound sensor and print out the detected signal on the screen. To do so, we’ll use the following code
task main()
{
SetSensorSound(S1);
int hlp = 0;
while (true)
{
NumOut(0, 0, SensorScaled(S1));
Wait(100);
}
}
The “SetSensorSound” command assigns the sound sensor to port 1, command “SensorScaled(S1)” reads the signal detected by this sensor, and the command “NumOut” prints the detected signal on the screen, at the location (0,0).
Now, let’s say that we not only want to see the current value (strength) of detected signal, but also to see the values of signal detected in previous one, two, three,… seconds ago. Printing the detected values on the screen adjacent to each other may not be too informative. A better approach would be to print the detected signal in the 2-dimensional coordinate system, where x-axis represents time and y-axis represents the signal value (strength). We can plot the coordinate system as follows:
task main()
{
ClearScreen();
RectOut(0, 0, 99, 63);
TextOut(90, 6, ">");
TextOut(23, 45, "^");
LineOut(25, 10, 90, 10);
LineOut(25, 10, 25, 50);
NumOut(12, 8, 0);
NumOut(8, 25, 50);
NumOut(2, 45, 100);
Wait(1000);
}
With the “RectOut” command we plot a rectangular box in which we’ll draw our coordinate system. Then, we use the “LineOut” commands to plot x- and y-axes. The (0, 0) point of the coordinate system is in the (25, 10) point of the screen. We use text printing command “TextOut” to plot the arrow of the coordinate system, and “NumOut” command to plot the percentage values that will be used to describe the signal strength.
Now, we need to combine these two codes together.
#define x0 25 #define y0 10 #define numElements 65 #define perSignal 50 #define maxSignal 100 //procedure that plots coordinate system void drawAxes() { ClearScreen(); RectOut(0,0, 99, 63); TextOut(90, 6, ">"); TextOut(23, 45, "^"); LineOut(x0, y0, x0 + numElements, y0); LineOut(x0, y0, x0, perSignal); NumOut(12, 8, 0); NumOut(8, 25, 50); NumOut(2, 45, 100); } //procedure that plots n(umElements) signal values onto the coordinate system void plotDBs(int arrayDB[], int indexDB) { drawAxes(); //first n(umElements) if (indexDB < numElements) for (int i = 0; i < numElements; i++) LineOut(x0 + i, y0, x0 + i, y0 + arrayDB[i]); // all other elements else { int j = 0; for (int i = (indexDB % numElements + 1); i < numElements; i++) LineOut(x0 + j, y0, x0 + j++, y0 + arrayDB[i]); for (int i = 0; i < indexDB % numElements + 1; i++) LineOut(x0 + j, y0, x0 + j++, y0 + arrayDB[i]); } } task main() { //array that keeps track of the last n(umElements) values detected by the sensor int myVector[numElements]; //the array will be automatically initialized to zero SetSensorSound(S1); int hlp = 0; while (true) { int signalIn = SensorScaled(S1); //we will scale the imput values so they plot within the coordinate system if (signalIn > maxSignal) signalIn = maxSignal; myVector[hlp % numElements] = (perSignal - y0)*signalIn/maxSignal; plotDBs(myVector, hlp); hlp++; Wait(100); } }
And here is how it looks
The program consists of three procedures: 1) drawAxes that creates the coordinate system, 2) plotDBs that plots the last n sensor values onto the coordinate system, and 3) the main task that sets up the sensor, reads (and stores) the sensor signal, and plots it onto the coordinate system. The program keeps track and plots up to 65 sensor signal values, i.e., 65 latest time points. We assumed that the maximum value the sensor can detect is 100. The signal values are scaled 50% for the plotting/fitting purposes.
]]>Each program consists of one or more tasks; for example, if a robot is required to drive towards a source of sound, its program may consist of the drive forward and sound sensor data processing tasks. Each NXC program must have at least one task and that task is called “main.” Thus, the most simple NXC program can be written as:
task main()
{}
Every task consists of zero or more functions/instructions. However, no instructions means no actions (as in the above example). NXC is case sensitive, meaning that “this” is not the same as “This” or “THis” or “THIS” , etc. Each instruction in NXC ends with the semicolon (;). We will introduce different instructions/functions/programming rules as we go.
Right now, for the “hello world” program we need a simple function called “TextOut.” It is defined as follows:
TextOut(location_x, location_y, message_text, options)
The NXT display is 100px wide (x-axis) and 64px tall (y-axis) and the (0,0) position is in the bottom left corner of the screen. Given this information, we can incorporate the TextOut function in the main task as follows:
task main()
{
TextOut(0, 0, “hello world”);
}
If you write (or copy/paste) this program into a simple text editor and save it as the “helloWorld.nxc” file, you can compile it and transfer it to NXTbrick using the following command:
nbc -$=usb -d helloWorld.nxc
(assuming that the NXT brick is on and connected to the computer via USB port, as well as that helloWorld.nxc program is in the same folder as the nbc compiler).
Now, if you go to NXT brick and select My Files =>Software Files, you will see the helloWorld program. You click on it and press Run to execute it.
If you have done it, you probably didn’t see the “hello world” message on the screen, as the screen returned to the Software Files. It does not mean that the message did not print out, but that this instruction was executed so fast that we didn’t see it before the program terminated itself. Hence, if we want to see our message, we need to delay the termination of the program. We will do it using the function called Wait(time_in_ms).
We can rewrite our program as:
task main()
{
TextOut(0, 0, “hello world”);
Wait(1000);
}
Now, if we compile and run our program, we well get the following output:
There are alternative ways of using TextOut() and Wait() functions. The following example:
task main()
{
TextOut(0, LCD_LINE1, “hello”);
Wait(SEC_5);
TextOut(0, LCD_LINE2, “world1”);
Wait(SEC_5);
TextOut(0, LCD_LINE3, “hello”);
Wait(SEC_5);
TextOut(0, LCD_LINE4, “world2”);
Wait(SEC_5);
TextOut(0, LCD_LINE5, “hello”);
Wait(SEC_5);
TextOut(0, LCD_LINE6, “world3”);
Wait(SEC_5);
TextOut(0, LCD_LINE7, “hello”);
Wait(SEC_5);
TextOut(0, LCD_LINE8, “world4”);
Wait(SEC_5);
}
will produce the following output:
]]>Knowing that NXT will represent the brain of any robot we make, as well as that this brain does not come with embedded intelligence or ability to learn, each robot we make will be as smart as we program it to be. Programming in the machine language probably wouldn’t take us too far. Luckily, there are easier ways to program NXT
. This does not mean that suddenly NXT
can understand something else than 1s and 0s; it means that there exist other computer programs (compilers and interpreters) that can translate programming languages that are more intuitive for humans into the machine language. There are quite a few programming languages (and compilers) that can be used for NXT
programming (here is a nice summary) and NXT comes with a LEGO® provided bytecode interpreter.
Here, I will focus on one of the high-level NXTprogramming languages, called NXC (Not eXactly C). The NXC is very similar to a standard C programming language, with some limitations that reflect different capabilities of NXT
OS. The most important part of the NXC is the NXC Application Programming Interface (API) that describes the system functions, constants, and macros that can be used by programs (this is what we’ll use to work with sensors, motors, and outputs). To write a NXC program, you don’t need any fancy editor, a simple text editor is enough.
To compile NXC programs we will use the NBC compiler (available for multiple platforms and can run under both 32-bit and 64-bit OS.). This compiler translates text-based source NXC programs into NXT bytecodes; these bytecodes are then executed on NXT
with the help of the NXT
LEGO® bytecode interpreter. A nice feature of NBC compiler is that it automatically includes NXC APIs when compiling a program. The NBC compiler installation is very simple:
To find more up-to-date information and documentation for NXC, check http://bricxcc.sourceforge.net/nxc/.
]]>