Skip to content

Commit 5474f84

Browse files
Merge pull request #94 from ClassicMiniDIY/fix/emerald-channel-ids
fix(emerald): map channel IDs from EM Soft and honor the [ValU] pressure unit — release 2.15.1
2 parents 2cb08ac + 9963af6 commit 5474f84

10 files changed

Lines changed: 429 additions & 40 deletions

File tree

‎CLAUDE.md‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,33 @@ because it also leads with a `Time` column, and only matches a first column of e
504504
by name (lowercased) in `find_gps_channels` (`src/ui/widgets/track_map.rs`); renaming or
505505
suffixing them silently disables the Track Map for MSL logs.
506506

507+
**Emerald parser load-bearing behaviors** (`src/parsers/emerald.rs`):
508+
509+
- **Channel IDs come from EM Soft's variable list, and most are unconfirmed** - the `[chanN]`
510+
value in the `.lg2` is an ID into EM Soft's logger variable list, which Emerald does not
511+
document. Only IDs 1, 15, 20, 24, 26, 31, 32 and 41 are confirmed (issue #93, reporter's EM
512+
Soft labels). The rest are original guesses. ID 1 is the K6 lambda input in mV (not TPS),
513+
41 is TPS, 31 is the 0-15 load site (not injector duty). Confirm an ID against an EM Soft
514+
screenshot before renaming it. A rename must also go into the `source_names` of
515+
`adapters/emerald/emerald-lg.adapter.yaml` in the ClassicMiniDIY/OECUASpecs repo (fetched
516+
by `build.rs` into the gitignored `spec/OECUASpecs/`); spec normalization matches on those
517+
names. Its `internal_id` field documents the IDs but UltraLog does not read it.
518+
- **MAP scaling depends on `[ValU]`** - the second `[ValU]` value is the logger's pressure unit:
519+
`1` stores MAP in whole kPa, `2` in mbar. Hardcoding either one makes the other log read 10x
520+
wrong. Unknown codes keep the mbar scaling.
521+
- **ID 1 is named "Lambda Sensor Voltage" on purpose** - it is a 0-1 V narrowband input where
522+
a higher reading is richer. The `"volt"` veto on `ChannelRole::Lambda` in
523+
`channel_map.rs` depends on that word, so the table generators never map it as lambda.
524+
- **Repeated names get the channel ID appended** - IDs 21/24 and 45/46 share a name, and name
525+
lookups return the first match. `disambiguate_names` keeps the plain name on a
526+
`CONFIRMED_IDS` entry (else the first by slot) and appends ` (ID n)` to the others, so a
527+
formula bound to `Ignition Advance` does not change meaning with slot order.
528+
- **The value column is the slot number, not the list position** - `[chanN]` reads bytes
529+
`8 + (N-1)*2` of the record. `parse_lg2` drops slots outside 1-8 and repeated slots, so an
530+
unreadable or missing `[chanN]` cannot shift later channels onto the wrong data.
531+
- **Ign Adv (ID 24) offset is inferred** - `raw * 0.1 - 50` gives 5.5° at idle and 14-17° at
532+
230 kPa boost. It is not from Emerald documentation.
533+
507534
**Haltech parser load-bearing behaviors** (`src/parsers/haltech.rs`, added for wall-clock-timestamped exports):
508535

