rusEFI ECU support

Any intention to support rusEFI ecu’s?
rusEFI is open source engine managment, works on Tuner Studio like Megasquirt, Speeduino.

Yes, this has been discussed couple of times over the email. I have not got a reply anymore though. Who would be a best candidate to be in contact with to get technical information about the protocol rusEFI uses? It does not seem to work with Megasquirt serial protocol which is used by Megasquirt and Speeduino.

Unfortunately the best answer I have when ask for serial and can bus documentation is: “All the answers are in the source code unfortunately, there is no .pdf or else documentation”
But also: “Fun thin that rusEFI and Speeduino use same TunerStudio serial protocol.”

I check rusefi firmware and I found this on tunerstudio.cpp file:

 * Tuner Studio has a really simple protocol, a minimal implementation
 * capable of displaying current engine state on the gauges would
 * require only two commands: queryCommand and ochGetCommand
 *
 * queryCommand:
 * 		Communication initialization command. TunerStudio sends a single byte H
 * 		ECU response:
 * 			One of the known ECU id strings.
 *
 * ochGetCommand:
 * 		Request for output channels state.TunerStudio sends a single byte O
 * 		ECU response:
 * 			A snapshot of output channels as described in [OutputChannels] section of the .ini file
 * 			The length of this block is 'ochBlockSize' property of the .ini file
 *
 * These two commands are enough to get working gauges.

The .ini file Output Channels (can’t atach .ini file because is 822KiB maximum filesize is 512 KiB):

[OutputChannels]

   ochGetCommand    = "O%2o%2c"

; see TS_OUTPUT_SIZE in console source code
   ochBlockSize     = 340

;
; see TunerStudioOutputChannels struct
;

; Bit flags
	  hasSdCard       = bits,    U32,      0,    [0:0], "true", "false";
	  isIgnitionEnabledIndicator=bits,U32, 0,    [1:1], "true", "false";
	  isInjectionEnabledIndicator=bits,U32,      0,    [2:2], "true", "false";
	  isCylinderCleanupEnabled=bits,U32,   0,    [3:3], "true", "false";
	  isCylinderCleanupActivated=bits,U32, 0,    [4:4], "true", "false";
	  ind_fuel_pump   = bits,    U32,      0,    [5:5], "true", "false";
	  ind_fan         = bits,    U32,      0,    [6:6], "true", "false";
	  ind_o2_heater   = bits,    U32,      0,    [7:7], "true", "false";
      ind_check_engine= bits,    U32,      0,    [8:8], "true", "false";
      needBurn        = bits,    U32,      0,    [9:9], "true", "false";
      clutchUpState    =bits,    U32,      0,  [11:11], "true", "false";
      clutchDownState  =bits,    U32,      0,  [12:12], "true", "false";
      knockEverIndicator=bits,   U32,      0,  [13:13], "true", "false";
      knockNowIndicator=bits,    U32,      0,  [14:14], "true", "false";
      brakePedalIndicator=bits,  U32,      0,  [15:15], "true", "false";
      toothLogReady      =bits,  U32,      0,  [16:16], "true", "false";
      acSwitchState     =bits,   U32,      0,  [17:17], "true", "false";
      isTpsError      = bits,    U32,      0,  [18:18], "true", "false";
      ind_clt_error   = bits,    U32,      0,  [19:19], "true", "false";
; not implemented
;      ind_map_error   = bits,    U32,      0,  [20:20], "true", "false";

      ind_iat_error   = bits,    U32,      0,  [21:21], "true", "false";
      ind_isTriggerError = bits, U32,      0,  [23:23], "true", "false";
      ind_hasFatalError=bits,    U32,      0,  [24:24], "true", "false";
	  ind_isWarnNow    =bits,    U32,      0,  [25:25], "true", "false";
	  ind_pedal_error  =bits,    U32,      0,  [26:26], "true", "false";
	  isTps2Error     = bits,    U32,      0,  [29:29], "true", "false";
	  isIdleClosedLoop= bits,    U32,      0,  [30:30], "true", "false";

