--This example configured for 06+ S2000 CAN --Virtual channels UNIT_PERC = '%' UNIT_PRESS = "kPa" UNIT_TEMP = 'F' UNIT_VSS = "MPH" MAX_PRESS = 110 MAX_RAW_16 = 65535 MAX_RPM = 9000 MAX_VSS = 150 --chan_id = addChannel(name, sampleRate, precision, min, max, unit) rpm_chan = addChannel("_RPM", 10, 0, 0, MAX_RPM) tps_chan = addChannel("_TPS", 10, 1, 0, 100, UNIT_PERC) ect_chan = addChannel("_ECT", 10, 0, 0, 250, UNIT_TEMP) iat_chan = addChannel("_IAT", 10, 0, 0, 200, UNIT_TEMP) map_chan = addChannel("_MAP", 10, 0, 0, MAX_PRESS, UNIT_PRESS) baro_chan = addChannel("_BARO", 10, 0, 0, MAX_PRESS, UNIT_PRESS) vss_chan = addChannel("_VSS", 10, 0, 0, MAX_VSS, UNIT_VSS) ign_chan = addChannel("_IGN", 10, 0, 0, 50, '*') bat_chan = addChannel("_BAT", 10, 1, 0, 15, 'V') --Convert raw to Fahrenheit function toF(value) --offset by 40 to convert raw to C then *1.8+32 to F return (value * 1.8 + 32) end --Convert raw to RPM function toRPM(value) --only start logging / telemetry if engine is running if value > 500 then startLogging() else stopLogging() end return value end ISOCAN_map = { [0x00] = function(data) can_to_chan(rpm_chan, data, 0x0D, 2, 0.25, 0) end, [0x01] = function(data) can_to_chan(tps_chan, data, 0x0F, 1, 1, 0) end, [0x02] = function(data) can_to_chan(ect_chan, data, 0x13, 1, 1, -40, toF) end, [0x03] = function(data) can_to_chan(iat_chan, data, 0x15, 1, 1, -40, toF) end, [0x04] = function(data) can_to_chan(map_chan, data, 0x17, 1, 1, 0) end, [0x05] = function(data) can_to_chan(baro_chan, data, 0x1A, 1, 1, 0) end, [0x06] = function(data) can_to_chan(vss_chan, data, 0x1B, 1, 1, 0) end, [0x07] = function(data) can_to_chan(ign_chan, data, 0x1E, 1, 1, 0) end, [0x08] = function(data) can_to_chan(bat_chan, data, 0x1F, 1, 0.1, 0) end } LSH_8 = 256 --value * 256 is equal to value << 8 --[[ Callback for processing a CAN packet and storing to a virtual channel vid: Virtual channel id data: CAN packet data pos: Offset to first byte in CAN packet size: Number of bytes in value scalar: Multiplier for the raw to user conversion offset: Adder for the raw to user conversion filter: Optional additional filter or conversion function.]] function can_to_chan(vid, data, pos, size, scalar, offset, filter) local raw_value = 0 --Pack the bytes into a word while size > 0 do raw_value = (raw_value * LSH_8) + data[pos] pos = pos + 1 size = size - 1 end --Convert the word to a user value local user_value = raw_value * scalar + offset --If a filter is present, filter if filter ~= nil then user_value = filter(user_value) end setChannel(vid, user_value) end --[[ Callback for writing and reading ISO CAN packets then processing into virtual channels chan: CAN channel to use for CAN traffic.]] ISO_TXID = 0x18DA10F1 ISO_RXID = 0x18DAF110 ISO_EXT = 1 ISO_22_2610 = { 0x03, 0x22, 0x26, 0x10, 0x55, 0x55, 0x55, 0x55 } ISO_30 = { 0x30, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } function processISO(chan) --setCANfilter(chan, 0, ISO_EXT, 0x18DA0000, 0x1FFF0000) --0x00000008, 0x00FFFFF8) --allows 344,800 --0x01360000, 0x00CFFFF8) --allows 344,800 --0x00000000, 0x00CFFFF8) --allows 344,800 --0x18DA0000, 0x00FFFFF8) --allows 310 --0x18DA0000, 0x00CFFFF8) --allows 310,319 --0x00000000, 0x008FFFF8) --allows 314,344,800 --0x00000000, 0x00800000) --allows 314,344,800 --0x00000000, 0x01800000) --allows 800 --0x00000000, 0x04800000) --allows 344 --0x04800000, 0x04800000) --allows 310,319,380,804,892,1125 --0x01360000, 0x01360000) --allows 310 --0x013A0000, 0x013A0000) --allows 319 --0x013F0000, 0x013F0000) --allows 319 setCANfilter(chan, 0, 1, 0x00000984, 0x000009f8) local result = txCAN(chan, ISO_TXID, ISO_EXT, ISO_22_2610) if result ~= 1 then return end local id, ext, frame repeat id, ext, frame = rxCAN(chan) if id == nil then print('boom1') --return else print('id ' ..id) end until (id == ISO_RXID) println('') print('frame:') for i=1,#frame do print(frame[i] ..' ') end println('') local resp local size = frame[2] print('resp_size=' .. size) local iso_resp = frame[3] print(' iso_resp=' .. iso_resp) if iso_resp ~= 0x62 then return end resp = frame --If there is more than one frame, request all remaining frames be sent if size > 6 then size = size - 6 txCAN(chan, ISO_TXID, ISO_EXT, ISO_30) local seq = 0x21 while size > 0 do repeat id, ext, frame = rxCAN(chan) if id == nil then print('boom2') return end until (id == ISO_RXID) and (frame[1] == seq) seq = seq + 1 for k,v in ipairs(frame) do table.insert(resp, v) end size = size - 7 print(' seq=' .. seq) print(' remaining=' .. size) println('') end end print('resp:') for i=1,#resp do print(resp[i] ..' ') end println('') --for i, func in ipairs(ISOCAN_map) do -- func(resp) --end end CAN_CHAN = 0 --Listen on the CAN1 CAN_BAUD = 500000 -- Listen at 500kbps TICKRATE = 30 --Hz function onTick() processISO(CAN_CHAN) end initCAN(CAN_CHAN, CAN_BAUD) setTickRate(TICKRATE)