Home STEM HQ TI-Nspire Authoring TI-Nspire Scripting HQ Scripting Tutorial - Lesson 46

           


Scripting Tutorial - Lesson 46: Lua Scripting and the TI Innovator™ Hub:

6. Lua Script for the Norland Research/TI Innovator™ Hub Robot



Download supporting file 1 for this tutorial: Norland_Robot.tns

Download supporting file 2 for this tutorial: NorlandRobot_TI-BASIC_Sampler.tns

Texas Instruments TI-Nspire Scripting Support Page

Norland Research E3 Innovator Robot Kit

       
  

Scripting for the Innovator Hub: Lesson 6: Lua Script for the Norland Research/TI Innovator™ Hub Robot

Top of Page

 
ANALOG and DIGITAL commands

The TI Innovator™ Hub has, at its heart, a TI LaunchPad MSP432 micro-controller unit, and every input and output to and from such a unit is really just a matter of sending voltage to a particular pin or set of pins on the board. The Hub offers a wide range of specialised commands for doing everything from setting LEDs and sounds to reading rangers, brightness, accelerometers and more.

However, the Hub command list also includes four generic commands - DIGITAL.IN, DIGITAL.OUT, ANALOG.IN and ANALOG.OUT. These can be used to control any pin to which they are connected and can be very useful as tools for going beyond the basic Hub commands.

For example, the Hub command set includes a SERVO command which is very powerful, and useful for controlling servo motors. The SERVO command includes clockwise and anti-clockwise, speed and time options. Issues associated with SERVO are explored in the next tutorial where we build a home-made Hub robot, but the key issue lies in controlling the current drawn, and not burning out the unprotected board.

The team at Norland Research have chosen a safer and more reliable option for their new Norland Research/TI Innovator™ Hub Robot, using direct current motors rather than servos, and providing their own power supply to ensure that the board is well protected. To control these motors, they use ANALOG and DIGITAL commands.

This robot vehicle is driven by motors controlled by a "H-bridge", allowing two sets of switches to control whether motors run forwards or backwards. In this case, these are controlled by BB pins 1-4, linked to ANALOG.OUT (or DIGITAL.OUT) commands. Using ANALOG.OUT allows the user to specify the speed of the robot; DIGITAL commands are either ON or OFF (0 or 1). Both will work for this device.

BB pins 1-7 are connected from the Hub to the robot - 1-4 control left and right wheels, 5 and 6 link to the bumper at the front of the motor (these are DIGITAL.IN pins), and BB7 reads the robot battery state, using ANALOG.IN.

Whether using TI-BASIC or Lua, the BB pins are connected to their ANALOG or DIGITAL commands, and then these are SET or READ. In this way, the robot can be controlled to move forward, back, left or right.

Below, you will find both simple TI-BASIC programs as well as the full Lua script which may be used to control the Norland Hub robot. If the student focus is upon simple coding, then TI-BASIC offers a great solution. You will find in the downloads for this tutorial a Norland Robot TI-BASIC Sampler written using Lua. As outlined in Tutorial 40, this can offer a very convenient way for students to easily access the various TI-BASIC programs required to run the robot, but also, more importantly, the means by which they can quickly and easily edit and explore these programs, instantly trying out their changes to see the effect.

In addition to the usual forward, back, left and right programs, there are simple programs to check the battery level and to check if the front bumpers are activated. There are also two programs related to the Hub's on-board brightness sensor - one which provides easy access to collecting data (which may be plotted or viewed in a spreadsheet) and, more interestingly, a program which uses the surrounding brightness to drive the robot! Entering minimum and maximum brightness values (which might be observed from the previous program), the robot will drive happily until the light is below or above those values - at which points it will reverse and turn to try a new direction!

If the focus is just on using the robot for various purposes OR on more advanced coding, then Lua becomes a clear choice.

Lua offers great opportunities for a simpler interface, controlling the robot by tapping the mouse on a simple control panel, or, even easier for students, simply using the trackpad arrow keys on the handheld to move in the four directions, and escape key to stop.

