GeneralPUBLIC

BEAN ↔ CAN || CAN ↔ BEAN Mapping Design Guide

Explain, step by step, how to design mappings in the graphical editors, how every source type works, how to choose selectors, how to use expressions and helper functions, how to calculate scaling, and how to validate the resulting physical traffic safely.

formulascanbeanmpxmappingguidebean2cancan2beaneditortutorial

BEAN ↔ CAN || CAN ↔ BEAN Mapping Design Guide — Expanded Engineering Edition

Document revision: 2.0 Date: 2026-09-21 Language: English Applies to: BEANalyzer UltraPro 5 BEAN → CAN format: BEANalyzer_Gateway_Mapping, version 3 CAN → BEAN format: BEANalyzer_CAN_to_BEAN_Mapping, version 1 Current UI terminology: CAN Interface Purpose: Explain, step by step, how to design mappings in the graphical editors, how every source type works, how to choose selectors, how to use expressions and helper functions, how to calculate scaling, and how to validate the resulting physical traffic safely.


1. Read this first

The Mapping editors are not simple “copy byte A to byte B” tools.

They are small protocol translators.

A correct Mapping describes:

WHAT source message is allowed to enter
        ↓
WHAT source value is used
        ↓
HOW that value is transformed
        ↓
WHERE the transformed value is placed
        ↓
WHEN the output is transmitted
        ↓
WHAT happens if the source stops updating

The best way to design a Mapping is to write those six answers down before touching the editor.

A Mapping that works by accident is difficult to maintain.

A Mapping that can be explained as:

“Match this exact source message, extract this field, convert it with this formula, put it into these exact destination bits, and transmit it with this timing policy”

is reproducible engineering.


2. The two directions are intentionally separate

BEANalyzer has two independent Mapping editors.

BEAN → CAN

Open:

Devices / CAN Gateway
    ↓
BEAN → CAN Mapping
    ↓
Open BEAN → CAN Mapping Editor...

This editor receives Toyota/Lexus BEAN information and builds one or more Classic CAN frames.

CAN → BEAN

Open:

Devices / CAN Gateway
    ↓
CAN → BEAN Mapping
    ↓
Open CAN → BEAN Mapping Editor...

This editor receives Classic CAN frames and builds BEAN application messages.

The CAN → BEAN editor does not ask you to construct a complete captured BEAN electrical frame.

It produces:

DID + MID + DATA

The BEAN bridge owns the link layer.


3. Mental model

BEAN → CAN

BEAN RX
  ↓
Message tab
BEAN match / source selector
  ↓
Payload Fields
  ↓
Source
  ↓
Encoding
  ↓
CAN destination bits
  ↓
Transmit policy
  ↓
CAN Interface
  ↓
physical CAN

CAN → BEAN

CAN RX
  ↓
Message tab
CAN match / source selector
  ↓
Payload Fields
  ↓
Source
  ↓
Encoding
  ↓
BEAN DATA destination bits
  ↓
Transmit policy
  ↓
BEAN bridge
  ↓
physical BEAN

4. Raw values versus physical values

This is the most important distinction in the entire Mapping system.

Consider coolant temperature.

Current project decoding:

coolant_temp = raw / 2

If BEAN DATA contains:

6B

then:

0x6B = 107 decimal
107 / 2 = 53.5 °C

Two different Mapping designs are possible.

Raw-preserving Mapping

source = raw byte 0x6B
scale  = 1
offset = 0
output = 0x6B

Physical-value Mapping

source = decoded coolant_temp = 53.5
scale  = 0.5
offset = 0
output = round(53.5 / 0.5)
       = 107
       = 0x6B

Both are correct if intentional.

The mistake is to mix the two models.


5. Encoding formula

Both Mapping directions use the same destination encoding rule:

destination_raw = round((source_value - offset) / scale)

This means:

Exact copy

scale  = 1
offset = 0

Physical value of 0.5 units per bit

scale = 0.5

Example:

physical = 53.5
raw = 53.5 / 0.5
    = 107

Physical value using an offset

Suppose:

physical = raw - 48

Rearrange:

raw = physical + 48

In BEANalyzer:

scale  = 1
offset = -48

because:

raw = (physical - (-48)) / 1
    = physical + 48

6. Destination bit numbering

BEANalyzer uses linear LSB0 destination bit numbering.

Byte 0 = bits  0..7
Byte 1 = bits  8..15
Byte 2 = bits 16..23
Byte 3 = bits 24..31
Byte 4 = bits 32..39
Byte 5 = bits 40..47
Byte 6 = bits 48..55
Byte 7 = bits 56..63

Therefore:

first complete byte  → start_bit 0
second complete byte → start_bit 8
third complete byte  → start_bit 16
fourth complete byte → start_bit 24

Do not use:

start_bit = 9

when you mean “second byte”.

9 means:

Byte 1, bit 1

7. Signed fields

If Signed is disabled, a field of N bits accepts:

0 .. (2^N - 1)

Examples:

8-bit unsigned  = 0..255
16-bit unsigned = 0..65535

If Signed is enabled, the accepted range is:

-(2^(N-1)) .. +(2^(N-1)-1)

Examples:

8-bit signed  = -128..127
16-bit signed = -32768..32767

Negative signed values are packed using two’s-complement representation.

Example:

-1 in signed 8-bit = 0xFF

8. Endianness

Single-byte fields are straightforward.

Multi-byte fields need careful byte order.

Example:

raw = 0x3C00

Big Endian:

3C 00

Little Endian:

00 3C

In the current Mapping implementation, Big Endian fields wider than 8 bits must be byte-aligned.

Examples of valid Big Endian destinations:

start_bit = 0,  length = 16
start_bit = 8,  length = 16
start_bit = 16, length = 32

Example of an invalid Big Endian multi-byte destination:

start_bit = 3
length    = 16

PART I — BEAN → CAN

9. Creating a new BEAN → CAN Mapping

Open:

Devices / CAN Gateway
    ↓
BEAN → CAN Mapping
    ↓
Open BEAN → CAN Mapping Editor...

Press:

New document

The left side of the editor is:

CAN messages / mappings

Each item in this list represents one outgoing CAN message definition.

Press:

Add

to create a new CAN message Mapping.


10. BEAN → CAN: Message tab

Select the Mapping on the left, then open:

Message

The tab contains four important groups:

Mapping identity
BEAN match / source selector
Transmit policy
Stale-source policy
CAN output frame

11. Mapping identity

Go to:

Message
    ↓
Mapping identity

Set:

Name
Enabled
Notes

Example:

Name:
IS200 Powertrain Summary

Enabled:
YES

Notes:
Packs outside temperature, coolant, vehicle speed and RPM into CAN 0x500.

During initial development, it is reasonable to leave:

Enabled = NO

until Preview / Test is correct.


12. BEAN match / source selector

Go to:

Message
    ↓
BEAN match / source selector

You will see:

CTX
DID
MID
Required DATA length

These are selectors.

They determine which BEAN messages are considered matching input for this Mapping.

They are not automatically copied into the CAN payload.


13. How to use CTX = ANY

The CTX field accepts a hexadecimal context/header byte, or no restriction.

The editor placeholder shows:

ANY or A3

Values interpreted as no restriction include:

ANY
any
*
blank

Therefore, if context is irrelevant:

Message
    ↓
BEAN match / source selector
    ↓
CTX = ANY

means:

accept any BEAN context/header

Example:

CTX = ANY
DID = FE
MID = 2C

This means:

match FE/2C regardless of CTX

14. How to use DID = ANY

Example:

CTX = A3
DID = ANY
MID = 1E

This means:

match MID 0x1E in context 0xA3 regardless of DID

Use ANY only when the missing selector is genuinely irrelevant.

A selector that is too broad can make unrelated messages feed the same Mapping.


15. How to use MID = ANY

Example:

CTX = ANY
DID = FE
MID = ANY

means:

accept any message ID sent to DID FE

