Text Input

One weakness of the standard EV3 software is its limited handling of text strings - all it can do is join text strings together (i.e. 'concatenate' them). So an EV3 Basic program that works with text might be a good place to start. Let's make a program that allows us to build a text string using the EV3's LCD screen and buttons, just like you have probably already done when you entered a WiFi or Bluetooth password on the brick. This program uses the EV3 brick but doesn't have any robotic element itself (motors, sensors) but it will be used later to create a text string to be written out by a 'writing robot' that we will develop.

To keep the code manageable, we will limit the allowed characters to the 26 capital letters of the English alphabet, the 10 digits, the period (dot), the hyphen and the space. For easy reading, we will use the largest text size possible, size 2, which has character cells that are 16 pixels wide. We will allow 22 pixels for the height of these large character cells. The characters will be arranged in a grid pattern with four rows numbered 1 to 4 and 11 columns numbered 1 to 11. We'll make it possible to 'wrap' from one side of the grid to the other as we move the highlight around the grid. So the screen will look like this: 

Clicking on the '<' will backspace (delete) the last character of the string and clicking the '>' will indicate that we have finished building the string, so we'll call that the 'Enter' character. We'll include error-checking so that if any of the three unused cells on the grid is clicked there will be a warning tone. There will also be a warning tone if the user tries to enter more than 11 characters, or if the user tries to backspace when there are no characters to delete. Note in the above image that the 'F' initially highlighted, and that it is in row 2 and column 6 of the grid. Note also that a rectangle has been drawn which will enclose our text string.

Here is possible code for this project. As usual, you can easily copy and paste this code into Small Basic and then test it for yourself. Nothing in this code is incompatible with the compiler of EV3 Explorer, so Explorer can be used to compile this program to the brick if desired ('brick mode'), rather than running it directly from Small Basic ('PC mode'). 

mytext=""

LCD.Clear()

LCD.Text(1,0,3,1," <=Backspace  >=Enter")

'Don't confuse the EV3 enter (middle) button 

'with the '>' char on the LCD screen

line[1]="0123456789."

line[2]="ABCDEFGHIJK"

line[3]="LMNOPQRSTUV"

line[4]="WXYZ -  < >"

LCD.Text(1,0,16,2,line[1])

LCD.Text(1,0,38,2,line[2])

LCD.Text(1,0,60,2,line[3])

LCD.Text(1,0,82,2,line[4])

LCD.Rect(1,0,103,178,25)  'draw rectangle to hold our string

col=6   'current column

row=2   'current row

x=81    'x coordinate of highlighted char 'F'

y=35    'y coordinate of highlighted char 'F'

LCD.InverseRect(x,y,16,22)   'highlight character 'F'

loop="True"   'loop control variable

While loop

  Buttons.Wait()

  Button=Buttons.GetClicks()

  LCD.InverseRect(x,y,16,22)   'clear inverse

  If Button="R" Then

    col=1+Math.Remainder(col,11)  'allow jump from col 11 to col 1

  ElseIf Button="L" Then

    col=11-Math.Remainder(12-col,11)'allow jump from col 1 to col 11

  ElseIf Button="U" Then

    row=4-Math.Remainder(5-row,4)  'allow jump from row 4 to row 1

  ElseIf Button="D" Then

    row=1+Math.Remainder(row,4)  'allow jump from row 1 to row 4

  ElseIf Button="E" Then

    If row=4 and col>6 Then

      If col =9 then   'backspace

        If  mytext<>"" Then

          'remove last character from mytext

          mytext=Text.GetSubText(mytext,1,Text.GetLength(mytext)-1)

        Else  'nothing to delete

          Speaker.Tone(100,1000,1000)

        endif

      ElseIf col = 11 Then   'Enter

        Loop="False"   ' do not repeat loop

      Else   'col=7,8 or 10, which is not valid in row 4

        Speaker.Tone(100,1000,1000)

      EndIf  

    Else  'middle button was pressed over a normal character

      If Text.GetLength(mytext)<>11 Then

        mytext=mytext+Text.GetSubText(line[row],col,1)

      Else  'already have the maximum 11 characters

        Speaker.Tone(100,1000,1000)

      EndIf

    EndIf

  EndIf

  x=-15+col*16 'calculate x coordinate of character to be highlighted

  y=-9+row*22  'calculate y coordinate of character to be highlighted

  LCD.InverseRect(x,y,16,22)

  LCD.Text(1,1,107,2,"           ")  'clear our text string

  LCD.Text(1,1,107,2,mytext)

EndWhile

LCD.Clear()

LCD.Text(1,0,16,2,"Here is")

LCD.Text(1,0,38,2,"your text:")

LCD.Text(1,0,82,2,mytext)

Program.Delay(8000)   'display for 8 seconds

This program includes plenty of comments so with some thought and experimentation you should be able to figure it out well enough, but I will give you some help with certain lines.

The first 'difficult' lines are the ones that use the function Math.Remainder(dividend, divisor). This function divides the first number by the second and returns the remainder. For example   Math.Remainder(11,3) would return 2. Other programming languages call this function 'modulus'. One way to understand how the function works in my program would be to try substituting values into the parameters of the argument. For example:

Let's look now at the line (in bold in the program above)

    mytext=Text.GetSubText(mytext,1,Text.GetLength(mytext)-1)

This line is used to remove the last character from the string, if necessary. It uses the function Text.GetSubtext(text, start, length) which returns a substring of the original string. It returns a substring with 'length' characters beginning with character 'start'. For example, Text.GetSubtext("EV3 Basic", 2, 5) would return "V3 Ba". Let's see whether my line of code can successfully remove the last character from the string "EV3 Basic". Text.GetLength("EV3 Basic") would return the number of characters in the string, which is nine, including the space. Text.GetSubText("EV3 Basic",1,9-1) would return a substring of "EV3 Basic". The substring would have 8 characters and would begin with the first character (character number 1) of the string, so it would return "EV3 Basi", which is exactly what we want.

Let's have a look at the similar line (in bold in the program above):

   mytext=mytext+text.GetSubText(line[row],col,1)

This line will be invoked when the user presses the middle button on the brick with the intention of adding the highlighted character to the existing string. Let's suppose the highlighted character is 'F' which we already noted is in row 2 and column 6. Then 

Text.GetSubText(line[row],col,1) 

will become 

Text.GetSubText(line[2],6,1).

Line[2] is "ABCDEFGHIJK"  so when we obtain the substring of just one character beginning with the sixth character of that string we obtain the character 'F', which is what we want. Concatenating this one character after the original string (mytext) gives us the correct new value for the string.