509536
- **Last-known-value substitution** - Unparseable/blank fields are filled with the last successfully parsed value for that column (`0.0` before the first valid sample), matching the approach used in `parsers/ecumaster.rs`. This preserves column alignment instead of shifting subsequent columns when a field fails to parse.
@@ -646,7 +673,7 @@ Example log files are in `exampleLogs/` organized by ECU type:
646673
- `exampleLogs/aim/` - AiM XRK/DRK files
647674
- `exampleLogs/link/` - Link ECU LLG files
648675
- `exampleLogs/woolich/` - Woolich Racing Tuned CSV exports
649-
- `exampleLogs/emerald/` - Emerald K6/M3D `.lg1`/`.lg2` files
676+
- `exampleLogs/emerald/` - Emerald K6/M3D `.lg1`/`.lg2` files (`EM Log MG ZS Turbo boost run` is the issue #93 log, `[ValU]` pressure unit kPa; the others use mbar)
650677
- `exampleLogs/megasquirt/` - MegaSquirt TunerStudio CSV exports, plus a `_gps.mlg` fixture with synthetic GPS channels (generated by `examples/inject_fake_gps_mlg.rs`; the coordinates are a fake closed loop, not a real location)
651678
- `exampleLogs/mhd/` - MHD Tuning CSV exports (VIN redacted)
652679
- `exampleLogs/msl/` - TunerStudio MSL excerpt from issue #86 (RealDash logging a Speeduino; trimmed to 2000 data rows, keeping the leading no-GPS-fix rows where `GPS Date`/`GPS Time` are blank)

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ultralog"
3-
version = "2.15.0"
3+
version = "2.15.1"
44
edition = "2024"
55
# egui/eframe 0.36 is the binding constraint on the minimum supported Rust
66
# version; edition 2024 itself only needs 1.85.

‎README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A high-performance, cross-platform ECU log viewer written in Rust.
66

77
![CI](https://github.com/ClassicMiniDIY/UltraLog/actions/workflows/ci.yml/badge.svg)
88
![License](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)
9-
![Version](https://img.shields.io/badge/version-2.15.0-green.svg)
9+
![Version](https://img.shields.io/badge/version-2.15.1-green.svg)
1010

1111
---
1212

@@ -139,7 +139,8 @@ Configurable units for 8 measurement categories:
139139
- **File type:** Binary format (`.lg1` data + `.lg2` channel definitions)
140140
- **Features:** Native binary format parser for Emerald K6/M3D ECUs
141141
- **Supported devices:** Emerald K6, M3D, and compatible ECU models
142-
- **Supported data:** TPS, Air Temp, MAP, Lambda, Oil/Fuel Pressure, Oil/Fuel Temp, Exhaust Temp, Boost Target/Duty, RPM, Coolant Temp, Battery Voltage, Ignition Advance, Injector Pulse Width, and more
142+
- **Supported data:** RPM, TPS, MAP, lambda sensor, ignition advance, injector duration, boost PWM, load site, air and coolant temperature, and more
143+
- **Units:** MAP is shown in kPa. The EM Soft logger pressure setting must be kPa or bar; other settings are not yet supported
143144
- **Note:** Both `.lg1` (data) and `.lg2` (channel definitions) files must be in the same directory
144145

145146
### MegaSquirt / Honda Tuning Studio - Full Support

‎docs/index.html‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@
112112
"applicationCategory": "UtilitiesApplication",
113113
"applicationSubCategory": "Automotive Software",
114114
"operatingSystem": ["Windows 10", "Windows 11", "macOS", "Linux"],
115-
"softwareVersion": "2.15.0",
116-
"releaseNotes": "https://github.com/ClassicMiniDIY/UltraLog/releases/tag/v2.15.0",
115+
"softwareVersion": "2.15.1",
116+
"releaseNotes": "https://github.com/ClassicMiniDIY/UltraLog/releases/tag/v2.15.1",
117117
"downloadUrl": "https://github.com/ClassicMiniDIY/UltraLog/releases/latest",
118118
"installUrl": "https://github.com/ClassicMiniDIY/UltraLog/releases/latest",
119119
"screenshot": [
@@ -1429,7 +1429,7 @@ <h1 id="hero-heading" class="tagline" itemprop="headline">Unlock Your Performanc
14291429
<div class="hero-badges">
14301430
<span class="version-badge">
14311431
<span class="new-tag">New</span>
1432-
v2.15.0
1432+
v2.15.1
14331433
</span>
14341434
<a href="https://github.com/ClassicMiniDIY/UltraLog" class="opensource-badge" target="_blank" rel="noopener noreferrer">
14351435
<i class="fa-brands fa-github" aria-hidden="true"></i> Open Source

‎docs/sitemap.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
44
<url>
55
<loc>https://ultralog.co/</loc>
6-
<lastmod>2026-09-18</lastmod>
6+
<lastmod>2026-09-27</lastmod>
77
<changefreq>weekly</changefreq>
88
<priority>1.0</priority>
99
<image:image>
46.9 KB
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[chan1]
2+
20
3+
[chan2]
4+
41
5+
[chan3]
6+
1
7+
[chan4]
8+
32
9+
[chan5]
10+
24
11+
[chan6]
12+
26
13+
[chan7]
14+
15
15+
[chan8]
16+
31
17+
[ValU]
18+
0
19+
1
20+
0
21+
0
22+
0

‎src/analysis/tables/channel_map.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ impl ChannelRole {
284284
"good",
285285
"ready",
286286
"protect",
287+
// Sensor voltage (Emerald "Lambda Sensor Voltage" is a 0-1 V
288+
// narrowband input): higher reads richer, so it is not lambda.
289+
"volt",
287290
],
288291
Self::LambdaTarget => &[
289292
"error", "airmass", "airflow", "boost", "idle", "rpm", "cam", "angle", "position",
@@ -566,6 +569,10 @@ mod tests {
566569
90
567570
);
568571
assert_eq!(name_score(ChannelRole::Lambda, "Target Lambda", None), 0);
572+
assert_eq!(
573+
name_score(ChannelRole::Lambda, "Lambda Sensor Voltage", None),
574+
0
575+
);
569576
assert!(name_score(ChannelRole::PulseWidth, "Injector 1 On Time", None) >= 40);
570577
assert_eq!(
571578
name_score(ChannelRole::PulseWidth, "Injection Stage 1 Dead Time", None),

0 commit comments

Comments
 (0)