This is powerful but broad.

It is usually better to select a specific MID unless the Mapping intentionally needs a family of messages.


16. Required DATA length

The field:

Required DATA length

is optional.

Examples:

blank

means:

do not require a specific DATA length

Example:

2

means:

only match messages whose application DATA length is exactly 2 bytes

This can help distinguish messages with the same DID/MID but different payload structures.


17. Selector recipes

Recipe A — Specific coolant message

Message
  ↓
BEAN match / source selector

CTX = ANY
DID = FE
MID = 2C
Required DATA length = 1

Meaning:

accept FE/2C with one DATA byte, regardless of CTX

Recipe B — Specific RPM message

CTX = ANY
DID = FE
MID = 26
Required DATA length = 2

Recipe C — Specific lighting-switch context

Current project example:

CTX = A3
DID = FE
MID = 1E
Required DATA length = 1

Recipe D — Any message from DID FE

CTX = ANY
DID = FE
MID = ANY
Required DATA length = blank

Use this only if fields/expressions are intentionally designed to work for all such messages.

Recipe E — Completely open selector

CTX = ANY
DID = ANY
MID = ANY
Required DATA length = blank

This is effectively a wildcard source.

It is useful for mappings based only on the global decoded-signal cache, but it can be too broad for direct raw-field extraction.


18. CTX/DID/MID are hexadecimal

In these selector text fields, values are interpreted as hexadecimal by convention.

Examples:

26    = 0x26
A3    = 0xA3
FE    = 0xFE
0x26  = 0x26

Do not interpret 26 as decimal 26.

It means hexadecimal 0x26.


19. Transmit policy

Go to:

Message
    ↓
Transmit policy

Controls:

Trigger
Period (ms)
Heartbeat (ms)

Trigger choices are:

Every matching BEAN message
On output value change
Fixed periodic rate
On change + heartbeat
Manual / test only

20. Trigger: Every matching BEAN message

Select:

Trigger = Every matching BEAN message

Behavior:

matching BEAN message arrives
        ↓
Mapping composes CAN frame
        ↓
CAN frame transmitted

Use when every source update must be mirrored.

Example:

BEAN FE/24 speed arrives
        ↓
CAN 0x510 speed frame sent

21. Trigger: On output value change

Select:

Trigger = On output value change

Behavior:

source produces 6B → transmit
source produces 6B → no transmit
source produces 6B → no transmit
source produces 6C → transmit

Counters and checksums are ignored when determining whether the semantic output changed.

This prevents a rolling counter from causing a frame to appear “changed” by itself.

Good uses:

light switch state
door status
temperature
gear
warning flags

22. Trigger: Fixed periodic rate

Select:

Trigger = Fixed periodic rate

Then configure:

Period (ms)

Example:

Period = 100

means approximately:

10 Hz

The runtime first needs a valid matching source sample.

It does not invent data before the first source message.


23. Trigger: On change \\\+ heartbeat

Select:

Trigger = On change + heartbeat

Configure:

Heartbeat (ms)

Example:

Heartbeat = 1000

Behavior:

value changes → transmit immediately
no change     → transmit again every ~1000 ms

This is useful when the destination expects periodic proof that a state is still alive.


24. Trigger: Manual / test only

Select:

Trigger = Manual / test only

No automatic CAN transmission occurs from runtime.

Use this while designing a new Mapping.

Recommended initial workflow:

Manual / test only
    ↓
Preview
    ↓
Send Test Frame via CAN Interface
    ↓
independent CAN capture
    ↓
only then choose automatic trigger

25. Stale-source policy

Go to:

Message
    ↓
Stale-source policy

Controls:

Source timeout (ms, 0=disabled)
When stale
Invalid value

Available actions:

Keep last value
Set zero
Set configured invalid value
Suppress CAN frame

26. Stale policy: Keep last value

Example:

Source timeout = 2000 ms
When stale     = Keep last value

If source stops updating:

last value = 60 km/h

periodic output may continue using:

60 km/h

This is only appropriate when retaining the last state is safe.


27. Stale policy: Set zero

Example:

When stale = Set zero

All source data/signals used by stale substitution are replaced with zero.

Use only if zero is a meaningful and safe fallback.

For speed:

0 km/h

may be sensible in some bench systems.

For coolant temperature:

0

may be misleading.


28. Stale policy: Set configured invalid value

Example:

When stale   = Set configured invalid value
Invalid value = 255

Useful when the destination protocol defines:

0xFF = unavailable

Do not invent 0xFF as invalid unless the target protocol actually defines it.


29. Stale policy: Suppress CAN frame

Example:

When stale = Suppress CAN frame

No CAN frame is transmitted while the source is stale.

This is usually the safest choice when the target protocol has no documented invalid encoding.


30. CAN output frame

Go to:

Message
    ↓
CAN output frame

Set:

CAN ID
29-bit extended CAN ID
DLC

Example:

CAN ID = 0x500
29-bit extended CAN ID = OFF
DLC = 8

Equivalent textual ID:

500

Standard CAN maximum:

0x7FF

Extended maximum:

0x1FFFFFFF

31. Payload Fields tab

Go to:

Payload Fields

Each row represents one contribution to the outgoing CAN DATA payload.

Press:

Add field

The field editor opens with three tabs:

Source
Destination
Encoding

This is where most Mapping design happens.


32. BEAN → CAN Source type: BEAN raw byte/bit

Go to:

Payload Fields
    ↓
Add field
    ↓
Source
    ↓
Source type = BEAN raw byte/bit

Controls:

BEAN DATA byte
Start bit in byte (LSB=0)
Source length (bits)
Byte order
Signed

33. Raw example: copy a complete BEAN byte

Suppose source DATA is:

6B

Configure:

BEAN DATA byte = 0
Start bit      = 0
Source length  = 8
Byte order     = little
Signed         = OFF

Then go to:

Destination

Set:

CAN start bit = 8
Length        = 8
Byte order    = little
Signed        = OFF

Then:

Encoding

Set:

CAN scale = 1
CAN offset = 0
Clamp raw minimum = blank
Clamp raw maximum = blank

Result:

BEAN DATA0 = 0x6B
        ↓
CAN byte1 = 0x6B

34. Raw example: extract a single bit

Suppose:

BEAN DATA0 bit4 = taillights ON

Configure Source:

BEAN DATA byte = 0
Start bit      = 4
Source length  = 1
Byte order     = little
Signed         = OFF

Destination example:

CAN start bit = 0
Length        = 1

Result:

BEAN bit4 → CAN bit0

If source byte is:

0x11 = 00010001b

bit4 is 1.


35. Raw example: extract low nibble

Source byte:

0xAB = 1010 1011

Configure:

BEAN DATA byte = 0
Start bit      = 0
Source length  = 4

Extracted value:

0xB

Destination:

CAN start bit = 12
Length        = 4

This places the nibble in CAN Byte1 bits4..7.


36. Raw example: extract high nibble

Source:

0xAB

Configure:

BEAN DATA byte = 0
Start bit      = 4
Source length  = 4

Extracted:

0xA

37. Raw example: 16-bit Big Endian RPM

If BEAN DATA is:

3C 00

configure:

BEAN DATA byte = 0
Start bit      = 0
Source length  = 16
Byte order     = big
Signed         = OFF

Exact raw-preserving destination:

CAN start bit = 24
Length        = 16
Byte order    = big
Signed        = OFF

Encoding:

scale  = 1
offset = 0

Result:

CAN B3-B4 = 3C 00

38. BEAN → CAN Source type: Decoded BEAN signal

Go to:

Payload Fields
    ↓
Add field
    ↓
Source
    ↓
Source type = Decoded BEAN signal

Control:

Signal name

Examples:

rpm
speed
coolant_temp
outside_temp

This source uses the latest numeric value decoded by BEAN-DBC.

It is extremely useful for combining information from separate BEAN messages into one CAN frame.


39. Decoded example: coolant temperature

Set:

Signal name = coolant_temp

Current formula:

coolant_temp = raw / 2

If you want the CAN byte to preserve the Toyota raw encoding:

Destination:
CAN start bit = 8
Length = 8

Encoding:
CAN scale = 0.5
CAN offset = 0

For:

coolant_temp = 53.5

CAN raw becomes:

round(53.5 / 0.5)
= 107
= 0x6B

40. Decoded example: outside temperature

Current formula:

outside_temp = raw - 48

To reproduce Toyota raw:

Signal name = outside_temp

Destination:
CAN start bit = 0
Length = 8

Encoding:
scale = 1
offset = -48

For:

outside_temp = 30

result:

(30 - (-48)) / 1
= 78
= 0x4E

41. Decoded example: speed

Current project interpretation:

speed = raw km/h

Use:

Signal name = speed

Destination:
start_bit = 16
length = 8

Encoding:
scale = 1
offset = 0

Example:

60 km/h → 0x3C

42. Decoded example: RPM

Current formula:

rpm = raw / 5.12

To restore raw encoding:

Signal name = rpm

Destination:
start_bit = 24
length = 16
byte_order = big

Encoding:
scale = 0.1953125
offset = 0

because:

1 / 5.12 = 0.1953125

Example:

3000 / 0.1953125
= 15360
= 0x3C00

43. BEAN → CAN Source type: Constant

Go to:

Source type = Constant

Control:

Numeric value

Use constants for fields that should not depend on source traffic.

Examples:

protocol version
fixed mode byte
reserved zero
fixed enable bit
manufacturer marker

44. Constant example: fixed zero byte

Set:

Numeric value = 0

Destination:
CAN start bit = 40
Length = 8

Encoding:
scale = 1
offset = 0

Result:

CAN B5 = 00

45. Constant example: fixed 0xA5 byte

Set:

Numeric value = 165

because:

0xA5 = 165 decimal

Destination:

CAN start bit = 56
Length = 8

Result:

CAN B7 = A5

The Constant input is numeric. A decimal value is the safest UI entry unless the current field parser explicitly accepts another numeric notation.


46. Constant example: single enable bit

Set:

Numeric value = 1

Destination:

CAN start bit = 7
Length = 1

Result:

CAN Byte0 bit7 = 1

47. BEAN → CAN Source type: Expression

Go to:

Source type = Expression

BEAN expression variables are:

raw0 .. raw15
ctx
did
mid
dlc
decoded numeric signal names

Example environment:

raw0 = BEAN DATA0
raw1 = BEAN DATA1
...
ctx  = context/header
did  = DID
mid  = MID
dlc  = number of BEAN DATA bytes
rpm  = decoded signal, if present
speed = decoded signal, if present

48. Allowed expression operations

Supported arithmetic:

+
-
*
/
//
%
**

Examples:

raw0 + 1
raw0 * 2
raw0 / 2
raw0 // 4
raw0 % 16
2 ** raw0

Supported bitwise operators:

&
|
^
<<
>>
~

Examples:

raw0 & 0x0F
raw0 | 0x80
raw0 ^ raw1
raw0 << 1
raw1 >> 2
~raw0

Supported comparisons:

==
!=
<
<=
>
>=

Supported Boolean operators:

and
or
not

Supported conditional expression:

A if condition else B

Example:

1 if speed > 0 else 0

49. Allowed helper functions

The only callable helper functions currently allowed are:

abs()
min()
max()
round()
int()
float()
floor()
ceil()

Arbitrary Python calls are rejected.

Attribute access is rejected.

Imports are rejected.

Keyword arguments are rejected.

The expression engine is deliberately restricted.


50. Helper function: abs()

Purpose:

absolute value

Examples:

abs(-5)
→ 5
abs(outside_temp)

Potential automotive use:

abs(target_speed - speed)

51. Helper function: min()

Purpose:

choose the smallest value

Examples:

min(raw0, 100)

This limits the expression result to no more than 100.

Example:

min(speed, 255)

52. Helper function: max()

Purpose:

choose the largest value

Example:

max(raw0, 10)

ensures the expression is at least 10.

Combined clamp-like expression:

min(max(speed, 0), 255)

53. Helper function: round()

Purpose:

round a numeric value before encoding

Example:

round(rpm / 100)

Note that the Mapping encoder itself also applies round() when converting the final source value to destination raw.


54. Helper function: int()

Purpose:

convert a numeric value to integer

Example:

int(rpm / 100)

This truncates toward zero before the encoder.

Difference:

int(12.9) = 12
round(12.9) = 13

55. Helper function: float()

Purpose:

force numeric value to floating-point

Example:

float(raw0) / 2

It is rarely required because division already produces numeric output, but it is available.


56. Helper function: floor()

Purpose:

round downward

Example:

floor(12.9)
→ 12

Negative example:

floor(-1.2)
→ -2

57. Helper function: ceil()

Purpose:

round upward

Example:

ceil(12.1)
→ 13

Negative example:

ceil(-1.2)
→ -1

58. Expression example: combine two BEAN bytes

If:

raw0 = high byte
raw1 = low byte

use:

(raw0 << 8) | raw1

Example:

raw0 = 0x3C
raw1 = 0x00

(raw0 << 8) | raw1
= 0x3C00

59. Expression example: convert raw RPM to physical RPM

Current BEAN RPM raw formula:

RPM = raw16 / 5.12

Expression:

((raw0 << 8) | raw1) / 5.12

If destination CAN field is physical RPM with:

1 rpm/bit

set Encoding:

scale = 1
offset = 0

60. Expression example: map one status bit to 0/1

1 if (raw0 & 0x10) != 0 else 0

This converts any non-zero masked bit into exactly:

0 or 1

61. Expression example: invert a Boolean status

0 if (raw0 & 0x10) != 0 else 1

62. Expression example: pack two nibbles

Suppose:

raw0 low nibble  → destination low nibble
raw1 low nibble  → destination high nibble

Expression:

(raw0 & 0x0F) | ((raw1 & 0x0F) << 4)

63. Expression example: use CTX/DID/MID

Because selectors are not copied automatically, you can explicitly create them.

Examples:

ctx
did
mid

To put MID into CAN B0:

Source type = Expression
Expression = mid

Destination:
start_bit = 0
length = 8

Encoding:
scale = 1
offset = 0

64. BEAN → CAN Source type: Rolling counter

Go to:

Source type = Rolling counter

Controls:

Counter width
Initial value
Step
Wrap at

Example:

Counter width = 4
Initial value = 0
Step = 1
Wrap at = 16

Sequence after successful transmissions:

0
1
2
3
...
15
0
1
...

The counter advances after successful output transmission.


65. Counter example: 4-bit alive counter in low nibble

Source:

Counter width = 4
Initial value = 0
Step = 1
Wrap at = 16

Destination:

CAN start bit = 48
Length = 4

Output sequence:

B6 low nibble:
0,1,2,3,...F,0...

66. Counter example: step by 2

Initial = 0
Step = 2
Wrap = 16

Sequence:

0,2,4,6,8,A,C,E,0...

67. Counter width versus wrap

Counter width describes the intended counter size and provides a natural default concept for wrapping.

Wrap at is the actual runtime modulus.

Example:

width = 4
wrap  = 10

sequence is:

0..9

not:

0..15

Make sure the destination bit length can hold the complete counter range.


68. BEAN → CAN Source type: Checksum / CRC

Go to:

Source type = Checksum / CRC

Algorithms:

xor8
sum8
crc8

Controls:

First CAN byte
Last CAN byte
CRC polynomial
CRC init
CRC xorout

Checksum fields are calculated after normal fields have been packed.


69. XOR8

For bytes:

B0 B1 B2

XOR8 computes:

B0 ^ B1 ^ B2

Example:

12 ^ 34 ^ 56
= 70

So:

XOR8 = 0x70

70. SUM8

SUM8 computes:

sum(bytes) & 0xFF

Example:

0xF0 + 0x30
= 0x120

0x120 & 0xFF
= 0x20

71. CRC8 implementation

Current Mapping CRC8 is an MSB-first left-shifting implementation.

Configurable:

poly
init
xorout

Default UI values:

poly   = 0x07
init   = 0x00
xorout = 0x00

There are no separate refin / refout controls in the current UI.

Do not assume this CRC matches an ECU protocol simply because the polynomial is the same.

CRC parameter conventions can differ.


72. Checksum range example

Suppose CAN layout is:

B0 data
B1 data
B2 data
B3 data
B4 data
B5 data
B6 counter
B7 checksum

Checksum field:

Algorithm = xor8
First CAN byte = 0
Last CAN byte = 6

Destination:

CAN start bit = 56
Length = 8

Recommended:

exclude checksum destination byte from its own source range

unless the target protocol specifically defines otherwise.


73. Destination tab

Every field has:

Destination

Controls:

CAN start bit (byte0 bit0 = 0)
Length (bits)
Byte order
Signed

Examples:

B0        → start 0, length 8
B1        → start 8, length 8
B2 bit3   → start 19, length 1
B3-B4 BE  → start 24, length 16, big

74. Encoding tab

Every field has:

Encoding

Controls:

CAN scale (physical/bit)
CAN offset
Clamp raw minimum
Clamp raw maximum

Formula:

CAN_raw = round((source_value - offset) / scale)

75. Clamp example

Suppose source can exceed an 8-bit field.

Set:

Clamp raw minimum = 0
Clamp raw maximum = 255

This prevents values below 0 or above 255 from escaping that range before destination-fit validation.

Without clamp, an out-of-range encoded value raises an error.


76. Complete BEAN → CAN walkthrough: packed IS200 summary frame

Goal:

CAN 0x500 DLC8

B0 outside_temp raw
B1 coolant raw
B2 speed raw
B3-B4 RPM raw Big Endian
B5-B7 00

Step 1 — Message tab

Go to:

Message

Set:

Mapping identity
Name = IS200 Powertrain Summary
Enabled = YES

Step 2 — BEAN match / source selector

Because this Mapping uses cached decoded signals from several BEAN messages:

CTX = ANY
DID = ANY
MID = ANY
Required DATA length = blank

This is intentionally broad.

Step 3 — Transmit policy

For a stable output frame:

Trigger = Fixed periodic rate
Period = 20 ms
Heartbeat = 1000 ms

20 ms corresponds to:

50 Hz

Step 4 — Stale-source policy

Example:

Source timeout = 3000 ms
When stale = Keep last value
Invalid value = 0

Step 5 — CAN output frame

CAN ID = 0x500
29-bit extended = OFF
DLC = 8

Step 6 — Payload Fields: outside

Add field
Source:
Field name = OutsideTemp
Enabled = YES
Source type = Decoded BEAN signal
Signal name = outside_temp

Destination:
CAN start bit = 0
Length = 8
Byte order = little
Signed = OFF

Encoding:
CAN scale = 1
CAN offset = -48
Clamp min = 0
Clamp max = 255

Step 7 — coolant

Source type = Decoded BEAN signal
Signal = coolant_temp

Destination:
start_bit = 8
length = 8

Encoding:
scale = 0.5
offset = 0
clamp 0..255

Step 8 — speed

Signal = speed

Destination:
start_bit = 16
length = 8

Encoding:
scale = 1
offset = 0
clamp 0..255

Step 9 — RPM

Signal = rpm

Destination:
start_bit = 24
length = 16
byte_order = big
signed = OFF

Encoding:
scale = 0.1953125
offset = 0
clamp 0..65535

Step 10 — reserved bytes

Create three Constant fields:

B5: value 0 → start_bit 40 length 8
B6: value 0 → start_bit 48 length 8
B7: value 0 → start_bit 56 length 8

77. Preview / Test for BEAN → CAN

Go to:

Preview / Test

Fields:

CTX
DID
MID
BEAN DATA bytes
Decoded signals JSON
Counter values JSON

For the packed summary example, use:

CTX = 0xA3
DID = 0xFE
MID = 0x26
BEAN DATA = 00 00

Decoded signals JSON:

{
  "outside_temp": 30,
  "coolant_temp": 53.5,
  "speed": 60,
  "rpm": 3000
}

Press:

Compose CAN Preview

Expected:

CAN ID: 0x500
DATA: 4E 6B 3C 3C 00 00 00 00

Then:

Send Test Frame via CAN Interface

Only do this on a controlled CAN network.


78. Preview trace

The Preview output includes a packing trace.

Typical line concept:

RPM: source=3000 -> encoded=15360 -> bits 24..39

Use the trace to answer:

What value did the source produce?
What raw value did Encoding produce?
Which bits received it?

If the final bytes are wrong, the trace usually identifies which stage is wrong.


79. Raw JSON tab

Go to:

Raw JSON

Buttons:

Refresh JSON from editor
Apply JSON to editor

Use this for advanced editing or bulk changes.

Do not edit JSON and assume it is valid.

After editing:

Apply JSON to editor

which validates and reloads the visual editor.


PART II — CAN → BEAN

80. Creating a new CAN → BEAN Mapping

Open:

Devices / CAN Gateway
    ↓
CAN → BEAN Mapping
    ↓
Open CAN → BEAN Mapping Editor...

Press:

New document

Left list:

BEAN output messages / mappings

Each Mapping in this list represents:

one CAN selector
    ↓
one BEAN output application message

81. CAN → BEAN Message tab

Select a Mapping and open:

Message

Groups:

Mapping identity
CAN match / source selector
Transmit policy
Stale-source policy
BEAN output application message

82. CAN match / source selector

Go to:

Message
    ↓
CAN match / source selector

Controls:

CAN ID
29-bit extended CAN ID
Required DLC

Example:

CAN ID = 0x500
29-bit extended CAN ID = OFF
Required DLC = 8

Only matching RX frames feed the Mapping.

The CAN ID is not automatically copied into BEAN DATA.


83. CAN ID notation

Text IDs are hexadecimal.

Equivalent:

500
0x500

Extended example:

18DAF110
0x18DAF110

For the extended example:

29-bit extended CAN ID = ON

84. Required DLC

Examples:

blank

means:

accept any DLC

Example:

8

means:

only CAN frames with exactly 8 data bytes

If the CAN layout is fixed, specifying DLC is strongly recommended.


85. Current CAN match limitation

The current selector matches:

CAN ID
Extended flag
DLC

It does not yet provide generic payload conditions like:

can1 == 0x41
can2 == 0x0C

inside the selector.

This matters for diagnostic traffic.

Example:

0x7E8

can carry many different OBD-II responses.

Matching only 0x7E8 DLC8 does not prove the response is PID 0C RPM.


86. BEAN output application message

Go to:

Message
    ↓
BEAN output application message

Controls:

DID / destination
MID / message
DATA length

Example:

DID = 62
MID = 2C
DATA length = 1

Output application payload:

62 2C <DATA0>

87. Do not add CRC/EOM

The Mapping output is not:

header + DID + MID + DATA + CRC + EOM + post-EOM

It is only:

DID + MID + DATA

Correct example:

62 2C 6B

Incorrect:

62 2C 6B xx 7E 40

The BEAN bridge/BeanMPX layer creates the physical link-layer representation.


88. Maximum CAN → BEAN DATA length

Current bridge payload maximum:

16 bytes total

DID \\\+ MID consume:

2 bytes

Therefore:

maximum DATA length = 14

The editor allows:

0..14

DATA bytes.


89. CAN → BEAN Payload Fields

Go to:

Payload Fields
    ↓
Add field

Field editor tabs:

Source
Destination
Encoding

Source types:

CAN raw byte/bit
Decoded CAN signal
Constant
Expression
Rolling counter
Application checksum / CRC

90. CAN raw byte/bit

Go to:

Source
    ↓
Source type = CAN raw byte/bit

Controls:

CAN DATA byte
Start bit in byte (LSB=0)
Source length (bits)
Byte order
Signed

CAN DATA byte range is:

0..7

because current input is Classic CAN.


91. CAN raw example: exact byte copy

Incoming:

500#4E6B3C3C00000000

Need:

CAN B1 = 6B
→
BEAN DATA0 = 6B

Source:

CAN DATA byte = 1
Start bit = 0
Source length = 8
Byte order = little
Signed = OFF

Destination:

BEAN DATA start bit = 0
Length = 8
Byte order = little
Signed = OFF

Encoding:

BEAN output scale = 1
BEAN output offset = 0

92. CAN raw example: single bit

Suppose:

CAN B0 bit7 = warning active

Source:

CAN DATA byte = 0
Start bit = 7
Source length = 1

Destination:

BEAN DATA start bit = 4
Length = 1

This maps:

CAN B0 bit7 → BEAN DATA0 bit4

93. CAN raw example: Big Endian RPM

Incoming:

B3 = 3C
B4 = 00

Source:

CAN DATA byte = 3
Start bit = 0
Source length = 16
Byte order = big
Signed = OFF

Destination:

BEAN DATA start bit = 0
Length = 16
Byte order = big
Signed = OFF

Encoding:

scale = 1
offset = 0

Result:

BEAN DATA = 3C 00

94. Decoded CAN signal

Go to:

Source type = Decoded CAN signal

Control:

Signal name

The current live CAN Interface path is raw-byte based and does not yet automatically add a CAN-DBC decoder.

Therefore:

CAN raw byte/bit
Expression

are normally the practical live sources today.

Decoded CAN signal works when numeric decoded signals are supplied by the input pipeline, Preview, tests, or future decoder integration.


95. Decoded CAN signal example: physical coolant

Suppose input pipeline supplies:

coolant_temp = 53.5

Target BEAN raw formula:

raw = temperature × 2

Use:

Signal name = coolant_temp

Destination:
start_bit = 0
length = 8

Encoding:
scale = 0.5
offset = 0

Result:

53.5 → 0x6B

96. CAN → BEAN Constant

Example fixed BEAN flag:

Source type = Constant
Numeric value = 1

Destination:

BEAN DATA start bit = 7
Length = 1

Result:

DATA0 bit7 = 1

97. CAN → BEAN Expression variables

Available variables:

can0
can1
can2
can3
can4
can5
can6
can7
can_id
dlc
decoded numeric CAN signal names, when supplied

98. CAN expression example: combine two bytes

(can3 << 8) | can4

For:

can3 = 0x3C
can4 = 0x00

result:

0x3C00

99. CAN expression example: scale OBD RPM into BEAN RPM

OBD PID 0C:

RPM = ((A << 8) | B) / 4

BEAN:

RPM = BEAN_raw / 5.12

Therefore:

BEAN_raw = OBD_raw × 1.28

Exact ratio:

32 / 25

Expression:

(((can3 << 8) | can4) * 32) / 25

Destination:

start_bit = 0
length = 16
byte_order = big

Encoding:

scale = 1
offset = 0

100. OBD RPM worked example

3000 rpm:

OBD raw = 3000 × 4
        = 12000
        = 0x2EE0

Example raw CAN response layout:

04 41 0C 2E E0 00 00 00

Therefore:

can3 = 0x2E
can4 = 0xE0

Expression:

(((0x2E << 8) | 0xE0) * 32) / 25
= 15360
= 0x3C00

BEAN decoder:

0x3C00 / 5.12
= 3000 rpm

101. OBD RPM warning

Do not automatically enable:

CAN ID = 0x7E8
DLC = 8

and assume every frame is RPM.

The current selector does not validate:

can1 == 0x41
can2 == 0x0C

A different PID response on the same CAN ID could be transformed incorrectly.


102. CAN expression example: threshold

1 if can0 >= 100 else 0

Potential use:

activate BEAN bit when CAN value crosses threshold

103. CAN expression example: mask and move bits

(can1 & 0x03) << 4

Takes:

CAN B1 bits0..1

and moves them to:

bits4..5

of the numeric result.


104. CAN expression example: choose greater sensor value

max(can0, can1)

105. CAN expression example: clamp

min(max(can0, 10), 200)

Range:

10..200

106. CAN → BEAN Rolling counter

Source:

Rolling counter

Example:

Counter width = 4
Initial value = 0
Step = 1
Wrap at = 16

Destination:

BEAN DATA start bit = 0
Length = 4

Counter advances only after a successful BEAN TX callback.


107. CAN → BEAN Application checksum / CRC

Go to:

Source type = Application checksum / CRC

Controls:

Algorithm
First BEAN DATA byte
Last BEAN DATA byte
CRC polynomial
CRC init
CRC xorout

Algorithms:

xor8
sum8
crc8

Important:

This is not the physical BEAN CRC.

It is only for an application-level byte inside BEAN DATA.


108. CAN → BEAN checksum example

Output DATA layout:

DATA0 source
DATA1 source
DATA2 source
DATA3 XOR8

Normal fields populate:

DATA0..DATA2

Checksum field:

Algorithm = xor8
First BEAN DATA byte = 0
Last BEAN DATA byte = 2

Destination:
start_bit = 24
length = 8

Then:

DATA3 = DATA0 ^ DATA1 ^ DATA2

109. CAN → BEAN destination bits

Examples:

DATA0       → start_bit 0
DATA1       → start_bit 8
DATA2       → start_bit 16
DATA3       → start_bit 24
DATA0 bit4  → start_bit 4
DATA1 bit2  → start_bit 10

Maximum current BEAN DATA bit range:

0..111

because:

14 bytes × 8 = 112 bits

110. Complete CAN → BEAN walkthrough: packed 0x500 back to four BEAN messages

Incoming:

500#4E6B3C3C00000000

Goal:

outside
coolant
speed
RPM

as four separate BEAN messages.

You must create four Mapping entries.


111. Mapping A — Outside temperature

Left panel:

BEAN output messages / mappings
    ↓
Add

Message tab:

Mapping identity
Name = CAN500 Outside Temp
Enabled = YES

CAN match / source selector:

CAN ID = 0x500
29-bit extended = OFF
Required DLC = 8

Transmit policy, first test:

Trigger = Manual / test only

BEAN output application message:

DID = 62
MID = CD
DATA length = 1

Payload Fields:

Add field

Source:

Source type = CAN raw byte/bit
CAN DATA byte = 0
Start bit = 0
Source length = 8
Byte order = little
Signed = OFF

Destination:

BEAN DATA start bit = 0
Length = 8

Encoding:

scale = 1
offset = 0

Expected:

62 CD 4E

112. Mapping B — Coolant

Duplicate Mapping A or press Add.

Message:

Name = CAN500 Coolant
CAN ID = 0x500
Required DLC = 8
DID = 62
MID = 2C
DATA length = 1

Field:

CAN DATA byte = 1
bit = 0
length = 8

Destination:

start_bit = 0
length = 8

Encoding:

scale = 1
offset = 0

Expected:

62 2C 6B

113. Mapping C — Speed

Name = CAN500 Speed
CAN ID = 0x500
DID = 62
MID = 24
DATA length = 1

Field:

CAN DATA byte = 2
length = 8

Expected:

62 24 3C

114. Mapping D — RPM

Name = CAN500 RPM
CAN ID = 0x500
DID = 62
MID = 26
DATA length = 2

Field Source:

CAN DATA byte = 3
Start bit = 0
Source length = 16
Byte order = big
Signed = OFF

Destination:

BEAN DATA start bit = 0
Length = 16
Byte order = big
Signed = OFF

Encoding:

scale = 1
offset = 0

Expected:

62 26 3C 00

115. FE versus 62

Project evidence must remain separated.

Observed/captured vehicle traffic includes forms such as:

FE 26 ...
FE 2C ...
FE 24 ...
FE CD ...

Bridge-oriented transmit templates commonly use:

62 26 ...
62 2C ...
62 24 ...
62 CD ...

Do not silently assume:

FE == 62

for transmission semantics.

Use the DID that is validated for your specific bridge/target test.

Document which form was:

observed
transmitted
accepted by target ECU

116. CAN → BEAN Preview / Test

Go to:

Preview / Test

Controls:

CAN ID
29-bit extended
CAN DATA bytes
Decoded CAN signals JSON
Counter values JSON

Example:

CAN ID = 0x500
Extended = OFF
CAN DATA = 4E 6B 3C 3C 00 00 00 00
Decoded signals JSON = {}
Counter values JSON = {}

Press:

Compose BEAN Preview

For coolant Mapping expected application payload:

62 2C 6B

Then:

Send Test Frame via BEAN

requires the physical BEAN interface.


117. CAN → BEAN live activation

The default Mapping behavior is intentionally safe.

A new Mapping is normally:

Enabled = NO
Trigger = Manual / test only

After validation:

  1. Connect the physical BEAN interface.
  2. Open the desired CAN → BEAN Mapping file.
  3. Enable the desired Mapping entries.
  4. Select an automatic Trigger.
  5. Save.
  6. Return to Devices / CAN Gateway.
  7. Enable:
Enable CAN → BEAN Mapping

The gateway does not auto-arm at application startup.


118. Editing the active CAN → BEAN Mapping

Changing/opening/saving the active Mapping while live output is active disarms the runtime.

This is intentional.

Workflow:

live gateway active
    ↓
open/save/change active Mapping
    ↓
runtime stops
    ↓
Enable CAN → BEAN Mapping clears
    ↓
user must re-arm explicitly

This prevents an edited rule from becoming electrically live mid-transaction.


PART III — HELPER FUNCTION REFERENCE

119. abs(x)

Returns absolute magnitude.

Examples:

abs(-10)     → 10
abs(raw0-50)
abs(speed-target_speed)

120. min(a, b, ...)

Returns smallest argument.

Examples:

min(raw0, 255)
min(speed, 200)
min(raw0, raw1, raw2)

121. max(a, b, ...)

Returns largest argument.

Examples:

max(raw0, 0)
max(speed, 10)
max(raw0, raw1)

122. min/max as a clamp

min(max(value, minimum), maximum)

Example:

min(max(speed, 0), 250)

123. round(x)

Rounds numeric value.

Example:

round(12.7) → 13

Useful:

round(rpm / 100)

The final destination encoder also rounds after applying scale/offset.


124. int(x)

Converts to integer by truncation toward zero.

Examples:

int(12.9)  → 12
int(-12.9) → -12

125. float(x)

Converts numeric value to floating-point.

Example:

float(raw0) / 2

126. floor(x)

Rounds toward negative infinity.

Examples:

floor(12.9) → 12
floor(-1.2) → -2

127. ceil(x)

Rounds toward positive infinity.

Examples:

ceil(12.1) → 13
ceil(-1.2) → -1

128. Allowed arithmetic examples

raw0 + raw1
raw0 - raw1
raw0 * 2
raw0 / 2
raw0 // 2
raw0 % 16
raw0 ** 2

129. Allowed bitwise examples

raw0 & 0x0F
raw0 | 0x80
raw0 ^ raw1
raw0 << 2
raw0 >> 2
~raw0

When using ~, remember Python represents integers with unlimited signed precision.

If you need an 8-bit inverted value, mask it:

(~raw0) & 0xFF

130. Allowed comparison examples

raw0 == 0
raw0 != 0
raw0 > 100
raw0 >= 100
raw0 < 10
raw0 <= 10

131. Allowed Boolean examples

(raw0 > 10) and (raw1 > 20)
(raw0 == 1) or (raw1 == 1)
not (raw0 == 0)

Since the final expression must produce a numeric result, it is usually clearer to wrap Boolean logic in a conditional expression.

Example:

1 if (raw0 > 10 and raw1 > 20) else 0

132. Conditional expression examples

1 if speed > 0 else 0
255 if coolant_temp > 120 else 0
raw0 if raw0 < 200 else 200
0 if rpm < 500 else rpm

133. What expressions cannot do

Do not use:

import
object.attribute
os.system(...)
open(...)
__import__(...)
list indexing syntax requiring unsupported AST nodes
arbitrary function calls
keyword arguments

The evaluator intentionally accepts only a limited expression subset.


PART IV — EXAMPLE LIBRARY

134. Example: copy BEAN byte to CAN byte

BEAN DATA0 = 0x42
CAN B4 target

Source:

bean_raw
byte 0
bit 0
length 8

Destination:

start_bit 32
length 8

Encoding:

1 / 0

Result:

CAN B4 = 42

135. Example: copy CAN byte to BEAN byte

CAN B5 = 0x77
BEAN DATA2 target

Source:

can_raw
byte 5
bit 0
length 8

Destination:

start_bit = 16
length = 8

Result:

BEAN DATA2 = 77

136. Example: BEAN Boolean bit to CAN byte

Source:

BEAN DATA0 bit4

Expression alternative:

1 if (raw0 & 0x10) else 0

Destination:

CAN B0

Encoding:

scale 1
offset 0

CAN B0 becomes:

00 or 01

instead of merely setting one bit.


137. Example: CAN Boolean bit to BEAN flag bit

Source:

CAN B2 bit3

Raw source:

byte 2
bit 3
length 1

Destination:

BEAN DATA0 start_bit 6
length 1

138. Example: temperature conversion to standard “°C \\\+ 40” CAN encoding

Suppose BEAN decoded source:

outside_temp = actual °C

Target CAN protocol uses:

raw = °C + 40

Use:

scale = 1
offset = -40

For:

25 °C

result:

65 decimal = 0x41

139. Example: 0.1 km/h per bit

Source:

speed = 63.4 km/h

Target CAN:

0.1 km/h / bit

Use:

scale = 0.1
offset = 0

Result:

634 decimal

Requires more than 8 bits.

Use:

16-bit destination

140. Example: signed temperature

Suppose source:

outside_temp = -14 °C

Target destination is signed 8-bit, 1 °C/bit.

Use:

Destination:
length = 8
Signed = ON

Encoding:
scale = 1
offset = 0

Raw signed value:

-14

packed two’s-complement:

0xF2

141. Example: map BEAN two-byte unsigned value into 12 CAN bits

Suppose:

source value = 0xABC

Destination:

start_bit = 0
length = 12
byte_order = little

The generic bit packer places low-order source bits into consecutive destination LSB0 positions.

For non-byte-aligned fields, document the exact bit layout and test Preview carefully.


142. Example: use DID as a CAN field

Message selector:

DID = ANY

Expression field:

did

Destination:

CAN B0

This explicitly exports the BEAN DID.

BEANalyzer never inserts it automatically.


143. Example: use CAN ID low byte inside BEAN DATA

CAN → BEAN expression:

can_id & 0xFF

Destination:

BEAN DATA0

Example:

CAN ID = 0x523

result:

0x23

144. Example: derive message size

BEAN expression:

dlc

For BEAN expression environment, dlc is the length of source DATA.

CAN expression:

dlc

is the CAN data length.

You can place it into a destination field if the target protocol requires an explicit payload length field.


145. Example: threshold RPM warning

BEAN → CAN:

Expression:
1 if rpm >= 2500 else 0

Destination:

CAN start bit = 0
length = 1

146. Example: RPM range code

0 if rpm < 1000 else 1 if rpm < 3000 else 2

Possible result:

0 = low
1 = medium
2 = high

Destination needs at least 2 bits.


147. Example: pack three Boolean states into one byte

Expression:

(1 if signal_a else 0) |
((1 if signal_b else 0) << 1) |
((1 if signal_c else 0) << 2)

Use decoded signal names only if those numeric names are actually available.


PART V — MATCHING STRATEGY

148. Narrow selector versus broad selector

A narrow BEAN selector:

