Skip to content

Instantly share code, notes, and snippets.

@brentpicasso
Last active January 26, 2020 18:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brentpicasso/982ec5de85066b82c92e to your computer and use it in GitHub Desktop.
Save brentpicasso/982ec5de85066b82c92e to your computer and use it in GitHub Desktop.
E46 expanded channels using 2.8.7 firmware and bitOp library
--This example configured for E46 CAN
-- Automatically starts logging with engine 'on' (RPM triggered)
--how frequently we poll for CAN messages
tickRate = 30
--the CAN baud rate
CAN_baud = 500000
--CAN channel to listen on. 0=first CAN channel, 1=second
CAN_chan = 0
--add your virtual channels here
--format addChannel(<name>, <sample rate>, <precision>, <min>, <max>, [units])
tpsId = addChannel("TPS", 10, 0, 0, 100, "%")
tempId = addChannel("EngineTemp", 1, 0, 0, 255, "F")
oilTempId = addChannel("OilTemp", 1, 0, 0, 255, "F")
rpmId = addChannel("RPM", 10, 0, 0, 10000)
steerId = addChannel("Steering", 10, 0, -360, 360, "Deg.")
brakeId = addChannel("BrakeSw", 10, 0, 0, 1)
brakePressId = addChannel("Brake", 10, 0, 0, 255, "Bar")
clutchId = addChannel("Clutch", 10, 0, 0, 1)
lfWheelId = addChannel("LFWheelSpd", 10, 0, 0, 200, "MPH")
rfWheelId = addChannel("RFWheelSpd", 10, 0, 0, 200, "MPH")
lrWheelId = addChannel("LRWheelSpd", 10, 0, 0, 200, "MPH")
rrWheelId = addChannel("RRWheelSpd", 10, 0, 0, 200, "MPH")
gearTempId = addChannel("GearboxTmp", 10, 0, 0, 400, "F")
fuelId = addChannel("Fuel", 1, 0, 0, 100, "%")
extTempId = addChannel("ExtTemp", 1, 0, 0, 120,"F")
--Convert C to F
function toF(value)
return value * 1.8 + 32
end
--E46 TPS, correct your throttle here for true 100%
function e46_tps(value)
return value + 0.0
end
--only start logging / telemetry if engine is running
function rpmFilter(value)
if value > 500 then startLogging() else stopLogging() end
return value
end
function brakeFilter(value)
return bit.rshift(bit.band(value, 0x10), 4)
end
function clutchFilter(value)
return bit.band(value, 0x01)
end
function processWheel(id, data, offset)
--wheel speed is 13 bits long, little endian
--low byte high byte
--76543210 76543210
--11111111 11111XXX
local highByte = bit.band(data[offset + 2], 0x1F)
local lowByte = data[offset + 1]
local value = highByte * 256 + lowByte
value = value * 0.0625
--convert to MPH. comment to keep KPH
value = value * 0.621371
setChannel(id, value)
end
function processSteering(data)
local steer = 0
if data[2] > 127 then
steer = -1*(((data[2]-128)*256)+data[1])
else
steer = (data[2]*256)+data[1]
end
setChannel(steerId, (steer*0.045))
end
function fuelFilter(value)
--adjust for 7 bit value
value = bit.band(value, 0x7F)
--convert liters to %. tank holds 62.83 liters
return value / 0.6283
end
function extTempFilter(value)
local temp = bit.band(value, 0x7F)
if value > 127 then
temp = -1 * temp
end
temp = toF(temp)
return temp
end
----------------------------------------
--customize here for CAN channel mapping
--format is:
--[CAN Id] = function(data) map_chan(<chan_id>, <data>, <CAN offset>, <CAN length>, <multiplier>,
-- <adder>, [filter])
----------------------------------------
CAN_map = {
[496] = function(data) processWheel(lfWheelId, data, 0)
processWheel(rfWheelId, data, 2)
processWheel(lrWheelId, data, 4)
processWheel(rrWheelId, data, 6)
end,
[339] = function(data) map_chan(brakeId, data, 0, 1, 1, 0, brakeFilter) end,
[504] = function(data) map_chan(brakePressId, data, 2, 1, 1, 0) end,
[809] = function(data) map_chan(tpsId, data, 5, 1 , 0.392156863, 0, e46_tps)
map_chan(tempId, data, 1, 1, 0.75, -48, toF)
map_chan(clutchId, data, 3, 1, 1, 0, clutchFilter)
end,
[1349] = function(data) map_chan(oilTempId, data, 4, 1, 1, -48, toF) end,
[1083] = function(data) map_chan(gearTempId, data, 0, 1, 1, -55, toF) end,
[790] = function(data) map_chan(rpmId, data, 2, 2, 0.15625, 0, rpmFilter) end,
[501] = function (data) processSteering(data) end,
[1555] = function (data) map_chan(fuelId, data, 2, 1, 1, 0, fuelFilter) end,
[1557] = function (data) map_chan(extTempId, data, 3, 1, 1, 0, extTempFilter) end
}
function onTick()
processCAN(CAN_chan)
end
--===========do not edit below===========
function processCAN(chan)
local msg = 0
repeat
local id, e, data = rxCAN(chan, 0)
if id ~= nil then
local map = CAN_map[id]
if map ~= nil then
map(data)
end
end
msg = msg + 1
until id == nil or msg > 100
end
--Map CAN channel, little endian format
function map_chan(cid, data, offset, len, mult, add, filter)
if offset + len > #data then return end
offset = offset + 1
local value = 0
local shift = 1
while len > 0 do
value = value + (data[offset] * shift)
shift = shift * 256
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment