WriterBot v1

It will be possible to easily scale the written text to any desired size by modifying a single line of the code. This scalability will give our writing robot an advantage over 'plotter' designs, but our writing robot will not be able to match the accuracy of a plotter.

A significant difference between the our turtle writing code and our robot writing code will involve the drawing of arcs. With the turtle arcs could be drawn as a set of many tiny straight lines whereas theoretically with the EV3 robot we can get a genuine arc just by using the command Motor.MoveSync(ports, speed1, speed2, angle, brake) with different values for speed1 and speed2. However, it's not at all obvious how to draw an arc with a given radius of curvature and a given arc angle using this command. The same is true in the standard EV3 software, whether you use the Move Steering block or the Move Tank block. After some very interesting mathematical discussions (just the kind you would hope to have with your students) with a kindly mathematician friend, I was able to obtain this relationship between the wheel separation, w, the radius of curvature of the drawn arc, r, the speed of the left wheel s1, and the speed of the right wheel s2. Note that this equation works even if one or both of the wheel speeds is negative. 

     s1/s2=(2r-w)/(2r+w)   which can be rearranged to give  r=(w/2)(s2+s1)/(s2-s1)

Deriving this equation for yourself could be a very interesting and satisfying mathematical exercise for you or your students, as it was for me... Note that the above equation works only if the pen is located at the midpoint between the wheels, as is the case for our robot. For a closer look at the above equations please see this page.

However, I had some trouble working with these arc movements and decided to postpone or abandon that effort and instead redesign all the characters concerned so that they are made up only of straight lines. Therefore you should not be surprised to note that the sequences of instructions for drawing many of the characters are not the same as they were for the turtle.

Here then (drum roll, please) is the code for WriterBot v1: 

'WriterBot v1 by Nigel Ward

mystring="EV3"   'you can change this

ports="BC"

penport="A"

scale=10  'desired letter height in cm: you can change this

'try heights between 5-20cm

s = scale * 0.0515  'adjust scale factor

tf=2   'turnfactor = motor turn angle / robot turn angle

'depends on wheel separation and wheel diameter

'recommended value =2 for standard driving

'base with wheel separation = 12.5cm and wheel diam = 5.6cm

sf = 1 'speed factor 1-3 (recommended value =1)

'For compatibility with the EV3 Explorer compiler,

'use array indices that are the Unicode

'code numbers of the corresponding characters.

'For example, the code number for "A" is 65

sequence[48]= "0A 1P 2c cA Cc 6c Ca 5p 1C 10"         '0

sequence[49]= "0A 30 0c 0P cc 0a 4p 0A 5P 2p" '1

sequence[50]= "0A 3c 0P ca ca dC 1A 2p"               '2

sequence[51]= "0A 3c 0P ca ca cA cA Ca Cp cC 10"      '3

sequence[52]= "1A 0P 2p 2A 0H 0P gG 0A 2p 0a 1A"      '4

sequence[53]= "0A 1C 0P Ca cA cC 1a 2a 2p 0a 4A"      '5

sequence[54]= "0A 2a 0P 1c cA CA cc 2c ca cp 0c 3A"   '6

sequence[55]= "1K 0P jk 6p 0e fE"                     '7

sequence[56]= "1C 0P cA da ca ca dA cp 0C 10"         '8

sequence[57]= "0a 5C 0P cA cC 2C ca Ca cC 1p 0a 2A"   '9

sequence[65]= "0A 0P 2p 0a 2P 6F ef 0f ee 2p 0A"       'A

sequence[66]= "0A 2a 0P 1C cA cC 1A 4a 5C Ca cp Cc 5a" 'B

sequence[67]= "2A 1c 0P CA cc 2c ca cp 0c 3A"          'C

sequence[68]= "0P 1C cC 2C cC 1a 8p 0a 20"             'D

sequence[69]= "0A 2a 0P 1p 0F ef 0P 6a 4A 2p"          'E

sequence[70]= "0A 2a 0P 1F 0p ef 0P 6a 4p 0A 20"       'F

sequence[71]= "0C cP 0c 1C CA cc 2c ca cp 0c 3A"       'G

sequence[72]= "0A 2a 0P 2p 0C DC 0P 4p 0a 2a 0P 4p 0A" 'H

sequence[73]= "0A 4a 0P 2p 5a 0P 4p 0A 5P 2p"          'I 

sequence[74]= "0A 4a 0P 2a 3c cA Cp cC 10"             'J

sequence[75]= "0A 0P 4p 0a 2C 0P Da dp 0C"             'K

sequence[76]= "0A 4P 8a 2p"                            'L

sequence[77]= "0A 0P 4C Ca cC 8p 0a"                   'M

sequence[78]= "0A 0P 4E Fe 4p 8a"                      'N

sequence[79]= "1C 0P cC 2C cA cC 2C cp 0C 10"          'O

sequence[80]= "0A 0P 4a 1c cA Cc 5p 0c dC"             'P