; RPM, vss
      RPMValue        = scalar,  U16,      4,      "RPM",    1,   0.00000
      rpmAcceleration = scalar,  S16,      6,     "RPM/s", 1,         0
      speedToRpmRatio = scalar,  S16,      8,    "value",{1/100},         0
      vehicleSpeedKph = scalar,  U08,     10,      "kph",    1,       0.0

; temperatures
     internalMcuTemperature = scalar,S08, 11,    "deg C",    1,         0
      coolant         = scalar,  S16,     12,    "deg C",{1/100},       0.0
      intake          = scalar,  S16,     14,    "deg C",{1/100},       0.0
      auxt1           = scalar,  S16,     16,    "deg C",{1/100},       0.0
      auxt2           = scalar,  S16,     18,    "deg C",{1/100},       0.0
      

; throttle, pedal
      TPSValue        = scalar,  S16,     20,        "%",{1/100},         0
      throttlePedalPosition = scalar,S16, 22,        "%",{1/100},         0
      tpsADC          = scalar,  U16,     24,      "ADC",    1,       0.0;

; air flow/mass measurments
      MAFValue        = scalar,  U16,     26,        "V",{1/1000},         0
      massAirFlowValue= scalar,  U16,     28,     "Kg/h", {1/10},         0
      MAPValue        = scalar,  U16,     30,     "kPa",{1/30},       0.0
      baroPressure    = scalar,  U16,     32,     "kPa",{1/30},       0.0
      lambdaValue     = scalar,  U16,     34,      "",{1/10000},       0.0
      engineLoad      = scalar,  U16,     36,        "%",{1/100},       0.0 ; Blend of MAP and TPS, depends on algorithm

; misc sensors
      VBatt           = scalar,	 U16,     38,        "V",{1/1000},       0.0
      oilPressure     = scalar,  U16,     40,     "kPa",{1/30},       0.0
      vvtPosition     = scalar,  U16,     42,      "deg",{1/50},         0

      ; 10 bit TPS ADC value (from 0 to 1023 in 5v scale)
      ;tpsADC2         = scalar,  U16,    44,             "ADC",            1,       0.0;

; fuel math
      chargeAirMass   = scalar,  U16,     44,        "g",0.001,         0
      crankingFuelMs  = scalar,  U16,     46,     "mg",{1/100},     0.0
      currentTargetAfr= scalar,  U16,     48,    "ratio",{1/1000},         0
      baseFuel        = scalar,  U16,     50,     "mg",{1/100},       0
      fuelRunning     = scalar,  U16,     52,     "mg",{1/100},       0
      actualLastInjection=scalar,U16,     54,     "ms",{1/300},     0.0
      injectorDutyCycle=scalar,  U08,     56,        "%",  0.5,         0
      veValue         = scalar,  U08,     57,    "ratio",  0.5,         0
      injectionOffset = scalar,  S16,     58,      "deg",{1/50},         0
      tCharge         = scalar,  U16,     60,    "deg C",{1/100},       0.0

; Corrections
      injectorLagMs   = scalar,  U16,     62,     "ms",{1/300},       0.0
      iatCorrection   = scalar,  S16,     64,        "%",{1/100},         0
      cltCorrection   = scalar,  S16,     66,        "%",{1/100},         0
      baroCorrection  = scalar,  S16,     68,        "%",{1/100},         0
      fuelPidCorrection=scalar,  S16,     70,       "%",{1/100},         0

; Wall model AE
      wallFuelAmount  = scalar,  U16,     72,     "ms",{1/300},         0
      wallFuelCorrection=scalar, S16,     74,       "ms",0.001,         0

; TPS/load AE
      engineLoadDelta = scalar,  S16,     76,    "value",{1/100},         0
      deltaTps        = scalar,  S16,     78,    "ratio",{1/100},         0
      engineLoadAccelExtra=scalar,S16,    80,    "value",{1/100},         0
      tpsAccelFuel    = scalar,  U16,     82,     "ms",{1/300},         0

; Ignition
      ignitionAdvance = scalar,  S16,     84,    "deg",{1/50},       0.0
      sparkDwellValue = scalar,  U16,     86,     "ms",{1/300},       0.0
      coilDutyCycle   = scalar,  S16,     88,      "%",{1/100},         0

; Idle & ETB
      idleAirValvePosition=scalar,S16,    90,      "%",{1/100},         0
      etbTarget       = scalar,  S16,     92,      "%",{1/100},         0
      etb1DutyCycle   = scalar,  S16,     94,      "%",{1/100},         0
      etb1Error       = scalar,  S16,     96,      "%",{1/100},         0

; Fuel system
      fuelTankLevel   = scalar,  U16,     98,      "%",{1/100},         0
      totalFuelConsumption=scalar,U16,   100,  "grams",                        1,         0
      fuelFlowRate    = scalar,  U16,    102, "gram/s",{1/200},         0

; Y axis values for selectable tables
      veTableYAxis    = scalar, U16,     104,      "%",     0.01, 0
      afrTableYAxis   = scalar, U16,     106,      "%",     0.01, 0

; Knock
      knockLevel      = scalar,  F32,    108,  "Volts",      1,         0

; Mode, firmware, protocol, run time
; TS requires 'seconds' name since it has special internal meaning
      seconds         = scalar,  U32,    112,    "sec",      1,       0.0
      engineMode      = scalar,  U32,    116,     "em",      1,       0.0;
      firmwareVersion = scalar,  U32,    120,"version_f",    1,         0


; calibation helpers
      calibrationValue = scalar, F32, 128, "", 1, 0
      calibrationMode = scalar, U08, 132, "", 1, 0
      ; 1 bytes padding1

      fuelingLoad     = scalar, U16,     134,      "%",     0.01, 0
      ignitionLoad    = scalar, U16,     136,      "%",     0.01, 0

      engineMakeCodeNameCrc16= scalar,  U16,    138,  "crc16",           1,         0

; Errors
      totalTriggerErrorCounter=scalar,U32,   140,"counter",           1,         0
      ; orderingErrorCounter 144
      warningCounter  = scalar,  U16,    148,  "count",           1,         0
      lastErrorCode   = scalar,  U16,    150,  "error",           1,         0
      recentErrorCode0= scalar,  U16,    152,  "error",           1,         0
      recentErrorCode1= scalar,  U16,    154,  "error",           1,         0
      recentErrorCode2= scalar,  U16,    156,  "error",           1,         0
      recentErrorCode3= scalar,  U16,    158,  "error",           1,         0
      recentErrorCode4= scalar,  U16,    160,  "error",           1,         0
      recentErrorCode5= scalar,  U16,    162,  "error",           1,         0
      recentErrorCode6= scalar,  U16,    164,  "error",           1,         0
      recentErrorCode7= scalar,  U16,    166,  "error",           1,         0

; Debug
      debugFloatField1= scalar,  F32,    168,    "val",           1,       0.0
      debugFloatField2= scalar,  F32,    172,    "val",           1,       0.0
      debugFloatField3= scalar,  F32,    176,    "val",           1,       0.0
      debugFloatField4= scalar,  F32,    180,    "val",           1,       0.0
      debugFloatField5= scalar,  F32,    184,    "val",           1,       0.0
      debugFloatField6= scalar,  F32,    188,    "val",           1,       0.0
      debugFloatField7= scalar,  F32,    192,    "val",           1,       0.0
      debugIntField1  = scalar,  S32,    196,    "val",           1,       0.0
      debugIntField2  = scalar,  S32,    200,    "val",           1,       0.0
      debugIntField3  = scalar,  S32,    204,    "val",           1,       0.0
      debugIntField4  = scalar,  S16,    208,    "val",           1,       0.0
      debugIntField5  = scalar,  S16,    210,    "val",           1,       0.0

; Accel
      accelerationX   = scalar,  S16,    212,      "G",        0.01,         0
      accelerationY   = scalar,  S16,    214,      "G",        0.01,         0

