AEM infinity CAN BUS data

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

roostinds
Posts: 11
Joined: Wed Sep 09, 2015 3:52 am
Location: Los Angeles Ca

AEM infinity CAN BUS data

Post by roostinds »

Hello all, please excuse my noobness but I am just not understanding how to translate the can bus data i am receiving and creating a virtual channel to display that information. I have converted the ID that AEM gives

Message ID: 0x01F0A000 Sources: AEM V2 & EMS&#8208;4 (30&#8208;6XXX) Infinity EMS (30&#8208;71XX) 20ms continuous (50hz) Byte Label Data Type Scaling Offset Range Scaling Offset Range
6 Intake Air Temp  8 bit signed, 2's comp 1 Deg C/bit 0 &#8208;128 to 127 C 1.8 Deg F/bit 32 &#8208;198.4 to 260.6 F
7 Coolant Temp 8 bit signed, 2's comp 1 Deg C/bit 0 &#8208;128 to 127 C 1.8 Deg F/bit 32 &#8208;198.4 to 260.6 F


ID 1 2 3 4 5 6 7 8
&#65279;32546816.0, 28.0, 189.0, 22.0, 43.0, 0.0, 240.0, 48.0, 80.0

So my translated ID is 32546816.0 byte 7 for coolant temp and based on scaling guage should read 86 degrees. My question is how the heck do i translate this into Lua script and put it into a virtual channel. Thanks for any help. Again sorry for the noobness. I tried researching as much as i could before asking.

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

It says byte 7 but thats actually the 8th bit as it starts from 0.

here is the doc you need for the AEM CAN protocol:
http://aemelectronics.com/sites/default ... Public.pdf

So for ID 32546816 (which is the Hex -> Dec of the 0x01F0A000 data)
RPM Bits 0 , 1 [28 , 189] that would be 28*256 + 189 = 7357 * .39063 = 2874rpm
TPS Bits 4, 5 [0, 240] that would be = 240 * 0.0015259 = 0.366%
ATS Bit 6 [48] that would be 48 Deg C
CTS Bit 7 [80] that would be 80 Deg C

The map part of the example scripts would be written as:

Code: Select all

CAN_map = &#123; 
  &#91;32546816&#93; = function&#40;data&#41; 
    map_chan&#40;rpmId, data, 0, 2, 0.39063, 0&#41;
    map_chan&#40;tpsId, data, 4, 2, 0.0015259, 0&#41;
    map_chan&#40;atsId, data, 6, 1, 1, 0&#41;
    map_chan&#40;ctsId, data, 7, 1, 1, 0&#41;
    end
&#125; 
If you still have issues shout out and I can set the base script up for you.

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

it'll only take me a sec... here you go:

Code: Select all

--Designed for AEM CAN Logging
--AEM CAN V2 Broadcast Protocol

--============================== Set Variables =================================

setTickRate&#40;25&#41;
initCAN&#40;0, 500000&#41;
CAN_chan = 0 -- 0=first CAN channel, 1=second

--comment out channels if reqd
--note IDs in HEX and must be converted to Decimal
--usage&#58; map_chan&#40;var, data, starting byte, byte length, Unit, Offset&#41;
CAN_map = &#123; 
  &#91;32546816&#93; = function&#40;data&#41; 
    map_chan&#40;rpmId, data, 0, 2, 0.39063, 0&#41; 
    map_chan&#40;tpsId, data, 4, 2, 0.0015259, 0&#41; 
    map_chan&#40;atsId, data, 6, 1, 1, 0&#41; 
    map_chan&#40;ctsId, data, 7, 1, 1, 0&#41; 
    end 
&#125;
	
--=============================== Add Virtual Channels ==========================