The Lua script offers the same control features as the TI-BASIC examples, plus other options for drawing on the power of the Hub. You will see from the animated GIF opposite that the autoDrive (or "lightSeeker" program) is a great tool for students to explore both the physical data readings around them, and also important principles of robotics.

Students interested in more challenging coding might be encouraged to explore using sensors other than brightness - an obvious example would be the ultrasonic ranger, with which the robot senses proximity to objects and automatically takes action to avoid these!

  

 
    
  1. A range of new settings variables are added, allowing the user to control such features as robot speed, run time, timer step, etc. Take note of the use of var.monitor and on.varChange which will update the script immediately any change occurs in these monitored values.

    These are stored for convenience in a spreadsheet on page 1.2.

  2.   
      

  3. On-screen instructions are included in on.paint, and on.resize serves as a full reset function (coupled with on.escapeKey).

    Study the graphical controller for the robot, which works neatly with the arrow keys.

  4.   
      

  5. Note the changes to mouseDown and mouseUp.

    Note also the utility function str2list which allows easy separation of Hub rxValues which may not always be numeric.

  6.   
      
  7. are defined here: individually for the four directions, and then the autoDrive function.

  8.   
      

  9. OneShotTimer is added to the Innovator functions, which are otherwise unchanged.

  
  

At this point, it is also instructive to compare the Lua functions we are defining to their TI-BASIC counterparts.

Define battcheck()=Prgm

Local A
Send "CONNECT ANALOG.IN 7 BB7 "
Send "READ ANALOG.IN 7 "
Get A
Disp A
Send "DISCONNECT ANALOG.IN 7 "
EndPrgm

Define bumper(time)=Prgm

Local n,l,r Send "CONNECT DIGITAL.IN 5 BB5 "
Send "CONNECT DIGITAL.IN 6 BB6 "
l:=1
r:=1
For n,1,time
Disp "Time
"&string(n)&" seconds"
Send "READ DIGITAL.IN 5 "
Get r
Send "READ DIGITAL.IN 6 "
Get l
If l>0 Then
Disp "LEFT BUMP at "&string(n)&" seconds"
ElseIf r>0 Then
Disp "RIGHT BUMP at "&string(n)&" seconds"
EndIf
wait 1
EndFor
Send "DISCONNECT DIGITAL.IN 5 "
Send "DISCONNECT DIGITAL.IN 6 "
EndPrgm

Define fd(speed, time)=Prgm

Send "CONNECT ANALOG.OUT 1 BB1 "
Send "CONNECT ANALOG.OUT 3 BB3 "
Disp "FORWARD"
Send "SET ANALOG.OUT 1 "&string(speed)
Send "SET ANALOG.OUT 3 "&string(speed)
wait time
Send "DISCONNECT ANALOG.OUT 1 "
Send "DISCONNECT ANALOG.OUT 3 "
EndPrgm

Define bk(speed, time)=Prgm

Send "CONNECT ANALOG.OUT 2 BB2 "
Send "CONNECT ANALOG.OUT 4 BB4 "
Disp "FORWARD"
Send "SET ANALOG.OUT 2 "&string(speed)
Send "SET ANALOG.OUT 4 "&string(speed)
wait time
Send "DISCONNECT ANALOG.OUT 2 "
Send "DISCONNECT ANALOG.OUT 4 "
EndPrgm

Define lt(speed, time)=Prgm

Send "CONNECT ANALOG.OUT 1 BB1 "
Send "CONNECT ANALOG.OUT 4 BB4 "
Disp "FORWARD"
Send "SET ANALOG.OUT 1 "&string(speed)
Send "SET ANALOG.OUT 4 "&string(speed)
wait time
Send "DISCONNECT ANALOG.OUT 1 "
Send "DISCONNECT ANALOG.OUT 4 "
EndPrgm

Define rt(speed, time)=Prgm

Send "CONNECT ANALOG.OUT 2 BB2 "
Send "CONNECT ANALOG.OUT 3 BB3 "
Disp "FORWARD"
Send "SET ANALOG.OUT 2 "&string(speed)
Send "SET ANALOG.OUT 3 "&string(speed)
wait time
Send "DISCONNECT ANALOG.OUT 2 "
Send "DISCONNECT ANALOG.OUT 3 "
EndPrgm