; egt
      egt1            = scalar,  S16,    216,  "deg C",      1,         0
      egt2            = scalar,  S16,    218,  "deg C",      1,         0
      egt3            = scalar,  S16,    220,  "deg C",      1,         0
      egt4            = scalar,  S16,    222,  "deg C",      1,         0
      egt5            = scalar,  S16,    224,  "deg C",      1,         0
      egt6            = scalar,  S16,    226,  "deg C",      1,         0
      egt7            = scalar,  S16,    228,  "deg C",      1,         0
      egt8            = scalar,  S16,    230,  "deg C",      1,         0

      TPS2Value       = scalar,  S16,    232,        "%",{1/100},         0

      rawTps1Primary  = scalar,	 U16,    234, "V",{1/1000}, 0.0
      rawPpsPrimary   = scalar,	 U16,    236, "V",{1/1000}, 0.0
      rawClt          = scalar,	 U16,    238, "V",{1/1000}, 0.0
      rawIat          = scalar,	 U16,    240, "V",{1/1000}, 0.0
      rawOilPressure  = scalar,	 U16,    242, "V",{1/1000}, 0.0
      rawPpsSecondary = scalar,	 U16,    248, "V",{1/1000}, 0.0

	; we use this to match logs to tunes
	tuneCrc16         = scalar,  U16,    244, "crc16",           1,         0
    sd_status         = scalar,  U08,    246,  "", 1.0, 0.0

; Transmission
      tcuCurrentGear  = scalar,  S08,     247,   "gear",    1,         0
      tcuDesiredGear  = scalar,  S08,     262,   "gear",    1,         0

	knock1 = scalar, S08, 250, "dbv", 1, 0
	knock2 = scalar, S08, 251, "dbv", 1, 0
	knock3 = scalar, S08, 252, "dbv", 1, 0
	knock4 = scalar, S08, 253, "dbv", 1, 0
	knock5 = scalar, S08, 254, "dbv", 1, 0
	knock6 = scalar, S08, 255, "dbv", 1, 0
	knock7 = scalar, S08, 256, "dbv", 1, 0
	knock8 = scalar, S08, 257, "dbv", 1, 0
    knock9 = scalar, S08, 258, "dbv", 1, 0
    knock10 = scalar,S08, 259, "dbv", 1, 0
    knock11 = scalar,S08, 260, "dbv", 1, 0
    knock12 = scalar,S08, 261, "dbv", 1, 0

	flexPercent = scalar, U08, 263, "%", 0.5, 0

	rawIdlePositionSensor = scalar,	 U16,    264, "V",{1/1000}, 0.0
	rawWastegatePosition  = scalar,	 U16,    266, "V",{1/1000}, 0.0
	wastegatePositionSensor = scalar,  S16,    268, "%",{1/100}, 0
	idlePositionSensor    = scalar,  S16,    270, "%",{1/100}, 0
	rawLowFuelPressure    = scalar,  U16,     272, "V",{1/1000}, 0
	rawHighFuelPressure   = scalar,  U16,     274, "V",{1/1000}, 0
	lowFuelPressure       = scalar,  S16,     276, "kpa", {1/30}, 0
	highFuelPressure      = scalar,  S16,     278, "bar", {1/10}, 0
	targetLambda     = scalar,  U16,     280,      "",{1/10000},       0.0
	AFRValue        = scalar,  U16,     282,      "AFR",{1/1000},       0.0
	VssAcceleration = scalar,  S16,     284,      "m/s2", {1/300}, 0.0
	lambdaValue2    = scalar,  U16,     286,      "",{1/10000},       0.0
	AFRValue2       = scalar,  U16,     288,      "AFR",{1/1000},       0.0

;
; see TunerStudioOutputChannels struct
;

