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:
if the right button is pressed when a character in column 10 is highlighted then the corresponding line in the program (in bold) will give Math.Remainder(10,11) which is 10 (10 divided by 11 is zero with remainder 10). Adding one to this gives the value 11 and so the new value for col is set to 11.
if the right button is pressed when a character in column 11 is highlighted then the corresponding line in the program will give Math.Remainder(11,11) which is 0 (11 divided by 11 is one with remainder zero). Adding one to this gives the value 1 and so the new value for col is set to 1.
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.