Define brightdata(s)=Prgm

Local n,b
time:={}
brightness:={}
For n,1,s
Send "READ BRIGHTNESS "
Get b
time[n]:=n
brightness[n]:=b
Disp "Brightness "&string(b)
Send "SET SOUND eval(b*100) 0.1"
Wait 0.1
EndFor
EndPrgm

Define lightseeker(m,x)=Prgm

Local b
b:=0
Send "READ BRIGHTNESS "
Get b
Disp "Brightness "&string(b)
Send "SET SOUND eval(b*10) 0.5"
While b>m
Send "READ BRIGHTNESS "
Get b
Disp "Brightness "&string(b)
Send "SET SOUND eval(b*10) 0.5"
If b>x Then
bk(100,1)
Else
fd(100,0.5)
lt(100,0.5)
EndIf
EndWhile
EndPrgm

  

-- TI Innovator Init Values

platform.apilevel = '2.7'
local screen = platform.window
local date = "060317"

require 'color'
pcall(function() require 'asi' end)

local hubStrOn, hubStrOff, msgStr, rxValue, timeStr, bump, repeats, time_step, delay, help
local list1, list2, index, dataList = {}, {}, {}, {}
var.store("index", index)
var.store("dataList", dataList)
local fontSize = 20

local robotConnected = false
local bump = 0
local orient = var.recall("orient") or 0
local time_step = var.recall("time_step") or 0.5
local runTime = var.recall("runtime") or 10
local runtimeStr = "Run Time: "..runTime
local robotSpeed = var.recall("speed") or 75
local speedStr = "Robot Speed: "..robotSpeed
local autoMin = 5
local autoMax = 20

var.monitor("speed")
var.monitor("runtime")
var.monitor("time_step")
var.monitor("automin")
var.monitor("automax")
var.monitor("hubstr")
var.monitor("orient")

function on.varChange(varList)

orient = var.recall("orient") or 0
robotSpeed = var.recall("speed") or 75
speedStr = "Robot Speed: "..robotSpeed
runTime = var.recall("runtime") or 10
runtimeStr = "Run Time: "..runTime
time_step = var.recall("time_step") or 0.5
autoMin = var.recall("automin") or 5
autoMax = var.recall("automax") or 20
hubStrOn = string.upper(var.recall("hubstr")) or ''
if hubStrOn:find("ON") then
hubStrOff = hubStrOn:gsub("ON","OFF")
else
hubStrOff = ''
end
screen:invalidate()
end

function addMsg(input)

msgStr = input
print(msgStr)
screen:invalidate()

end

function on.construction()

--the next three lines are required for Hub connection
TI_Innovator.init(TI_InnovatorStateCallback)
TI_Innovator.setReadListener(TI_InnovatorReadCallback)
TI_Innovator.connect()