; todo: generate this section programmatically
	LM_SPEED_DENSITY = {3},
	LM_REAL_MAF = {4}

      egoCorrection   = { 100 }
      time            = { timeNow }

	; These "synthetic" channels provide the Y-axis (load) value for gen purp PWM table's Y axes
	gppwm1_load = {(gppwm1_loadAxis == 0) ? TPSValue : ((gppwm1_loadAxis == 1) ? MAPValue : ((gppwm1_loadAxis == 2) ? coolant : ((gppwm1_loadAxis == 3) ? intake : ((gppwm1_loadAxis == 4) ? fuelingLoad : ignitionLoad))))}
	gppwm2_load = {(gppwm2_loadAxis == 0) ? TPSValue : ((gppwm2_loadAxis == 1) ? MAPValue : ((gppwm2_loadAxis == 2) ? coolant : ((gppwm2_loadAxis == 3) ? intake : ((gppwm2_loadAxis == 4) ? fuelingLoad : ignitionLoad))))}
	gppwm3_load = {(gppwm3_loadAxis == 0) ? TPSValue : ((gppwm3_loadAxis == 1) ? MAPValue : ((gppwm3_loadAxis == 2) ? coolant : ((gppwm3_loadAxis == 3) ? intake : ((gppwm3_loadAxis == 4) ? fuelingLoad : ignitionLoad))))}
	gppwm4_load = {(gppwm4_loadAxis == 0) ? TPSValue : ((gppwm4_loadAxis == 1) ? MAPValue : ((gppwm4_loadAxis == 2) ? coolant : ((gppwm4_loadAxis == 3) ? intake : ((gppwm4_loadAxis == 4) ? fuelingLoad : ignitionLoad))))}

Also atach a tunerstudio_outputs.h file
Is this enough for implement rusEFI support?
Thanks.
tunerstudio.cpp (27.6 KB)
tunerstudio_outputs.h (9.26 KB)

I will take a look. I do need help on testing though as we do not have a test device.

I ordered a board to start some test.

Great! Drop me an email and I will share direct link to test version.

Hi I test the update but RealDash don’t connect with rusefi, after sniff alot in the serial connection with tuner studio, I found the message I need to send to rusefi to get the data. (need to send: 0 5 O 0 0 133 0 Z u T 139)
This is the code I use with arduino to get the data maybe this help.

const int BUFFER_SIZE = 140;
byte gauges[BUFFER_SIZE];
int Flags1;
int Flags2;
int Flags3;
int Flags4;

bool hasSdCard;
bool isIgnitionEnabledIndicator;
bool isInjectionEnabledIndicator;
bool isCylinderCleanupEnabled;
bool isCylinderCleanupActivated;
bool isFuelPumpOn;
bool isFanOn;
bool isO2HeaterOn;
bool checkEngine;
bool needBurn;
bool unusedBit10;
bool clutchUpState;
bool clutchDownState;
bool knockEverIndicator;
bool knockNowIndicator;
bool brakePedalState;
bool toothLogReady;
bool acSwitchState;
bool isTpsError;
bool isCltError;
bool isMapError;
bool isIatError;
bool unusedAt22;
bool isTriggerError;
bool hasCriticalError;
bool isWarnNow;
bool isPedalError;
bool isKnockChipOk;
bool launchTriggered;
bool isTps2Error;
bool isIdleClosedLoop;

// RPM, vss
uint16_t RPM;
int16_t rpmAcceleration;
float speedToRpmRatio;
int vehicleSpeedKph;

// temperatures
int8_t internalMcuTemperature;
float coolantTemperature;
float intakeAirTemperature;
int16_t auxTemp1;
float auxTemp1_1;
int16_t auxTemp2;
float auxTemp2_1;

// throttle, pedal
float throttlePosition;
float pedalPosition;
unsigned tpsADC;

// air flow/mass measurment
float massAirFlowVoltage;
float massAirFlow;
int manifoldAirPressure;
int baroPressure;
float lambda;
float engineLoad;

// misc sensors
float vBatt;
int oilPressure;
int vvtPosition;

// Fuel math
float chargeAirMass;
float crankingFuelMass;
float currentTargetAfr;
float fuelBase;
float fuelRunning;
float actualLastInjection;
float injectorDutyCycle;
float veValue;
float injectionOffset;
float tCharge;

// Corrections
float injectorLagMs;
float iatCorrection;
float cltCorrection;
float baroCorrection;
float shortTermFuelTrim;

// Wall model AE
float wallFuelAmount;
float wallFuelCorrection;

// TPS/load AE
float engineLoadDelta;
float deltaTps;
float engineLoadAccelExtra;
float tpsAccelFuel;

// Ignition
float ignitionAdvance;
float sparkDwell;
float coilDutyCycle;

// Idle & ETB
float idlePosition;
float etbTarget;
float etb1DutyCycle;
float etb1Error;

// Fuel system
float fuelTankLevel;
int totalFuelConsumption;
float fuelFlowRate;