CTX = A3
DID = FE
MID = 1E
DATA length = 1

is safer for raw extraction.

A broad selector:

CTX = ANY
DID = ANY
MID = ANY

is useful when the output is driven by cached decoded signals and timing rather than current raw message bytes.

Rule:

The broader the selector, the less you should rely on raw0, raw1, etc. unless every matching message has the same layout.

149. Why raw fields and ANY can be dangerous

Suppose:

CTX = ANY
DID = ANY
MID = ANY

and field:

raw0 → CAN B0

Every matching BEAN message may have a different meaning for DATA0.

Result:

CAN B0 changes according to unrelated BEAN messages

That is usually wrong.

Use a specific selector for direct raw extraction.


150. Why decoded signals and ANY can be useful

Suppose Mapping uses:

outside_temp
coolant_temp
speed
rpm

from the decoded-state cache.

A periodic CAN summary frame may be intentionally independent of whichever BEAN message arrived last.

In that design, a broad selector can be acceptable because the actual fields are not raw0..rawN.

Document this architecture clearly.


PART VI — TIMING

151. Do not copy CAN timing blindly into BEAN

CAN may run at:

500 kbps

while BEAN is a much slower network.

If CAN produces an update every:

5 ms

do not automatically transmit a BEAN frame every 5 ms simply because the source does.

Prefer:

On change

or a validated periodic interval.


152. Example timing design for slow temperature

Temperature changes slowly.

Possible policy:

Trigger = On change + heartbeat
Heartbeat = 1000 ms

This gives:

fast reaction when temperature changes
+
one refresh per second

153. Example timing design for RPM

RPM changes rapidly.

Possible policies:

Every matching message

if source and destination networks can safely support it,

or:

Fixed periodic rate
Period = 50 ms

for 20 Hz.

The correct rate must come from capture/ECU behavior, not from guesswork.


154. Example timing design for door status

Door state is event-like.

Use:

On output value change

Optionally heartbeat if the target needs refresh.


PART VII — ANTI-LOOP

155. Why bidirectional gateways can loop

Potential loop:

BEAN
 ↓
BEAN → CAN
 ↓
CAN
 ↓
CAN → BEAN
 ↓
BEAN
 ↓
...

Current CAN → BEAN runtime includes local CAN TX echo suppression.

It fingerprints:

CAN ID
Extended flag
DATA
timestamp

A recent identical CAN RX matching a local CAN TX can be suppressed once.

Default local echo window:

120 ms

This protects the local echo path.

It is not a universal distributed gateway-loop detector.


156. One-shot echo consumption

One locally transmitted CAN frame creates one fingerprint.

If an identical RX appears quickly:

fingerprint consumed
frame suppressed

A later identical external frame is allowed.

This prevents a broad “ignore identical frame for 120 ms” rule from hiding legitimate traffic.


PART VIII — TROUBLESHOOTING

157. No CAN output from BEAN → CAN

Check:

Mapping Enabled?
Correct active file?
Trigger not Manual?
Selector matches?
Required DATA length matches?
Source raw byte exists?
Decoded signal name exact?
Destination fits DLC?
CAN Interface connected?
Runtime active?

158. CAN frame exists but field is zero

Possible causes:

wrong source byte
wrong source bit
decoded signal missing
expression variable name wrong
stale policy replaced data
field disabled
destination overwritten by another field

159. Correct source but wrong destination byte

Check:

start_bit
length
endianness

Remember:

B0 = 0
B1 = 8
B2 = 16
B3 = 24

160. Value doubled or halved

This is usually a scaling misunderstanding.

Ask:

Is source raw?
or
Is source already physical?

Example:

coolant decoded = 53.5

If you use:

scale = 1

you get approximately:

54

not Toyota raw 107.

To restore raw:

scale = 0.5

161. RPM bytes reversed

Expected:

3C 00

Got:

00 3C

Check:

byte_order = big

for the 16-bit source/destination where appropriate.


162. CAN → BEAN produces no output

Check:

physical BEAN interface connected
CAN Interface receiving
active CAN → BEAN file correct
Mapping Enabled
Trigger automatic
Enable CAN → BEAN Mapping checked
CAN ID exact
extended flag exact
DLC exact
source byte valid
DATA length large enough
runtime not fail-closed after backend error

163. Periodic Mapping produces nothing at startup

Expected behavior.

Periodic mode waits for:

first matching source sample

before it has state to retransmit.


164. Mapping immediately disables

Potential causes:

backend exception
invalid field
value outside destination range
invalid expression
BEAN output too long
disconnected BEAN bridge

CAN → BEAN backend errors fail closed.


165. Expression validation fails

Check for unsupported syntax.

Allowed:

raw0 + 1
(raw0 << 8) | raw1
1 if raw0 > 10 else 0
min(max(raw0, 0), 255)

Not allowed:

some_object.attribute
__import__("os")
open("file")

PART IX — VALIDATION PROCEDURE

166. Phase 1 — mathematical validation

Before transmitting anything:

source value
formula
expected destination raw
expected bytes

must be manually calculable.

Example:

RPM = 3000
raw = 3000 × 5.12
    = 15360
    = 0x3C00

167. Phase 2 — Preview validation

Use:

Preview / Test

Verify exact bytes.

Do not continue because “the number looks about right”.

Verify the exact hexadecimal payload.


168. Phase 3 — physical bus capture

For CAN:

BEANalyzer
  ↓
CAN Interface
  ↓
CAN bus
  ↓
independent receiver

The project has confirmed CANalyst-II TX at 500 kbps using an independent Arduino CAN receiver.

For BEAN:

BEANalyzer
  ↓
BEAN bridge
  ↓
BEAN wire
  ↓
independent capture

is still the correct validation principle.


169. Phase 4 — target ECU behavior

Physical bytes on the wire do not automatically prove:

target ECU understood them

Validate actual target behavior.

Examples:

cluster needle moves
warning lamp changes
A/C display updates
ECU state changes

Only then can target acceptance be considered vehicle-confirmed.


170. Phase 5 — timing validation

Test:

single frame
repeated frame
on-change
periodic
heartbeat
source stale
source recovery
long-duration operation

171. Phase 6 — loop validation

With both directions active:

verify no local CAN echo becomes BEAN feedback
verify no external gateway creates a repeated cycle

PART X — EVIDENCE CLASSIFICATION

172. Evidence levels

Recommended project labels:

CONFIRMED BY MANUFACTURER
CONFIRMED IN VEHICLE
CONFIRMED BY CAPTURE
CONFIRMED BY WORKING CODE
CORROBORATED
EXPERIMENTAL
HYPOTHESIS
PENDING VALIDATION
UNKNOWN

173. Example evidence chain

Formula implemented in Mapping composer
→ CONFIRMED BY CODE

CANalyst-II physically transmitted frame and Arduino received it
→ CONFIRMED BY CAPTURE

Generated BEAN frame observed on wire
→ CONFIRMED BY CAPTURE

IS200 cluster accepts generated frame
→ CONFIRMED IN VEHICLE

Do not merge those into one claim.


PART XI — JSON REFERENCE

174. BEAN → CAN document

{
  "format": "BEANalyzer_Gateway_Mapping",
  "version": 3,
  "name": "My BEAN to CAN Mapping",
  "notes": "",
  "mappings": []
}

175. CAN → BEAN document

{
  "format": "BEANalyzer_CAN_to_BEAN_Mapping",
  "version": 1,
  "name": "My CAN to BEAN Mapping",
  "notes": "",
  "mappings": []
}

176. BEAN → CAN Mapping example

{
  "id": "mapping_001",
  "name": "Coolant to CAN",
  "enabled": true,
  "notes": "",
  "match": {
    "bus": "BEAN",
    "context": null,
    "did": "FE",
    "mid": "2C",
    "data_len": 1
  },
  "trigger": {
    "mode": "on_bean_message",
    "period_ms": 100,
    "heartbeat_ms": 1000
  },
  "stale": {
    "timeout_ms": 1000,
    "action": "suppress_frame",
    "invalid_value": 0
  },
  "output": {
    "bus": "CAN",
    "id": "0x500",
    "extended": false,
    "dlc": 8
  },
  "fields": []
}