sequence[81]= "0a 5C 0P cA cC 2C ca 5C 6p 0a 1c 0P cp 0C" 'Q

sequence[82]= "0A 0P 4a 1c cA Cc 5c dp 0C"             'R

sequence[83]= "0a 5C 0P cA cA da ca cp 0c 3A"          'S

sequence[84]= "0A 4a 0P 20 5a 4p 0A 10"                'T

sequence[85]= "0a 8P 3C cA cC 3p 7P 5p 0a"             'U

sequence[86]= "0A 4J 0P Jj 0j jp 0J 8a"                'V

sequence[87]= "0A 4P 8e eE 0E Ee 4p 8a"                'W

sequence[88]= "0F 0P fp 0f 6f 0P fp 0F"                'X

sequence[89]= "1A 0P 2E ep Ee 0e 0P ep 0E 8a"          'Y

sequence[90]= "0A 4a 0P 2F Ff 2p"                      'Z

sequence[32]= "20"                                     'space

sequence[45]= "0A 1a 0P 2p 0a 2A"                      'hyphen

sequence[46]= "0P 0b 0b 0p 0B 0B 10"                   'period

For j=1 To Text.GetLength(mystring)

  char=text.GetSubText(mystring,j,1)  

  'extracts jth character from mystring

  unicode_for_char=text.GetCharacterCode(char)

  For n=1 to (1+Text.GetLength(sequence[unicode_for_char]))/3

    movechar=text.GetSubText(sequence[unicode_for_char],n*3-2,1)

    move_unicode=Text.GetCharacterCode(movechar)

    If move_unicode>64 And move_unicode<91 Then  'capital letter

      movesign=-1

      movechar=text.ConvertToLowerCase(movechar)

    Else

      movesign=1

    EndIf

    

    turnchar=text.GetSubText(sequence[unicode_for_char],n*3-1,1)

    turn_unicode=Text.GetCharacterCode(turnchar)

    If turn_unicode>64 And turn_unicode<91 Then  'capital letter

      turnsign=-1

      turnchar=Text.ConvertToLowerCase(turnchar)

    Else

      turnsign=1

    EndIf

    

    If movechar="1" Then

      Motor.Move(ports,10*sf,100*s,"True")

    ElseIf movechar="2" Then

      Motor.Move(ports,10*sf,200*s,"True")

    ElseIf movechar="3" Then

      Motor.Move(ports,10*sf,300*s,"True")

    ElseIf movechar="4" Then

      Motor.Move(ports,10*sf,400*s,"True")

    ElseIf movechar="5" Then

      Motor.Move(ports,-10*sf,100*s,"True")

    ElseIf movechar="6" Then

      Motor.Move(ports,-10*sf,200*s,"True")

    ElseIf movechar="7" Then

      Motor.Move(ports,-10*sf,300*s,"True")

    ElseIf movechar="8" Then

      Motor.Move(ports,-10*sf,400*s,"True")

      

    ElseIf movechar="c" Then  'move sqr(2)*100*s

      Motor.Move(ports,movesign*10*sf,141.4*s,"True")

    ElseIf movechar="d" Then

      Motor.Move(ports,movesign*10*sf,282.8*s,"True")  

    ElseIf movechar="e" Then

      Motor.Move(ports,movesign*10*sf,223.6*s,"True") 'sqr(5)

    ElseIf movechar="f" Then

      Motor.Move(ports,movesign*10*sf,447.2*s,"True") '2*sqr(5)

    ElseIf movechar="g" Then 

      Motor.Move(ports,movesign*10*sf,316.2*s,"True") 'sqr(10)

    ElseIf movechar="j" Then 'sqr(5)

      Motor.Move(ports,movesign*10*sf,412.3*s,"True") 'sqr(17)

    ElseIf movechar="m" Then

      Motor.Move(ports,movesign*10*sf,360.6*s,"True") 'sqr(13)

    EndIf

    

    If turnchar="a" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*90,"True")

    ElseIf turnchar="b" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*180,"True")      

    ElseIf turnchar="c" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*45,"True")

    ElseIf turnchar="e" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*26.565,"True")

    ElseIf turnchar="f" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*63.434,"True")

    ElseIf turnchar="g" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*18.435,"True")

    ElseIf turnchar="h" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*71.565,"True")

    ElseIf turnchar="j" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*14.036,"True")

    ElseIf turnchar="k" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*75.963,"True")

    ElseIf turnchar="m" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*33.69,"True")

    ElseIf turnchar="n" Then

      Motor.MoveSync(ports,turnsign*15,turnsign*-15,tf*56.31,"True")

    ElseIf turnchar="p" Then 

           Motor.Move(penport,-20*turnsign,200,"True")  

           'lowers pen if turnsign negative i.e. capital "P"

    EndIf

  EndFor

  Motor.Move(ports,10*sf,100*s,"True")'insert space between characters

EndFor

Continue on to WriterBot v2 to see how we can incorporate the 'Text Input' code we developed, so that the user can enter the desired text while the program is running rather than having to modify the code each time.