// Knock
float knockLevel;

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
}

void loop() {

  Serial1.write(0);
  Serial1.write(5);
  Serial1.write("O");
  Serial1.write(0);
  Serial1.write(0);
  Serial1.write(133);
  Serial1.write(0);
  Serial1.write("Z");
  Serial1.write("u");
  Serial1.write("T");
  Serial1.write(139);

  while (Serial1.available() > 0) {
    // read the incoming bytes:
    Serial1.readBytes(gauges, BUFFER_SIZE);

    // prints the received data
    //for(int i = 0; i < BUFFER_SIZE; i++)
    //Serial.print(gauges[i]);
  }
  delay(5);
  Flags1 = gauges[3];
  Flags2 = gauges[4];
  Flags3 = gauges[5];
  Flags4 = gauges[6];

  hasSdCard = bitRead(Flags1, 0);
  isIgnitionEnabledIndicator = bitRead(Flags1, 1);
  isInjectionEnabledIndicator = bitRead(Flags1, 2);
  isCylinderCleanupEnabled = bitRead(Flags1, 3);
  isCylinderCleanupActivated = bitRead(Flags1, 4);
  isFuelPumpOn = bitRead(Flags1, 5);
  isFanOn = bitRead(Flags1, 6);
  isO2HeaterOn = bitRead(Flags1, 7);
  checkEngine = bitRead(Flags2, 0);
  needBurn = bitRead(Flags2, 1);
  unusedBit10 = bitRead(Flags2, 2);
  clutchUpState = bitRead(Flags2, 3);
  clutchDownState = bitRead(Flags2, 4);
  knockEverIndicator = bitRead(Flags2, 5);
  knockNowIndicator = bitRead(Flags2, 6);
  brakePedalState = bitRead(Flags2, 7);
  toothLogReady = bitRead(Flags3, 0);
  acSwitchState = bitRead(Flags3, 1);
  isTpsError = bitRead(Flags3, 2);
  isCltError = bitRead(Flags3, 3);
  isMapError = bitRead(Flags3, 4);
  isIatError = bitRead(Flags3, 5);
  unusedAt22 = bitRead(Flags3, 6);
  isTriggerError = bitRead(Flags3, 7);
  hasCriticalError = bitRead(Flags4, 0);
  isWarnNow = bitRead(Flags4, 1);
  isPedalError = bitRead(Flags4, 2);
  isKnockChipOk = bitRead(Flags4, 3);
  launchTriggered = bitRead(Flags4, 4);
  isTps2Error = bitRead(Flags4, 5);
  isIdleClosedLoop = bitRead(Flags4, 6);

  // RPM, vss
  RPM = gauges[8] << 8 | gauges[7];

  rpmAcceleration = gauges[10] << 8 | gauges[9];

  speedToRpmRatio = gauges[12] << 8 | gauges[11];
  speedToRpmRatio = speedToRpmRatio / 100;

  vehicleSpeedKph = gauges[13];

  // temperatures
  internalMcuTemperature = gauges[14];

  coolantTemperature = gauges[16] << 8 | gauges[15];
  coolantTemperature = coolantTemperature / 100;

  intakeAirTemperature = gauges[18] << 8 | gauges[17];
  intakeAirTemperature = intakeAirTemperature / 100;

  auxTemp1 = gauges[20] << 8 | gauges[19];
  //auxTemp1 = auxTemp1/100;
  auxTemp1_1 = auxTemp1;
  auxTemp1_1 = auxTemp1_1 / 100;

  auxTemp2 = gauges[22] << 8 | gauges[21];
  auxTemp2_1 = auxTemp2;
  auxTemp2_1 = auxTemp2_1 / 100;

  // throttle, pedal
  throttlePosition = gauges[24] << 8 | gauges[23];
  throttlePosition = throttlePosition / 100;

  pedalPosition = gauges[26] << 8 | gauges[25];
  pedalPosition = pedalPosition / 100;

  tpsADC = gauges[28] << 8 | gauges[27];

  // air flow/mass measurment
  massAirFlowVoltage = gauges[30] << 8 | gauges[29];
  massAirFlowVoltage = massAirFlowVoltage / 1000;

  massAirFlow = gauges[32] << 8 | gauges[31];
  massAirFlow = massAirFlow / 10;

  manifoldAirPressure = gauges[34] << 8 | gauges[33];
  manifoldAirPressure = manifoldAirPressure / 30;

  baroPressure = gauges[36] << 8 | gauges[35];
  baroPressure = baroPressure / 30;

  lambda = gauges[38] << 8 | gauges[37];
  lambda = lambda / 10000;

  engineLoad = gauges[40] << 8 | gauges[39];
  engineLoad = engineLoad / 100;

  // misc sensors
  vBatt = gauges[42] << 8 | gauges[41];
  vBatt = vBatt / 1000;

  oilPressure = gauges[44] << 8 | gauges[43];
  oilPressure = oilPressure / 30;

  vvtPosition = gauges[46] << 8 | gauges[45];
  vvtPosition = vvtPosition / 50;

  //tpsADC2 = gauges[48] << 8 | gauges[47];

  // Fuel math
  chargeAirMass = gauges[48] << 8 | gauges[47];
  chargeAirMass = chargeAirMass / 1000;

  crankingFuelMass = gauges[50] << 8 | gauges[49];
  crankingFuelMass = crankingFuelMass / 100;

  currentTargetAfr = gauges[52] << 8 | gauges[51];
  currentTargetAfr = currentTargetAfr / 1000;

  fuelBase = gauges[54] << 8 | gauges[53];
  fuelBase = fuelBase / 100;

  fuelRunning = gauges[56] << 8 | gauges[55];
  fuelRunning = fuelRunning / 100;

  actualLastInjection = gauges[58] << 8 | gauges[57];
  actualLastInjection = actualLastInjection / 300;

  injectorDutyCycle = gauges[59];
  injectorDutyCycle = injectorDutyCycle / 2;

  veValue = gauges[60];
  veValue = veValue / 2;

  injectionOffset = gauges[62] << 8 | gauges[61];
  injectionOffset = injectionOffset / 50;

  tCharge = gauges[64] << 8 | gauges[63];
  tCharge = tCharge / 100;

  // Corrections
  injectorLagMs = gauges[66] << 8 | gauges[65];
  injectorLagMs = injectorLagMs / 300;

  iatCorrection = gauges[68] << 8 | gauges[67];
  iatCorrection = iatCorrection / 100;

  cltCorrection = gauges[70] << 8 | gauges[69];
  cltCorrection = cltCorrection / 100;

  baroCorrection = gauges[72] << 8 | gauges[71];
  baroCorrection = baroCorrection / 100;

  shortTermFuelTrim = gauges[74] << 8 | gauges[73];
  shortTermFuelTrim = shortTermFuelTrim / 100;

  // Wall model AE
  wallFuelAmount = gauges[76] << 8 | gauges[75];
  wallFuelAmount = wallFuelAmount/300;
  
  wallFuelCorrection = gauges[78] << 8 | gauges[77];
  wallFuelCorrection = wallFuelCorrection/1000;

  // TPS/load AE
  engineLoadDelta = gauges[80] << 8 | gauges[79];
  engineLoadDelta = engineLoadDelta/100;
  
  deltaTps = gauges[82] << 8 | gauges[81];
  deltaTps = deltaTps/100;
  
  engineLoadAccelExtra = gauges[84] << 8 | gauges[83];
  engineLoadAccelExtra = engineLoadAccelExtra/100;
  
  tpsAccelFuel = gauges[86] << 8 | gauges[85];
  tpsAccelFuel = tpsAccelFuel/300;

  // Ignition
  ignitionAdvance = gauges[88] << 8 | gauges[87];
  ignitionAdvance = ignitionAdvance/50;
  
  sparkDwell = gauges[90] << 8 | gauges[89];
  sparkDwell = sparkDwell/300;
  
  coilDutyCycle = gauges[92] << 8 | gauges[91];
  coilDutyCycle = coilDutyCycle/100;

  // Idle & ETB
  idlePosition = gauges[94] << 8 | gauges[93];
  idlePosition = idlePosition/100;
  
  etbTarget = gauges[96] << 8 | gauges[95];
  etbTarget = etbTarget/100;
  
  etb1DutyCycle = gauges[98] << 8 | gauges[97];
  etb1DutyCycle = etb1DutyCycle/100;
  
  etb1Error = gauges[100] << 8 | gauges[99];
  etb1Error = etb1Error/100;

  // Fuel system
  fuelTankLevel = gauges[102] << 8 | gauges[101];
  fuelTankLevel = fuelTankLevel / 100;

  totalFuelConsumption = gauges[104] << 8 | gauges[103];

  fuelFlowRate = gauges[106] << 8 | gauges[105];
  fuelFlowRate = fuelFlowRate / 200;

  // Knock
  knockLevel = gauges[114] << 24 | gauges[113] <<16 | gauges[112] <<8 | gauges[111];

  Serial.println(RPM);
}