null selector corresponds to:

ANY

in conceptual UI use.


177. CAN → BEAN Mapping example

{
  "id": "can_to_bean_001",
  "name": "CAN500 Coolant to BEAN",
  "enabled": true,
  "notes": "",
  "match": {
    "bus": "CAN",
    "id": "0x500",
    "extended": false,
    "dlc": 8
  },
  "trigger": {
    "mode": "on_can_message",
    "period_ms": 100,
    "heartbeat_ms": 1000
  },
  "stale": {
    "timeout_ms": 1000,
    "action": "suppress_frame",
    "invalid_value": 0
  },
  "output": {
    "bus": "BEAN",
    "did": "62",
    "mid": "2C",
    "data_len": 1
  },
  "fields": []
}

178. Raw field JSON example

BEAN → CAN:

{
  "name": "CoolantRaw",
  "enabled": true,
  "source": {
    "type": "bean_raw",
    "byte": 0,
    "bit": 0,
    "length": 8,
    "byte_order": "little",
    "signed": false
  },
  "destination": {
    "start_bit": 8,
    "length": 8,
    "byte_order": "little",
    "signed": false
  },
  "encoding": {
    "scale": 1.0,
    "offset": 0.0,
    "clamp_min": 0,
    "clamp_max": 255
  }
}

CAN → BEAN equivalent source:

"type": "can_raw"

179. Expression JSON example

{
  "source": {
    "type": "expression",
    "expression": "((raw0 << 8) | raw1) / 5.12"
  }
}

CAN → BEAN:

{
  "source": {
    "type": "expression",
    "expression": "(((can3 << 8) | can4) * 32) / 25"
  }
}

180. Counter JSON example

{
  "source": {
    "type": "counter",
    "bits": 4,
    "initial": 0,
    "step": 1,
    "wrap": 16
  }
}

181. Checksum JSON example

{
  "source": {
    "type": "checksum",
    "algorithm": "crc8",
    "from_byte": 0,
    "to_byte": 6,
    "poly": "0x07",
    "init": "0x00",
    "xorout": "0x00"
  }
}

PART XII — PRACTICAL DESIGN TEMPLATES

182. Template: direct raw translator

Use when source and destination intentionally share the same raw representation.

Source:
raw byte/bit

Encoding:
scale = 1
offset = 0

Destination:
same bit length

Advantages:

simple
easy to verify
minimal numerical ambiguity

183. Template: semantic translator

Use when protocols encode the same physical value differently.

Example:

BEAN RPM raw / 5.12
→ physical RPM
→ destination uses 0.25 rpm/bit

Use decoded signal:

rpm

Destination encoding:

scale = 0.25
offset = 0

At:

3000 rpm

destination raw:

12000 = 0x2EE0

184. Template: status normalizer

Source status may use a mask:

raw0 & 0x40

Normalize:

1 if (raw0 & 0x40) else 0

Destination can then use:

one bit

or:

one byte

185. Template: packed gateway frame

Use decoded-signal state cache.

Example CAN frame:

B0 temperature
B1 coolant
B2 speed
B3-B4 RPM
B5 status
B6 counter
B7 checksum

This is a good architecture when one external CAN node needs a compact vehicle-state summary.


186. Template: fan-out CAN → BEAN

One CAN frame:

0x500

contains several values.

Create multiple mappings:

Mapping 1 → BEAN outside
Mapping 2 → BEAN coolant
Mapping 3 → BEAN speed
Mapping 4 → BEAN RPM

Do not create one BEAN message containing unrelated MIDs.


187. Template: event-to-state conversion

CAN event byte:

1 = active
0 = inactive

BEAN target needs bit4.

Source:

can0

Destination:

start_bit = 4
length = 1

If CAN source can contain values other than 0/1, normalize:

1 if can0 != 0 else 0

188. Template: state-to-event conversion

BEAN bit:

raw0 & 0x10

CAN target byte:

0xAA active
0x55 inactive

Expression:

0xAA if (raw0 & 0x10) else 0x55

Destination:

8 bits

PART XIII — FINAL CHECKLIST

189. Before Save

Verify:

Mapping name descriptive
Enabled intentional
Selector not too broad
Trigger intentional
Stale behavior intentional
Output ID/DID/MID correct
DLC/DATA length correct
Every field enabled intentionally
Start bits non-overlapping unless overlap is intentional
Endianness correct
Signedness correct
Scale non-zero
Clamp values sensible

190. Before physical transmission

Verify:

Preview exact hex output
Independent expected calculation
Bench network controlled
Correct bitrate
Correct CAN standard/extended mode
BEAN bridge connected if CAN → BEAN
CAN Interface connected if BEAN → CAN

191. Before automatic runtime

Verify:

Manual test successful
Physical frame captured
Target behavior understood
Trigger frequency safe
Stale policy safe
No feedback loop
Long-duration traffic acceptable

192. Final engineering rule

Every Mapping should be reconstructable as:

WHAT was mapped
WHY it was mapped
HOW the source was selected
HOW the value was decoded
HOW the value was encoded
WHERE the bits were placed
WHEN the message was transmitted
HOW stale data was handled
WHAT was physically observed
WHAT the target ECU did
WHAT remains unverified

If those answers are documented, the Mapping is maintainable.

If they are not, it is only an experiment.


193. Quick UI cheat sheet — BEAN → CAN

Devices / CAN Gateway
  ↓
Open BEAN → CAN Mapping Editor
  ↓
Add
  ↓
Message
  ├─ Mapping identity
  ├─ BEAN match / source selector
  │    CTX = ANY / A3 / ...
  │    DID = ANY / FE / ...
  │    MID = ANY / 26 / ...
  │    Required DATA length = blank / 1 / 2 / ...
  ├─ Transmit policy
  │    Trigger
  │    Period
  │    Heartbeat
  ├─ Stale-source policy
  │    Timeout
  │    Action
  │    Invalid value
  └─ CAN output frame
       CAN ID
       Extended
       DLC

Payload Fields
  ↓
Add field
  ├─ Source
  ├─ Destination
  └─ Encoding

Preview / Test
  ↓
Compose CAN Preview
  ↓
Send Test Frame via CAN Interface

Raw JSON

194. Quick UI cheat sheet — CAN → BEAN

Devices / CAN Gateway
  ↓
Open CAN → BEAN Mapping Editor
  ↓
Add
  ↓
Message
  ├─ Mapping identity
  ├─ CAN match / source selector
  │    CAN ID
  │    Extended
  │    Required DLC
  ├─ Transmit policy
  │    Trigger
  │    Period
  │    Heartbeat
  ├─ Stale-source policy
  │    Timeout
  │    Action
  │    Invalid value
  └─ BEAN output application message
       DID
       MID
       DATA length

Payload Fields
  ↓
Add field
  ├─ Source
  ├─ Destination
  └─ Encoding

Preview / Test
  ↓
Compose BEAN Preview
  ↓
Send Test Frame via BEAN

Raw JSON

195. Current implementation limitations to remember

Classic CAN only in these Mapping paths
CAN payload maximum = 8 bytes
CAN → BEAN DATA maximum = 14 bytes
CAN → BEAN live input is normally raw-byte based
No automatic CAN-DBC decoder in the current live CAN Interface path
CAN selector currently matches ID / Extended / DLC, not arbitrary payload signatures
Big Endian multi-byte fields must be byte-aligned
Local CAN echo protection is not a universal distributed-loop detector
BEAN transmit DID semantics such as FE vs 62 must be validated for the actual bridge/target path

AE&D — Anyzun Electronics & Development BEANalyzer UltraPro 5 BEAN ↔ CAN Mapping Design Guide — Expanded Engineering Edition