Help with shift light script

Discussion on the Lua Scripting capabilities for RaceCapture/Pro. Also see the <a href="http://autosportlabs.net/RaceCapturePro_Lua_Scripting">Lua Scripting Guide</a>

Moderators: JeffC, stieg

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Help with shift light script

Post by PopKorn78 »

Hi all, I need help to get my shift light to work.

With my script, I get this error:
[lua] Script error: [string "tickrate = 30..."]:35.0: attempt to compare number with nil

If I change line 35 from "local r = rpm" to "local r = rpmId", I'm not getting any errors, but the shift light do not work.

Here is the script:
tickRate = 30
--the CAN baud rate
CAN_baud = 250000
--CAN channel to listen on. 0=first CAN channel, 1=second
CAN_chan = 0

ledState = 0
--change this to make a bigger averaging window
maxAvg = 300
--300 = 10 seconds averaging at 30Hz tick rate

--do not change
fuelAvg={}
fuel2Index = 1

--add your virtual channels here
rpmId = addChannel("RPM", 25, 0, 0, 8000, "RPM")
vltId = addChannel("EcuVolts", 10, 1, 0, 20, "volts")
gearid = addChannel("Gear", 25, 0, 0, 6)
iatId = addChannel("IAT", 1, 0, 0, 120, "F")
ectId = addChannel("EngineTemp", 1, 0, 80, 250, "F")
tpsId = addChannel("TPS", 10, 0, 0, 100, "%")
mapId = addChannel("MAP", 10, 2, -15, 25, "PSI")
injId = addChannel("InjectorPW", 10, 3, 0, 100, "ms")
ignId = addChannel("Ignition", 10, 0, -20, 20, "D")
knkId = addChannel("Knock", 1, 0, 0, 15, "count")
camId = addChannel("CamTiming", 10, 0, -20, 20, "D")
fuel2Id = addChannel("FuelLevel", 10, 0, 0,100,"%")

function toF(value)
return value * 1.8 + 32
end

function Shift()
local r = RPM
if r > 6300 then setGpio(2,1) else setGpio(2,0) end
if r > 6800 then setGpio(1,1) else setGpio(1,0) end
if r > 7300 then setGpio(0,1) else setGpio(0,0) end
end

function updateFuelAvg(value)
local i
if #fuelAvg == 0 then
--initialize averaging table
for i = 1, maxAvg do fuelAvg=0 end
end
fuelAvg[fuel2Index] = value
fuel2Index = fuel2Index + 1
if fuel2Index > maxAvg then fuel2Index = 1 end
local sum = 0
for i = 1, #fuelAvg do
sum = sum + fuelAvg
end
setChannel(fuel2Id, sum / maxAvg)
end

function Logging()
if getGpsSpeed() > 10 then
startLogging()
else
stopLogging()
end
end

--customize here for CAN channel mapping
--offset/length in bytes?
--format is: [CAN Id] = function(data) map_chan(<channel id>, data, <CAN offset>, <CAN length>, <multiplier>, <adder>)
CAN_map = {
--did not bother logging gear speed and target cam angle
[1632] = function(data) map_chan(rpmId, data, 0, 2, 1, 0) map_chan(vltId, data, 5, 1, 0.1, 0) map_chan(gearid, data, 0, 1, 1, 0) end,
[1633] = function(data) map_chan(iatId, data, 0, 2, 1, 0, toF) map_chan(ectId, data, 2, 2, 1, 0, toF) end,
[1634] = function(data) map_chan(tpsId, data, 0, 2, 1, 0) map_chan(mapId, data, 2, 2, 0.0145037738, -14.7) end,
[1635] = function(data) map_chan(injId, data, 0, 2, 0.001, 0) map_chan(ignId, data, 2, 2, 1, 0) end,
[1637] = function(data) map_chan(knkId, data, 0, 2, 1, 0) end,
[1638] = function(data) map_chan(camId, data, 2, 2, 1, 0) end
}

