Introduction

This tutorial will build on the ideas from the previous one on first steps with pbLua. We'll discover the different things we can do with the LCD display and how they can be combined to make effective indicators of the current state of your robot's program.

Along the way, we'll learn a bit about the Lua string library, and also some more of Lua's syntax.

Remember to refer to the online version of Programming in Lua is a reference that you should be looking at in parallel with this text.

By the end of this tutorial, you'll be able to control the LCD display an the NXT as well as have a better understanding of the string library and how it can be used to format text.

Hello World!

We'll use the canonical first program to get an idea of how to control the LCD display using the pbLua Display API. Recall that the NXT specific functions are all in the nxt table.

-- Hello World! for the LCD Display

nxt.DisplayClear()
nxt.DisplayText( "Hello World!" )

Once again, the code is straightforward. The call to nxt.DisplayClear() is not strictly needed, but it helps to clear the display before we get started.

Writing Text To the LCD

The LCD display has 6400 individual pixels arranged as 64 rows of 100 pixels each. The coordinates of the top left pixel are (0,0). The coordinates of the bottom right pixel are (99,63).

The DisplayText() function writes the string using a 5x7 font with a single pixel to the right and bottom of each character. We'll adopt the convention that the x and y coordinates of the string are relative to the top left pixel of the display.

The Lua language allows you to call functions with fewer parameters than required, and it will use nil as the value of parameters that are not specified. It is up to the library designer to handle function calls with fewer parameters than are specified, and the nxt.DisplayText() function is a great example of how this works.

The function is defined to be called like this:

nxt.DisplayText( string [, x, y, inv] )

By convention, parameters enclosed in "[]" are optional.

If you do not specify the x and y coordinates in the call to nxt.DisplayText(), they default to (0,56) which puts the text on the bottom line of the display.

To get an idea of how the x and y coordinates are used to place text on the display, the following code will write 8 strings on the display at nice 8 pixel vertical and 4 pixel horizontal intervals:

-- Writing text to the LCD

nxt.DisplayClear()

nxt.DisplayText( "Line 1",  0,  0 )
nxt.DisplayText( "Line 2",  4,  8 )
nxt.DisplayText( "Line 3",  8, 16 )
nxt.DisplayText( "Line 4", 12, 24 )
nxt.DisplayText( "Line 5", 16, 32 )
nxt.DisplayText( "Line 6", 20, 40 )
nxt.DisplayText( "Line 7", 24, 48 )
nxt.DisplayText( "Line 8", 28, 56 )

The nxt.DisplayText() routine does bounds checking to make sure that x and y are reasonable, and it also looks after clipping text that wraps past the edge of the display. Since each character uses 6 pixels horizontally, you can only get 16 complete characters in one line of the display.

There is one more parameter to the nxt.DisplayText() function, which is the inv parameter. It controls how the text is displayed. By default the text appears as dark pixels on a white background. If inv is non-zero then the text appears as light pixels on a dark background. Here's the previous example rewritten to produce alternating light and dark lines of text:

-- Writing alternating light and dark text to the LCD

nxt.DisplayClear()

nxt.DisplayText( "Line 1",  0,  0, 0   )
nxt.DisplayText( "Line 2",  4,  8, 1   )
nxt.DisplayText( "Line 3",  8, 16      )
nxt.DisplayText( "Line 4", 12, 24, 999 )
nxt.DisplayText( "Line 5", 16, 32, 0   )
nxt.DisplayText( "Line 6", 20, 40, -8  )
nxt.DisplayText( "Line 7", 24, 48, 0   )
nxt.DisplayText( "Line 8", 28, 56, 1   )

Note that it does not matter what the value of inv is - as long as it's non-zero the text is inverted.

There's one additional function for dealing with text on the LCD, and that's the DisplayScroll() function. It scrolls the display up exactly 8 pixels, or one line of text.

The DisplayScroll() function is handy when you're writing a lot of information to the screen and need to make room for more, like this:

-- Scrolling the LCD

nxt.DisplayClear()
nxt.DisplayText( "Line 1" )
nxt.DisplayScroll()
nxt.DisplayText( "Line 2" )
nxt.DisplayScroll()
nxt.DisplayText( "Line 3" )
nxt.DisplayScroll()
nxt.DisplayText( "Line 4" )
nxt.DisplayScroll()

In practice, this is usually more trouble than it's worth and I end up formatting 8 lines of text in specific places on the screen which are then updated, like in the Bluetooth GPS examples.

Setting and Clearing Pixels on the LCD

Writing text strings is nice, but sometimes you'll need to be able to have much finer control of the display, and that's when you want to have pixel level control. In the future, pbLua may have support for lines, circles, sprites, and other graphical niceties. In the meantime, you'll have to write your own routines for this, which may actually be fun for some of you.

The DisplayPixel() routine is defined to be called like this:

nxt.DisplayPixel( x, y [, state] )

and the default value for state is 1 which turns the pixel on. In fact, any non-zero value will turn the pixel on, and if you're paying attention, 0 will turn the pixel off.

For a demonstration of how this works, we'll use a pbLua-specific function that we have not gone over yet in detail which generates a random number within certain bounds. The program below will fill the LCD with 10,000 random pixels, which should result in an almost completely black display.

-- Demonstration of setting random display pixels

function RandomDisplayPixel()
  local x,y
  nxt.DisplayClear()

  for i=1,10000 do
    x = nxt.random(100)
    y = nxt.random(64)
    nxt.DisplayPixel(x,y)
  end

end

-- Another way of writing this without local variables is

function RandomDisplayPixel()
  nxt.DisplayClear()

  for i=1,10000 do
    nxt.DisplayPixel(nxt.random(100),nxt.random(64))
  end

end

Reading the Pixel State

For completeness, the pbLua Display API has a function that reads the state of a pixel. This has some practical use in writing graphic manipulation routines, but I've used it to generate a very simple display copy routine.

In the following example, the contents of the diplay are written to the console as 100 lines of 64 characters each - the display is turned 90 degrees.

-- Reading the Display and Writing it to the Console

function DumpDisplay()
  for x=0,99 do
    s = ""
    for y=0,63 do
      if 0 ~= nxt.DisplayGetPixel(x,63-y) then
        s = s .. "*"
       else
        s = s .. " "
      end
    end
    print( s )
  end
end

That's pretty much all there is to writing text and pixels to the LCD of the NXT. The next tutorial will get into using the touch, light, and sound sensors on the NXT.