hondavert-dev/lib/core/models/sensor_defs.dart
metatroncubeswdev 6b8d069ef4 O2 in volts, injector duty, Fuel Pump default flag, raw frame log
Checked against the USB tool on the bench (3210 rpm):
- O2: raw x 5/256 V (raw 195 -> 3.81 V, as the USB tool shows).
- New derived sensor: injector duty = INJ ms x RPM / 1200
  (16.67 ms @ 3210 rpm -> 44 %, as the USB tool shows).
- Default dashboard flags: MIL, Fuel Pump, FAN Out, VTEC Out (the
  requirement's "FuelCut" is the fuel pump flag on the S300).
- Log one raw frame (bytes 0-63) every 5 s so USB-tool readings can be
  matched to bytes; INJ, IGN, TPS, MIL, AF and PA still need that check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:47:12 -04:00

137 lines
5.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import '../protocol/sensor_state.dart';
import 'sensor_def.dart';
import 'flag_def.dart';
/// Master list of all analog sensor definitions. Units, ranges and decimals
/// are the base (metric) ones; see units.dart for the displayed unit.
const List<SensorDef> sensorDefs = [
SensorDef(
id: 'rpm', displayName: 'RPM', unit: 'rpm', min: 0, max: 9000, decimals: 0),
SensorDef(
id: 'vss', displayName: 'Speed', unit: 'km/h', min: 0, max: 280, decimals: 0),
SensorDef(
id: 'map', displayName: 'Manifold pressure', unit: 'kPa', min: 0, max: 300),
SensorDef(
id: 'tps', displayName: 'Throttle position', unit: '%', min: 0, max: 100),
SensorDef(
id: 'inj',
displayName: 'Injector duration',
unit: 'ms',
min: 0,
max: 20,
decimals: 2),
SensorDef(
id: 'ign', displayName: 'Timing advance', unit: '°', min: -20, max: 60),
SensorDef(
id: 'ect', displayName: 'Coolant temp', unit: '°C', min: -40, max: 150),
SensorDef(
id: 'iat',
displayName: 'Intake air temp',
unit: '°C',
min: -40,
max: 150),
SensorDef(
id: 'bat', displayName: 'Battery voltage', unit: 'V', min: 0, max: 20),
SensorDef(
id: 'o2', displayName: 'O2 sensor', unit: 'V', min: 0, max: 5, decimals: 2),
// Derived: injector duration × RPM (USB tool: 16.67 ms @ 3210 rpm = 44 %).
SensorDef(
id: 'duty', displayName: 'Injector duty', unit: '%', min: 0, max: 100, decimals: 0),
// AFR/AIN scales not yet bench-verified: shown as raw values.
SensorDef(
id: 'gear', displayName: 'Gear', unit: '', min: 0, max: 6, decimals: 0),
SensorDef(
id: 'eth', displayName: 'Ethanol', unit: '%', min: 0, max: 100, decimals: 0),
SensorDef(
id: 'pa', displayName: 'Barometric pressure', unit: 'kPa', min: 0, max: 120),
SensorDef(
id: 'afr', displayName: 'AFR', unit: 'raw', min: 0, max: 255, decimals: 0),
SensorDef(
id: 'strim', displayName: 'Short trim', unit: '%', min: -30, max: 30),
SensorDef(
id: 'ltrim', displayName: 'Long trim', unit: '%', min: -30, max: 30),
SensorDef(
id: 'ain0', displayName: 'Analog input 0', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain1', displayName: 'Analog input 1', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain2', displayName: 'Analog input 2', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain3', displayName: 'Analog input 3', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain4', displayName: 'Analog input 4', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain5', displayName: 'Analog input 5', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain6', displayName: 'Analog input 6', unit: 'raw', min: 0, max: 1023, decimals: 0),
SensorDef(
id: 'ain7', displayName: 'Analog input 7', unit: 'raw', min: 0, max: 1023, decimals: 0),
];
SensorDef sensorDef(String id) =>
sensorDefs.firstWhere((d) => d.id == id, orElse: () => sensorDefs.first);
/// Base-unit value of sensor [id] in [s].
double sensorValue(SensorState s, String id) {
switch (id) {
case 'rpm': return s.rpm;
case 'vss': return s.vss;
case 'map': return s.map;
case 'tps': return s.tps;
case 'inj': return s.inj;
case 'ign': return s.ign;
case 'ect': return s.ect;
case 'iat': return s.iat;
case 'bat': return s.bat;
case 'o2': return s.o2;
// One injection per 2 revolutions: ms × rpm / 120000 × 100.
case 'duty': return s.inj * s.rpm / 1200;
case 'gear': return s.gear.toDouble();
case 'eth': return s.eth;
case 'pa': return s.pa;
case 'afr': return s.afr;
case 'strim': return s.strim;
case 'ltrim': return s.ltrim;
case 'ain0': return s.ain0;
case 'ain1': return s.ain1;
case 'ain2': return s.ain2;
case 'ain3': return s.ain3;
case 'ain4': return s.ain4;
case 'ain5': return s.ain5;
case 'ain6': return s.ain6;
case 'ain7': return s.ain7;
default: return 0;
}
}
/// Master list of boolean flags (selectable on the dashboard). The first
/// eight follow the requirement document's examples; the rest are the other
/// status bits the ECU frame carries.
final List<FlagDef> flagDefs = [
FlagDef(id: 'mil', displayName: 'MIL', read: (s) => s.mil),
FlagDef(id: 'fanout', displayName: 'FAN Out', read: (s) => s.fanOut),
FlagDef(id: 'vtec', displayName: 'VTEC Out', read: (s) => s.vtec),
FlagDef(id: 'knock', displayName: 'Knock', read: (s) => s.knock),
FlagDef(id: 'o2error', displayName: 'WBO Error', read: (s) => s.o2Error),
FlagDef(id: 'iaterror', displayName: 'IAT Error', read: (s) => s.iatError),
FlagDef(id: 'ecterror', displayName: 'CLT Error', read: (s) => s.ectError),
FlagDef(id: 'fuelpump', displayName: 'Fuel Pump', read: (s) => s.fuelPump),
FlagDef(id: 'revlimit', displayName: 'Rev Limit', read: (s) => s.revLimit),
FlagDef(id: 'igncut', displayName: 'Ign Cut', read: (s) => s.ignCut),
FlagDef(id: 'boostcut', displayName: 'Boost Cut', read: (s) => s.boostCut),
FlagDef(id: 'launch', displayName: 'Launch Cut', read: (s) => s.launch),
FlagDef(
id: 'launchretard',
displayName: 'Launch Retard',
read: (s) => s.launchRetard),
FlagDef(id: 'shiftcut', displayName: 'Shift Cut', read: (s) => s.shiftCut),
FlagDef(
id: 'closedloop', displayName: 'Closed Loop', read: (s) => s.closedLoop),
FlagDef(id: 'vtp', displayName: 'VTEC Press', read: (s) => s.vtp),
FlagDef(id: 'acswitch', displayName: 'AC Switch', read: (s) => s.acSwitch),
FlagDef(id: 'brake', displayName: 'Brake', read: (s) => s.brakeSwitch),
];
FlagDef flagDef(String id) =>
flagDefs.firstWhere((f) => f.id == id, orElse: () => flagDefs.first);