function onTick()
processCAN(CAN_chan)
Shift()
updateFuelAvg(getAnalog(0))
Logging()
end



--===========do not edit below===========
function processCAN(chan)
repeat
local id, e, data = rxCAN(chan)
if id ~= nil then
local map = CAN_map[id]
if map ~= nil then
map(data)
end
end
until id == nil
end

--Map CAN channel, big endian format
function map_chan(cid, data, offset, len, mult, add, filter)
offset = offset + 1
local value = 0
while len > 0 do
value = (value * 256) + data[offset]
offset = offset + 1
len = len - 1
end
local cv = value * mult + add
if filter ~= nil then cv = filter(cv) end
setChannel(cid, cv)
end

initCAN(CAN_chan, CAN_baud)
setTickRate(tickRate)

brentp
Site Admin
Posts: 6274
Joined: Wed Jan 24, 2007 6:36 am

Post by brentp »

Looks like your error is happening in the Shift() function.

The nil value it's complaining about is RPM, which never gets set in the script; so it's nil by default, and Lua refuses to compare a number with nil.

You can set the local RPM value by including a filter in the CAN mapping, which can call a custom function. Similar to the toF() function already being used. Example:

Code: Select all

function setRpm&#40;value&#41;
RPM = value
return value
end

--customize here for CAN channel mapping 
--offset/length in bytes? 
--format is&#58; &#91;CAN Id&#93; = function&#40;data&#41; map_chan&#40;<channel id>, data, <CAN offset>, <CAN length>, <multiplier>, <adder>&#41; 
CAN_map = &#123; 
--did not bother logging gear speed and target cam angle 
&#91;1632&#93; = function&#40;data&#41; map_chan&#40;rpmId, data, 0, 2, 1, 0, setRpm&#41; map_chan&#40;vltId, data, 5, 1, 0.1, 0&#41; map_chan&#40;gearid, data, 0, 1, 1, 0&#41; end, 
&#91;1633&#93; = function&#40;data&#41; map_chan&#40;iatId, data, 0, 2, 1, 0, toF&#41; map_chan&#40;ectId, data, 2, 2, 1, 0, toF&#41; end, 
&#91;1634&#93; = function&#40;data&#41; map_chan&#40;tpsId, data, 0, 2, 1, 0&#41; map_chan&#40;mapId, data, 2, 2, 0.0145037738, -14.7&#41; end, 
&#91;1635&#93; = function&#40;data&#41; map_chan&#40;injId, data, 0, 2, 0.001, 0&#41; map_chan&#40;ignId, data, 2, 2, 1, 0&#41; end, 
&#91;1637&#93; = function&#40;data&#41; map_chan&#40;knkId, data, 0, 2, 1, 0&#41; end, 
&#91;1638&#93; = function&#40;data&#41; map_chan&#40;camId, data, 2, 2, 1, 0&#41; end 
&#125; 
Hope this helps!
Brent Picasso
CEO and Founder, Autosport Labs
Facebook | Twitter

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

It kind of work, I don't get the message, but shift light are not working

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

I ran other test.

When I try with a testRpm line, light works fine, but when I use the scipt for the CAN, the lights stay on the last setting I tryed with the testRpm. The RPM on the App works fine, but it looks like the script for the lights does not get the value of the RPM virtual channel. I have tryed two diffrent light script with the same results.

Any ideas LUA gurus?

brentp
Site Admin
Posts: 6274
Joined: Wed Jan 24, 2007 6:36 am

Post by brentp »

Hi, Post your latest script and we'll see if we can tease anything out of it.
Brent Picasso
CEO and Founder, Autosport Labs
Facebook | Twitter

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

Here it is

tickRate = 30
--the CAN baud rate
CAN_baud = 250000
--CAN channel to listen on. 0=first CAN channel, 1=second
CAN_chan = 0