Menu={

{"About",
{" ©2017 Compass Learning Technologies", function() end},
{" Version "..date, function() end},
{" Contact: steve@compasstech.com.au ", function() end},
{" Help?", function() on.help() end},
},
{"Controls",
{"Scan and Connect", function() TI_Innovator.connect() end},
{"Disconnect", function() TI_Innovator.disconnect() on.resize() end},
{"RESET", function() on.resize() end},
},
{"SET Samples",
{"SET LIGHT ON/OFF (default)", function() hubStrOn = "SET LIGHT ON" hubStrOff = "SET LIGHT OFF" TI_Innovator.Send(hubStrOn) addMsg(hubStrOn) rxValue = "Press mouse down to toggle light" end},
{"SET COLOR.RED ON/OFF", function() hubStrOn = "SET COLOR.RED ON" hubStrOff = "SET COLOR.RED OFF" TI_Innovator.Send(hubStrOn) addMsg(hubStrOn) rxValue = "Press mouse down to toggle red LED" end},
{"SET COLOR.GREEN ON/OFF", function() hubStrOn = "SET COLOR.GREEN ON" hubStrOff = "SET COLOR.GREEN OFF" TI_Innovator.Send(hubStrOn) addMsg(hubStrOn) rxValue = "Press mouse down to toggle green LED" end},
{"SET COLOR.BLUE ON/OFF", function() hubStrOn = "SET COLOR.BLUE ON" hubStrOff = "SET COLOR.BLUE OFF" TI_Innovator.Send(hubStrOn) addMsg(hubStrOn) rxValue = "Press mouse down to toggle blue LED" end},
{"SET SOUND 220 1", function() hubStrOn = "SET SOUND 220 1" hubStrOff = "SET SOUND 0 1" TI_Innovator.Send(hubStrOn) addMsg(hubStrOn) rxValue = "Press mouse down to repeat sound" end},
{'_________________', function() end},
{"SET SPEAKER 1 220 5", function() hubStrOn = "SET SPEAKER 1 220 5" TI_Innovator.Send("CONNECT SPEAKER 1 OUT1") TI_Innovator.Send(hubStrOn) hubStrOff = "SET SPEAKER 1 0 1" rxValue = "Press mouse down to toggle speaker" end},
{"SET LED 1 ON", function() hubStrOn = "SET LED 1 ON" TI_Innovator.Send("CONNECT LED 1 OUT1") TI_Innovator.Send(hubStrOn) hubStrOff = "SET LED 1 0FF" rxValue = "Press mouse down to toggle LED" end},
{"SET SERVO 1 CW 50 5 (OUT3)", function() TI_Innovator.Send("CONNECT SERVO 1 OUT3") hubStrOn = "SET SERVO 1 CW 50 5" hubStrOff = "SET SERVO 1 CW 50 0" rxValue = "Press mouse down to toggle servo" end},
{"SET ANALOG.OUT 1 100", function() hubStrOn = "SET ANALOG.OUT 1 100" TI_Innovator.Send("CONNECT ANALOG.OUT 1 OUT1") TI_Innovator.Send(hubStrOn) hubStrOff = "SET ANALOG.OUT 1 0" rxValue = "Press mouse down to toggle analog read" end},
{"SET DIGITAL.OUT 1 ON", function() hubStrOn = "SET DIGITAL.OUT 1 ON" TI_Innovator.Send("CONNECT DIGITAL.OUT 1 OUT1") TI_Innovator.Send(hubStrOn) hubStrOff = "SET DIGITAL.OUT 1 0FF" rxValue = "Press mouse down to toggle digital read" end},
},
{"READ Samples",
{'Norland Battery Check (b)', function() batteryCheck() end},
{"READ BRIGHTNESS", function() hubStrOn = "READ BRIGHTNESS" TI_Innovator.Send(hubStrOn) TI_Innovator.Read() timeStr = "Press mouse down to take fresh reading" end},
{'_________________', function() end},
{"READ RANGER 1", function() hubStrOn = "READ RANGER 1" TI_Innovator.Send("CONNECT RANGER 1 IN1") math.eval("wait(0.5)") TI_Innovator.Send(hubStrOn) TI_Innovator.Read() hubStrOff = '' timeStr = "Press mouse down to take fresh reading" end},
{"READ DHT 1", function() hubStrOn = "READ DHT 1" TI_Innovator.Send("CONNECT DHT 1 IN1") TI_Innovator.Send(hubStrOn) TI_Innovator.Read() hubStrOff = '' driver = "DHT 1" timeStr = "Press mouse down to take fresh reading" end},
{"READ BAROMETER", function() hubStrOn = "READ BAROMETER" TI_Innovator.Send("CONNECT BAROMETER I2C") TI_Innovator.Send(hubStrOn) TI_Innovator.Read() hubStrOff = '' timeStr = "Press mouse down to take fresh reading" end},
{"READ ACCEL 1", function() hubStrOn = "READ ACCEL 1" TI_Innovator.Send("CONNECT ACCEL 1 I2C") TI_Innovator.Send(hubStrOn) TI_Innovator.Read() hubStrOff = '' timeStr = "Press mouse down to take fresh reading" driver = "ACCEL 1" driverConnected = true end},
{"READ ANALOG.IN 1", function() hubStrOn = "READ ANALOG.IN 1" TI_Innovator.Send("CONNECT ANALOG.IN 1 IN1") TI_Innovator.Send(hubStrOn) TI_Innovator.Read() hubStrOff = '' timeStr = "Press mouse down to take fresh reading" driver = "ANALOG.IN 1" driverConnected = true end},
{"READ DIGITAL.IN 1", function() hubStrOn = "READ DIGITAL.IN 1" TI_Innovator.Send("CONNECT DIGITAL.IN 1 IN1") TI_Innovator.Send(hubStrOn) TI_Innovator.Read() hubStrOff = '' timeStr = "Press mouse down to take fresh reading" driver = "DIGITAL.IN 1" driverConnected = true end},
},
{"Sound Samples",
{"C4", function() hubStrOn = "SET SOUND 262 TIME 1" TI_Innovator.Send(hubStrOn) hubStrOff = "SET SOUND 0 1" msgStr = hubStrOff rxValue = "Press mouse down to play sound" end},
{"A4", function() hubStrOn = "SET SOUND 440 TIME 1" TI_Innovator.Send(hubStrOn) hubStrOff = "SET SOUND 0 1" msgStr = hubStrOff rxValue = "Press mouse down to play sound" end},
{"C5", function() hubStrOn = "SET SOUND 523 TIME 1" TI_Innovator.Send(hubStrOn) hubStrOff = "SET SOUND 0 1" msgStr = hubStrOff rxValue = "Press mouse down to play sound" end},
{"No tone", function() hubStrOn = "SET SOUND 0 TIME 1" TI_Innovator.Send(hubStrOn) hubStrOff = "SET SOUND 0 1" msgStr = hubStrOff end},
{"Aliens (sample)", function() tempo = 1000 I=1 list1 = notes_aliens list2 = times_aliens playTone(list1,list2) rxValue = "Aliens" end},
{"BallGame (sample)", function() tempo = 1000 I=1 list1 = notes_bgame list2 = times_bgame playTone(list1,list2) rxValue = "Take me out to the Ball Game" end},
{"Happy Birthday (sample)", function() tempo = 1000 I=1 list1 = notes_bday list2 = times_bday playTone(list1,list2) rxValue = "Happy Birthday" end}, {"If I Only Had a Brain (sample)", function() tempo = 4000 I=1 list1 = notes_brain list2 = times_brain playTone(list1,list2) rxValue = "If I only had a brain" end},
{"Fur Elise (sample)", function() tempo = 1000 I=1 list1 = notes_elise list2 = times_elise playTone(list1,list2) rxValue = "Fur Elise" end},
{"Home on the Range (sample)", function() tempo = 1000 I=1 list1 = notes_home list2 = times_home playTone(list1,list2) rxValue = "Home on the Range" end},
{"Well-tempered Scale", function() tempo = 1000 I=1 list1 = notes_welltemp list2 = times_scale playTone(list1,list2) rxValue = "Well tempered scale" end},
{"Harmonic Scale", function() tempo = 1000 I=1 list1 = notes_harmonic list2 = times_scale playTone(list1,list2) rxValue = "Harmonic scale" end},
},
{"Robot Samples",
{"ROBOT FD runTime", function() fd(runTime) end},
{"ROBOT BK runTime", function() bk(runTime) end},
{"ROBOT LT 1 secs", function() lt(1) end},
{"ROBOT RT 1 secs", function() rt(1) end},
{"autoDrive (a)", function() autoDrive(runTime) end},
{"Switch Handheld Orientation (o)", function() orient = 1 - orient var.store("orient", orient) end},
},
{"TIMER Samples",
{"wait(runTime) (w)", function() wait(runTime) end},
{"blink(runTime,1)", function() blink(runTime,1) end},
{"alarm(runTime,0.5)", function() alarm(runTime,0.5) end},
},
}
toolpalette.register(Menu)
screen:invalidate()
end

 
 

 
 

In our next lesson, we take these ideas further and build our own simple robot, exploring the servo commands.


  

Back to Top

  

Home STEM HQ TI-Nspire Authoring TI-Nspire Scripting HQ Scripting Tutorial - Lesson 46