Thanks for the code snippet. We have target to get rusEFI support working for next release of RealDash.

Thanks for the support.

This implementation is now on 1.9.5-beta1. Any testing help from rusEFI users is appreciated.

http://realdash.net/forum/viewtopic.php?f=2&t=1318&sid=431627d637a474a994cc7727b3cc137a

Hi, Now I have connection with rusefi ECU now, I test only a few sensors because Ecu still on bench, once is installed on my engine I can make more extensive test.

Thanks for the support.

Test Video:

Hi, I update my ECU to latest firmware, RealDash connect but data is incorrect now. I check the code and I found Output channels block size change from 340 to 640.
I atach file with new Output channels block.
I hope you can update rusEFI support.
Thanks.
tunerstudio_outputs.h (1 KB)

Please link the documentation of new output channels. The header file that you attached does not seem to contain anything useful.

Sorry for late response but this week was very busy, I connect real dash with my ECU and the data is correct, I don’t now what happens the other day. (all gauges are incorrect pairing).
The only think don’t work is speed, I recently add vss input to my ecu and in tuner studio speed it’s fine but don’t work in RealDash. It’s possible you share the *.ini file for rusefi to check what can be wrong.
Thanks for the support.

Hello :slight_smile: My name is Andrey and I am the rusEFI founder.