--virtual channels
--addChannel( name, sampleRate, [precision], [min], [max], [units] )
rpmId = addChannel("RPM", 100, 0, 0, 8000, "RPM")
vltId = addChannel("EcuVolts", 10, 1, 0, 20, "volts")
gearid = addChannel("Gear", 25, 0, 0, 6)
iatId = addChannel("IAT", 1, 0, 0, 120, "F")
ectId = addChannel("EngineTemp", 1, 0, 80, 250, "F")
tpsId = addChannel("TPS", 10, 0, 0, 100, "%")
mapId = addChannel("MAP", 10, 2, -15, 25, "PSI")
injId = addChannel("InjectorPW", 10, 3, 0, 100, "ms")
ignId = addChannel("Ignition", 10, 0, -20, 20, "D")
knkId = addChannel("Knock", 1, 0, 0, 15, "count")
camId = addChannel("CamTiming", 10, 0, -20, 20, "D")
fuel2Id = addChannel("FuelLevel", 10, 0, 0,100,"%")

function toF(value)
return value * 1.8 + 32
end

function setRpm(value)
RPM = value
return value
end

--testRPM = 2301
function Shift()
local r = RPM
if r > 1300 then setGpio(1,1) else setGpio(1,0) end
if r > 1800 then setGpio(0,1) else setGpio(0,0) end
if r > 2300 then setGpio(2,1) else setGpio(2,0) end
end

--offset/length in bytes?
--format is: [CAN Id] = function(data) map_chan(<channel id>, data, <CAN offset>, <CAN length>, --<multiplier>, <adder>)
CAN_map = {
[1632] = function(data) map_chan(rpmId, data, 0, 2, 1, 0, setRpm) map_chan(vltId, data, 5, 1, 0.1, 0) map_chan(gearid, data, 0, 1, 1, 0) end,
[1633] = function(data) map_chan(iatId, data, 0, 2, 1, 0, toF) map_chan(ectId, data, 2, 2, 1, 0, toF) end,
[1634] = function(data) map_chan(tpsId, data, 0, 2, 1, 0) map_chan(mapId, data, 2, 2, 0.0145037738, -14.7) end,
[1635] = function(data) map_chan(injId, data, 0, 2, 0.001, 0) map_chan(ignId, data, 2, 2, 1, 0) end,
[1637] = function(data) map_chan(knkId, data, 0, 2, 1, 0) end,
[1638] = function(data) map_chan(camId, data, 2, 2, 1, 0) end
}

function onTick()
--RPM=testRPM
processCAN(CAN_chan)
Shift()
end



--===========do not edit below===========
function processCAN(chan)
repeat
local id, e, data = rxCAN(chan)
if id ~= nil then
local map = CAN_map[id]
if map ~= nil then
map(data)
end
end
until id == nil
end

--Map CAN channel, big endian format
function map_chan(cid, data, offset, len, mult, add, filter)
offset = offset + 1
local value = 0
while len > 0 do
value = (value * 256) + data[offset]
offset = offset + 1
len = len - 1
end
local cv = value * mult + add
if filter ~= nil then cv = filter(cv) end
setChannel(cid, cv)
end

initCAN(CAN_chan, CAN_baud)
setTickRate(tickRate)

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

Does someone as a clue to what I'm doying wrong?

boggie1688
Posts: 138
Joined: Fri Apr 07, 2017 3:47 pm
Location: Oakland, CA

Post by boggie1688 »

A couple things:

Does your RPM show up on the dashboard when you select RPM? I didn't see anything passing the RPM value back to the channel.

Try these changes:

function setRpm(value)
RPM = value
setChannel(rpmId, RPM)
end


function onTick()
processCAN(CAN_chan)
Shift()
end

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

boggie1688 wrote:A couple things:

Does your RPM show up on the dashboard when you select RPM? I didn't see anything passing the RPM value back to the channel.

Try these changes:

function setRpm(value)
RPM = value
setChannel(rpmId, RPM)
end