--usage&#58; addChannel&#40;"Name",samplerate&#123;1,10,25,50,100,200&#125;,precision&#40;2&#41;,min&#40;0&#41;,max&#40;1000&#41;,units&#41;
rpmId = addChannel&#40;"RPM", 25, 0, 0, 10000, 'RPM'&#41;
tpsId = addChannel&#40;"TPS", 10, 1, 0, 100, '%'&#41;
atsId = addChannel&#40;"ATS", 10, 1, 0, 200, 'C'&#41;
ctsId = addChannel&#40;"CTS", 10, 1, 0, 200, 'C'&#41;

--========================== Init ===================================

function onTick&#40;&#41;
  processCAN&#40;&#41;
end

--========================== CAN =============================

function processCAN&#40;&#41; --finds an id that exists then passes it to 
  repeat
    local id, e, data = rxCAN&#40;0&#41;
    if id ~= nil then  -- step through CAN data until you get a value
      local map = CAN_map&#91;id&#93;
      if map ~= nil then
        map&#40;data&#41; --this runs map_chan function with the CAN 'data'
      end
    end
  until id == nil
end

function map_chan&#40;cid, data, offset, len, mult, add&#41; --eg &#40;rpmId, data, 0, 2, 1, 0&#41;
  offset = offset + 1
  local value = 0
  while len > 0 do
    value = &#40;value * 256&#41; + data&#91;offset&#93;
    offset = offset + 1
    len = len - 1
  end
  setChannel&#40;cid, &#40;value * mult&#41; + add&#41;
end

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

Just noticed you're in the US... so you need to change the lines:

map_chan(atsId, data, 6, 1, 1, 0)
map_chan(ctsId, data, 7, 1, 1, 0)

to

map_chan(atsId, data, 6, 1, 1.8, 32)
map_chan(ctsId, data, 7, 1, 1.8, 32)

so that you get it in Fahrenheit ... you'll also need to change the units in your virtual channel map:

atsId = addChannel("ATS", 10, 1, 0, 200, 'C')
ctsId = addChannel("CTS", 10, 1, 0, 200, 'C')

to

atsId = addChannel("ATS", 10, 1, 0, 300, 'F')
ctsId = addChannel("CTS", 10, 1, 0, 300, 'F')

roostinds
Posts: 11
Joined: Wed Sep 09, 2015 3:52 am
Location: Los Angeles Ca

Post by roostinds »

Got it thanks. This helps out so much. I will try this when i get home tonight.. I will definitely let you know if there is anything else i can't figure out..

roostinds
Posts: 11
Joined: Wed Sep 09, 2015 3:52 am
Location: Los Angeles Ca

Post by roostinds »

So if there data on other ID's not associated with this first one, can i add it to the end of this script