rusEFI firmware is changing rapidly and the array of data points we expose is changing pretty often - any snapshot of datapoints is not a frozen public API. The proper way is to request specific firmware signature from the unit via HELLO command, lookup corresponding .ini file from the internet at https://rusefi.com/online/ini/rusefi/2022/ and parse the .ini file to get the gauges specifically for this firmware dynamically

good news I have the java code for most of the steps here I am happy to share or make minimal bundle

good news I am happy to commit to some data point names being “public api” (names, not offsets)

please let me know if you have time and desire to look into this and I am happy to provide more details

before chip shortage stm32f407discovery was a $20 piece of real stm32 running real rusEFI firmware

also a reminder that we have rusefi_simulator.exe build from rusefi/simulator at master · rusefi/rusefi · GitHub Windows binary available inside https://rusefi.com/build_server/rusefi_bundle.zip and that simulator runnig on win/linux/mac would expose real rusEFI protocol via TCP/IP

Welcome to the forums. I will take a look at this in near future.

Any news?

Sorry for the delay. Today I tried the simulator and I do get 1200 RPM from it, anything else is more or less 0 values. I can also read two error codes from the simulator.

In current parser, its sending the 11 byte data request and waiting for block of at least 140 bytes to parse. Is there a problem with that approach? Do you have documentation of the current data block ECU sends after the 11 byte data request? If not, please send it to my email in order to update this.

right, with simulator you mostly get the 1200 RPM maybe also time since reboot and not much else

yes, 11 byte data request and your requests actually contains offset and size of output region you are requesting, right? At the moment region size is limited at 500, so if you request 140 portion of the overall outputs you should totally get 140 back

https://github.com/rusefi/rusefi/blob/b449e85bae43611f8b0c5dfe363f46ab25ca63d8/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java#L573 would be out own java client showing how it currently gets the 1204 bytes of data as three chunks

the drama is the fact that any day 1204 could become 1250 or 1200 and you have to download and parse the corresponding ini from https://rusefi.com/online/ini/rusefi/2022/ folder