function onTick()
processCAN(CAN_chan)
Shift()
end
Yes, the RPM on the tablet is working fine.

I will try your changes and see if it works.

boggie1688
Posts: 138
Joined: Fri Apr 07, 2017 3:47 pm
Location: Oakland, CA

Post by boggie1688 »

PopKorn78 wrote:
boggie1688 wrote:A couple things:

Does your RPM show up on the dashboard when you select RPM? I didn't see anything passing the RPM value back to the channel.

Try these changes:

function setRpm(value)
RPM = value
setChannel(rpmId, RPM)
end


function onTick()
processCAN(CAN_chan)
Shift()
end
Yes, the RPM on the tablet is working fine.

I will try your changes and see if it works.
Sorry, I looked back at my edits and realized this won't work.

The idea is that the can_map passes a value to setRpm. You should try to add a print to see what value you are actually getting inside the setRpm function. You can even at print functions inside your shift function too. Check to see what value is getting passed in and make sure it matches what you expect.

Last idea:
Take out the shift() in your ontick.
Make your setRPM() function call your shift() function.

function setRpm(value)
RPM = value
shift(RPM)
end

function shift(RPM)
local r = RPM
if r > 1300 then setGpio(1,1) else setGpio(1,0) end
if r > 1800 then setGpio(0,1) else setGpio(0,0) end
if r > 2300 then setGpio(2,1) else setGpio(2,0) end
end

Then shift is automatically done in conjunction with your processCan().

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

Thanks, will try that.

Can you give me an example for the print for the RPM please? I tried it once, but could not get it to work. Real newb at LUA here

boggie1688
Posts: 138
Joined: Fri Apr 07, 2017 3:47 pm
Location: Oakland, CA

Post by boggie1688 »

PopKorn78 wrote:Thanks, will try that.

Can you give me an example for the print for the RPM please? I tried it once, but could not get it to work. Real newb at LUA here
I'm learning too.

Printing is the easiest way to make sure values are getting passed into the function.

The print command is used like this:
println()

println("hello") will echo hello when you poll the log.
println(RPM) will echo the value of the variable RPM when you poll the log.


The other thing to remember is when you call a function, ie shift(). The value inside parenthesis is passed to the function.

For example:
function setRpm(value)
RPM = 5
shift(RPM)
end

The above function is passing the value RPM to the function shift(). That value is 5. Now you can actually define what is received by the function as a new variable. That variable is then carried into the function. For example:

function shift(rpm2)
local r = rpm2
if r > 1300 then setGpio(1,1) else setGpio(1,0) end
if r > 1800 then setGpio(0,1) else setGpio(0,0) end
if r > 2300 then setGpio(2,1) else setGpio(2,0) end
end

shift(RPM) calls the function shift(), and copies the value of RPM to a variable rpm2. That variable is carried as rpm2 through the entire function. Remember RPM = 5, therefore rpm2 = 5.

I'm not 100% sure how the can_map function shares a variable with setRpm(), but the setRpm() function is called from inside can_map. The function setRpm() is setup to receive a variable, and store it to "value". I'd add a print command inside setRpm to see what that value actually is and whether or not it even has anything to do with RPM.

function setRpm(value)
println(value)
RPM = value
shift(RPM)
end

Again, not a programmer at all, just what I've gathered in the last week from play around with the RCP3.

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

Good news, light works.

Bad news, I lost RPM on the tablet

boggie1688
Posts: 138
Joined: Fri Apr 07, 2017 3:47 pm
Location: Oakland, CA

Post by boggie1688 »

Post the scrip.

Probably need this:
setChannel(rpmId, RPM)

Add it to the end of setRpm().

PopKorn78
Posts: 62
Joined: Mon Mar 16, 2015 2:07 am

Post by PopKorn78 »

Got it to work, needed to add a return value.

Now I need to figure out a way to have the lights to blink &#128516;

Thanks for the help

Post Reply