CAN_map = {
[32546816] = function(data)
map_chan(rpmId, data, 0, 2, 0.39063, 0)
map_chan(tpsId, data, 4, 2, 0.0015259, 0)
map_chan(atsId, data, 6, 1, 1, 0)
map_chan(ctsId, data, 7, 1, 1, 0)
end

CAN_map = {
[32546820] = function(data)
map_chan(FuelPressId, data, 3, 1, 0.580151, 0)
map_chan(OilPressId, data, 4, 1, 0.580151, 0)
end

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

close... but should be:

Code: Select all

CAN_map = &#123; 
&#91;32546816&#93; = function&#40;data&#41; 
  map_chan&#40;rpmId, data, 0, 2, 0.39063, 0&#41; 
  map_chan&#40;tpsId, data, 4, 2, 0.0015259, 0&#41; 
  map_chan&#40;atsId, data, 6, 1, 1, 0&#41; 
  map_chan&#40;ctsId, data, 7, 1, 1, 0&#41; 
end,
&#91;32546820&#93; = function&#40;data&#41; 
  map_chan&#40;fpsId, data, 3, 1, 0.580151, 0&#41; 
  map_chan&#40;opsId, data, 4, 1, 0.580151, 0&#41; 
end
&#125;
also, keep your virtual channel names to be shorter than 8 characters. I changed the above to fpsId and opsId
note: there is a comma after the first array entry, but not the last.

Array = {[1] = Hi, [2] = This, [3] = is, [4] = an, [5] = array}

print Array[2] will return "This"

In this case CAN_map[32546820] will return:

Code: Select all

function&#40;data&#41;
  map_chan&#40;FuelPressId, data, 3, 1, 0.580151, 0&#41; 
  map_chan&#40;OilPressId, data, 4, 1, 0.580151, 0&#41; 
end
What you are doing here is making an array called CAN_map that is mapping a function to a location in the array [32546816]... The bottom part of the script is finding an ID in the CAN stream, checking if there is data for that ID in the CAN_Map and then grabbing the data (ie the map_chan stuff) and then running it as a function. It's all a bit tricky to get your head around.

Code: Select all

function processCAN&#40;&#41;
  repeat 
    local id, e, data = rxCAN&#40;0&#41; 
    if id ~= nil then
      local map = CAN_map&#91;id&#93; 
      if map ~= nil then 
        map&#40;data&#41;
      end 
    end 
  until id == nil 
end 
so this function only does something if it finds an ID that matches your ID in the CAN_map ie 32546816 or 32546820. If it finds any other ID it will discard it.

If the ID matches then makes a function called map from the data in the CAN_map array and runs it with the data that follows the ID which is the 8 bytes of data that contains the sensor values.

Code: Select all

local map = CAN_map&#91;id&#93; 
which makes:

Code: Select all

map&#40;data&#41;
  map_chan&#40;FuelPressId, data, 3, 1, 0.580151, 0&#41; 
  map_chan&#40;OilPressId, data, 4, 1, 0.580151, 0&#41; 
end
This function calls the map_chan function that does some simple math to convert the required byte data to a value and maps it to a virtual channel using setChannel.

roostinds
Posts: 11
Joined: Wed Sep 09, 2015 3:52 am
Location: Los Angeles Ca

Post by roostinds »

I see you have this command as well

setChannel(cid, (value * mult) + add)

with the new virtual channels I am not seeing them in the dashboard function. Does setchannel how ever I labeled it apprear in the dashboard drop down menu?

Thank you btw. You have been extremely helpful!!

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

setChannel is the RCP command to map a virtual channel.

eg:
setChannel(rpm, 3000)

Can you post your full script?

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

here try this:

Code: Select all

setTickRate&#40;25&#41; 
initCAN&#40;0, 500000&#41; 
CAN_chan = 0 

CAN_map = &#123; 
&#91;32546816&#93; = function&#40;data&#41; 
  map_chan&#40;rpmId, data, 0, 2, 0.39063, 0&#41; 
  map_chan&#40;tpsId, data, 4, 2, 0.0015259, 0&#41; 
  map_chan&#40;atsId, data, 6, 1, 1, 0&#41; 
  map_chan&#40;ctsId, data, 7, 1, 1, 0&#41; 
end, 
&#91;32546820&#93; = function&#40;data&#41; 
  map_chan&#40;fpsId, data, 3, 1, 0.580151, 0&#41; 
  map_chan&#40;opsId, data, 4, 1, 0.580151, 0&#41; 
end 
&#125; 

rpmId = addChannel&#40;"RPM", 25, 0, 0, 10000, 'RPM'&#41; 
tpsId = addChannel&#40;"TPS", 10, 1, 0, 100, '%'&#41; 
atsId = addChannel&#40;"ATS", 10, 1, 0, 200, 'C'&#41; 
ctsId = addChannel&#40;"CTS", 10, 1, 0, 200, 'C'&#41; 
fpsId = addChannel&#40;"FPS", 10, 1, 0, 200, 'PSI'&#41; 
opsId = addChannel&#40;"OPS", 10, 1, 0, 200, 'PSI'&#41; 

function onTick&#40;&#41; 
  processCAN&#40;&#41; 
end 

function processCAN&#40;&#41;
  repeat 
    local id, e, data = rxCAN&#40;0&#41; 
    if id ~= nil then
      local map = CAN_map&#91;id&#93; 
      if map ~= nil then 
        map&#40;data&#41;
      end 
    end 
  until id == nil 
end 

function map_chan&#40;cid, data, offset, len, mult, add&#41;
  offset = offset + 1 
  local value = 0 
  while len > 0 do 
    value = &#40;value * 256&#41; + data&#91;offset&#93; 
    offset = offset + 1 
    len = len - 1 
  end 
  setChannel&#40;cid, &#40;value * mult&#41; + add&#41; 
end
You should see channels called "RPM, TPS, ATS, CTS, FPS and OPS" pop up in the channels list on the RCP dashboard.

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

Post by brentp »

madjak, thanks for the AEM script! is this verified for your AEM installation? I'll add it to our wiki here:

http://autosportlabs.net/AEM_Infinity_6H
Brent Picasso
CEO and Founder, Autosport Labs
Facebook | Twitter

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

Post by brentp »

Also, I normalized the channel names - I assumed the channels are:

RPM
TPS
IAT (Inlet Air Temperature)
EngineTemp
FuelPress
OilPress

Thanks again!
Brent Picasso
CEO and Founder, Autosport Labs
Facebook | Twitter

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

I can't verify it works... I don't have AEM. Just written via the pdf found online.

roostinds
Posts: 11
Joined: Wed Sep 09, 2015 3:52 am
Location: Los Angeles Ca

Post by roostinds »

So I tried the script and I am getting this error message:

&#65279;running lua script len(7161)...lua: startup script error: ([string "startup"]:196.0: unexpected symbol near '+')
done

Any idea what this means? Current script I am using:

setTickRate(25)
initCAN(0, 500000)
CAN_chan = 0

CAN_map = {
[32546816] = function(data)
map_chan(rpmId, data, 0, 2, 0.39063, 0)
map_chan(tpsId, data, 4, 2, 0.0015259, 0)
map_chan(atsId, data, 6, 1, 1, 0)
map_chan(ctsId, data, 7, 1, 1, 0)
end,
[32546820] = function(data)
map_chan(mapId, data, 0, 2, 0.014504 , &#8208;14.6960)
map_chan(fpsId, data, 3, 1, 0.580151, 0)
map_chan(opsId, data, 4, 1, 0.580151, 0)
map_chan(afrId, data, 5, 1, 0.057227, 7.325)
end
}

rpmId = addChannel("RPM", 25, 0, 0, 10000, 'RPM')
tpsId = addChannel("TPS", 10, 1, 0, 100, '%')
atsId = addChannel("IAT", 10, 1, 0, 200, 'C')
ctsId = addChannel("EngineTemp", 10, 1, 0, 200, 'C')
mapId = addChannel("Boost", 10, 1, 0, 935, 'PSI')
fpsId = addChannel("FuelPress", 10, 1, 0, 200, 'PSI')
opsId = addChannel("OilPress", 10, 1, 0, 200, 'PSI')
afrId = addChannel("AFR", 10, 1, 0, 21.9, 'PSI')

function onTick()
processCAN()
end

function processCAN()
repeat
local id, e, data = rxCAN(0)
if id ~= nil then
local map = CAN_map[id]
if map ~= nil then
map(data)
end
end
until id == nil
end

function map_chan(cid, data, offset, len, mult, add)
offset = offset + 1
local value = 0
while len > 0 do
value = (value * 256) + data[offset]
offset = offset + 1
len = len - 1
end
setChannel(cid, (value * mult) + add)
end

madjak
Posts: 29
Joined: Mon Jul 13, 2015 7:40 am

Post by madjak »

Are you sure thats all there is in the script window? I think the 196 is the line number and you should only have 50 lines of code.

make sure that script window is completely clear before you paste in the script.

Post Reply