Can you hear me?!

While noone purchased the NXT just to print words and numbers on the screen, knowing how to print things on the NXT screen can be useful. In this post, I’ll use the NXT sound sensor to illustrate how to use the NXC printing commands with the signal detected by NXT sensors.

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

Sound sensor output

Sound sensor output

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.

Posted in Basic NXC, Sensors | Tagged , | Leave a comment

Hello world!

Now, it’s time to look  at some actual NXC programs. We will start with the traditional first example – a “hello world” program – a program that prints a “hello world” message on the screen. This example will demonstrate the structure of NXC programs, as well as how to compile and run them.

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 NXT™brick 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:

hello world

hello world

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:

FxCam_1356576396667

Posted in Basic NXC | Tagged , , , , | Leave a comment

NXT micro-computer

NTX brickThe NXT™ brick is a micro-computer. As any other computer, it needs an operating system (OS) to communicate with the hardware and to allow programs to run. Different OSs are developed and optimized for different types of computers. The NXT™ micro-computer runs the NXT™ OS. Among other things, the NXT™ OS provides a set of commands and functions that define how NXT™ (i.e., the robot) communicates with motors, sensors, and the NXT™ screen. It also defines the required structure and properties of programs that will be run on the NXT™. As any other machine, at its lowest level NXT™ requires all programs to be represented in the form of the machine language. All commands in the machine language are represented as sequences of 1 and 0, e.g., 10101100101. As such they correspond to electrical signals: 1 – signal/electricity on and 0 – signal/electricity off, that can be directly interpreted by the computer. However, while easily understood by computers, machine language is not very intuitive for humans (because it consist entirely of 1s and 0s) and it is very inefficient (or almost impossible) for programmers to use it.

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 NXT™programming 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:

  1. Download the latest NBC release (zip or tgz file, depending on the platform) from http://bricxcc.sourceforge.net/nbc/, and
  2. Unpack the downloaded file.

To find more up-to-date information and documentation for NXC, check http://bricxcc.sourceforge.net/nxc/.

 

Posted in About | Tagged , , | Leave a comment