Page 1 of 2

AEM infinity CAN BUS data

Posted: Wed Sep 09, 2015 4:08 am
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‐4 (30‐6XXX) Infinity EMS (30‐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 ‐128 to 127 C 1.8 Deg F/bit 32 ‐198.4 to 260.6 F
7 Coolant Temp 8 bit signed, 2's comp 1 Deg C/bit 0 ‐128 to 127 C 1.8 Deg F/bit 32 ‐198.4 to 260.6 F


ID 1 2 3 4 5 6 7 8
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.

Posted: Wed Sep 09, 2015 7:44 am
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 = { 
  [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
} 
If you still have issues shout out and I can set the base script up for you.

Posted: Wed Sep 09, 2015 7:51 am
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(25)
initCAN(0, 500000)
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: map_chan(var, data, starting byte, byte length, Unit, Offset)
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 
}
	
--=============================== Add Virtual Channels ==========================

--usage: addChannel("Name",samplerate{1,10,25,50,100,200},precision(2),min(0),max(1000),units)
rpmId = addChannel("RPM", 25, 0, 0, 10000, 'RPM')
tpsId = addChannel("TPS", 10, 1, 0, 100, '%')
atsId = addChannel("ATS", 10, 1, 0, 200, 'C')
ctsId = addChannel("CTS", 10, 1, 0, 200, 'C')

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

function onTick()
  processCAN()
end

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

function processCAN() --finds an id that exists then passes it to 
  repeat
    local id, e, data = rxCAN(0)
    if id ~= nil then  -- step through CAN data until you get a value
      local map = CAN_map[id]
      if map ~= nil then
        map(data) --this runs map_chan function with the CAN 'data'
      end
    end
  until id == nil
end

function map_chan(cid, data, offset, len, mult, add) --eg (rpmId, data, 0, 2, 1, 0)
  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

Posted: Wed Sep 09, 2015 7:58 am
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')

Posted: Wed Sep 09, 2015 10:02 pm
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..

Posted: Wed Sep 09, 2015 10:10 pm
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

Posted: Thu Sep 10, 2015 2:38 am
by madjak
close... but should be:

Code: Select all

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(fpsId, data, 3, 1, 0.580151, 0) 
  map_chan(opsId, data, 4, 1, 0.580151, 0) 
end
}
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(data)
  map_chan(FuelPressId, data, 3, 1, 0.580151, 0) 
  map_chan(OilPressId, data, 4, 1, 0.580151, 0) 
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()
  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 
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[id] 
which makes:

Code: Select all

map(data)
  map_chan(FuelPressId, data, 3, 1, 0.580151, 0) 
  map_chan(OilPressId, data, 4, 1, 0.580151, 0) 
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.

Posted: Thu Sep 10, 2015 4:49 am
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!!

Posted: Thu Sep 10, 2015 8:09 am
by madjak
setChannel is the RCP command to map a virtual channel.

eg:
setChannel(rpm, 3000)

Can you post your full script?

Posted: Thu Sep 10, 2015 8:15 am
by madjak
here try this:

Code: Select all

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(fpsId, data, 3, 1, 0.580151, 0) 
  map_chan(opsId, data, 4, 1, 0.580151, 0) 
end 
} 

rpmId = addChannel("RPM", 25, 0, 0, 10000, 'RPM') 
tpsId = addChannel("TPS", 10, 1, 0, 100, '%') 
atsId = addChannel("ATS", 10, 1, 0, 200, 'C') 
ctsId = addChannel("CTS", 10, 1, 0, 200, 'C') 
fpsId = addChannel("FPS", 10, 1, 0, 200, 'PSI') 
opsId = addChannel("OPS", 10, 1, 0, 200, '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
You should see channels called "RPM, TPS, ATS, CTS, FPS and OPS" pop up in the channels list on the RCP dashboard.

Posted: Thu Sep 10, 2015 10:36 pm
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

Posted: Thu Sep 10, 2015 10:47 pm
by brentp
Also, I normalized the channel names - I assumed the channels are:

RPM
TPS
IAT (Inlet Air Temperature)
EngineTemp
FuelPress
OilPress

Thanks again!

Posted: Fri Sep 11, 2015 2:25 am
by madjak
I can't verify it works... I don't have AEM. Just written via the pdf found online.

Posted: Fri Sep 11, 2015 4:41 am
by roostinds
So I tried the script and I am getting this error message:

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 , ‐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

Posted: Fri Sep 11, 2015 4:50 am
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.