You are on page 1of 20

P38 BECM communications - BeaDy http://www.beady.

com/blog/p38-becm-communications/

/* */
 MENU

BeaDy Never a dull day

P38 BECM communications


 6th April 2020

When making my p38 camper I needed to make a new wiring loom but still wanted to
keep the look of the P38 internally as I feel it is a very tidy interior, I also wanted to
remove the BECM and make a small neater one that did the bits I just needed.

The BECM talks to all the other systems (ABS,ENGINE,HVAC) via simple wires going hi
and lo to indicate errors or status,

The outstations in the doors, display and the switch panel use a form of serial comms to
talk to each other.

I only reverse-engineered the display but the comms system is the same on the others it
will take someone else to sni�f the codes using a simple cheap Arduino.

There is a working arduino sketch at the end of the post.



you just need three wires to the display, +12v and ground to make it work with any of the

1 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

components. , if you only want to listen then you can just sni�f the data wire, to know
 MENU
which is sending the data is a little harder to do, because you cant detect which end
pulled the line low.

The system runs on three wires,

�. Clock wire

�. Data Direction

�. Data wire

�. ground is always needed �

The data wires to the display are easy to get to on the BECM they are on the plug just
below the fusebox and can easy be identi�ied because of the dual coloured wires. push a
paperclip into the data wire and connect that to the a input pin on the arduino with a 1k
resistor in series then connect a earth from the car to your arduino and then make a
sketch to relay, use 4800 8N1 bps comms on the BECM wire to the serial monitor on the
computer. then press things or make things happen on the car and see what gets sent
to/from the BECM. you should see the mileage being sent from the display to the BECM
it is easy to work it out.

Bytes : A6 13 83 73 45

A6 is the code to says its mileage then the mileage is in plain text here the mileage is
138373 (45 is the checksum)

Here is how the connections are wired into the switch panel for the windows

2 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

 MENU

three wires OG,LG and � (black = GND)

on the display the signals wires are doubled up for reliabilty . 

3 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

 MENU

basically there is a red a green and a orange wire 2 & 12 ,3 & 13 , 5 & 15

orange is Data direction

4 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

red is clock signal


 MENU

green is the actual data

the clock wire runs at 4.8 khz

the data dir wire is pulled low when sending data, you must wait 5ms before writing to
the data line a�ter pulling this low

and the data is 4800 8N1 just like any rs232

So what does this data ?


The data is in 10 byte blocks

which consist of two 5 byte sections


byte 0 : ID
byte 1 : data
byte 2 :data
byte 3 :data
byte 4 : Checksum byte : bytes 0,1,2,3 all XORed together

The display sleeps if it doesn’t get a valid data stream, so if you have power and nothing
is on the screen then your data stream is wrong somehow.

to keep the screen awake when you dont need to send any data then you must send AA
AA AA AA cs 00 which is the keep alive signal

Byte 1 is the control/action code

• 0xA5 : is the lights on the display

• 0x00 : are messageson the upper line of the LCD, I pressume these vary by Display
�OM, you can set the language

• 0x0F : message on the lower line of the LCD



0x

5 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

OK, if you now used my Arduino sketch and have the hazard lights on the display going
 MENU
on/o�f what else can you send to the display?

Here is what I have found that you can send the display, I didn’t decode the data coming
from the display because I didn’t need it.

Byte Hex bit Function


#

1 A5   {lighting }

2   …. Le�t indicator
…0

    …. Main beam indicator


. .1.

    …. Right indicator
.2. .

    …. Brake warning light


3…

    …4 Low fuel light


….

    . .5. Over temp light


….

    .6. . Traction control light


….

    7… Seat belt light


….


3   …. BATT light

6 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

…0
 MENU

    …. Oil light
. .1.

    …. ABS light
.2. .

    …. Heater plugs light


3…

    …4 Engine check light


….

    . .5. Nothing ???


….

    .6. . Transfer box warning


….

    7… Trailer light
….

4   ….  
…0

    …. SRS light? Gauges ON must be set to make gauges


. .1. work I.e. BYTE 4 must be at least 0x06 for back light
to be on and the gauges working.

    …. LCD back Light


.2. .

    …. Side light indicator


3…

7 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

    …4 Air susp MENU
up light
….

    . .5. Nothing ??
….

    .6. . Nothing ??
….

    7… Nothing??
….

5     CS �irst 4 bytes XORed together

       

Byte # Hex bit function

1 00   {messages}

2   0x_0 english

    0x_1 french

    0x_2 german

    0x_3  

    Upper nibble ??

       

        

8 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

       
 MENU

3   0x00 Same as byte 4 but for lower LCD line

       

       

       

       

       

       

       

4   Message On upper line of lcd

    0x00 to 0x16 “FUSE  xx  failed”

    17 Right dip beam

    18 Le�t dip beam

    19 RH main beam

    1A LH main beam

    0x33 “Check oil level”

    0x34 “Engine oil overheat”


9 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

    0x35 “gearbox overheat”


 MENU

    0x36 Transfer overheat

    0x48 Ignition key in

    0x49 Lights on

    0x4b Overspeed

    0x4e Fuel guage fault

    0x4f Temp guage fault

    0xA1 Diagnostic mode

    0xa3 Start engine

    0xA6 SLOW DOWN

    0xA8 ICE alert

    0x�f Test pattern

       

Byte # Hex bit function

1 0F   0x59 messes this up

2   Bit 0-3  0-7 P N � D 2 1in lcd


       

10 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

    Bit 3  MENU LOW or L if PDRN is shown

    Upper nibble  

    1 SPO�T

    2 high

       

       

3   … . …0  

    … . . .1.  

    … . .2. .  

    … . 3…  

    …4 … .  

    . .5. … .  

    .6. . … .  

    7… … .  

4   … . …0  

    … . . .1.  

    … . .2. .  

11 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

    … . 3…  MENU  

    …4 … .  

    . .5. … .  

    .6. . … .  

    7… … .  

5      

       

0x55 fuel and temp gauge

Warning lights come on automatic, but can be tested using  A5

0x49 temp warning light comes on

0x97 low fuel light comes on

NOTE

AA AA AA AA cs 00   = 0 keep alive

If not received by dash or another message then display goes into fail mode.

Warning about temp and fuel and both  gauges go to min fuel and max temp

erors and wierd stu�f

If the DI� wire is disconnected the dash goes into sleep 

12 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

0x59 does something wierd but never worked out what


 MENU

0x15   turns stu�f o��?

A6,, message strategy?

{0x5a,0x9B,0xF5,0x00,0x3B,0xA5,0x00,0x00,0x04,0xA0};

This was Making the overall mileage run up

Arduino sketch for P38 BECM comms


Here is a working Arduino sketch , if you know what an arduino is then you knwo what
to do,

I think i used pull up resistor to get 12v lines from the 5v , but i am not full sure of this so
check, the signal will be inverted if I did

have fun and please send me updates.

1 #include <TimerOne.h>
2
3 /* comms with the P38 display
4 uses three lines + gnd
5 Dir is data direction low = arduino sending , high = arduino recieving
6 the DIR pin runs at 21hz, dont know if its driven by the BeCm as a master
7 so display wait for hi to txr its 5 byte block
8
9 Clk clock a 4.8 khz only runs when txring should be driven by display wh
10 Data data @4800 8n1
11
12 arduino sends 10byte blocks
13 which are 2 x 5 bytes
14 byte 0 ID
15 byte 1 data
16 byte 2 data
17 byte 3 data
18 byte 4 CS byte 0,1,2,3 all XORed together
19 */
20
21 //---------- define pins -----------------
22
23 #define TxrPin 2 //LG yw
24 #define DirPin 3 //OG gn

25 #define ClkPin 4 //RG be
26

13 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

27 // the pin directions changed with Dir pin subr


28  MENU
29 /*
30 interupt on timer for DIR pin which changes over the dir pin and sen
31 after 5ms of Dir_pin going low what ever is in the two txr buffers i
32 by the Transmit Subr.
33
34 the receive is ignored.
35 */
36
37 // vars to set the data direction pin timer
38 long DataDir_Period_txr = 27400; //should be 20hz 31.8 ms
39 long DataDir_Period_rxr = 15800; // 15 ms
40 long DataDir_Period_start_txr = 4400 ; // 5 ms
41 byte TransmitFlag ;
42
43 byte TxrBuffer[12]; // byte 5 and 10 are CS
44
45 /*
46
47 Chescksum in byte 5 and 10 is calced when the array is put in the
48 txr buffer so ignore it here
49 */
50
51
52 byte TxrBufferDefault[10] = {0xAA,0xAA,0xAA,0xAA,0x00,0xAA,0xAA,0xAA,0xAA
53 byte TxrBufferHazardOff[10] = {0xA5,0x00,0x00,0x06,0x00,0xAA,0xAA,0xAA,0x
54 byte TxrBufferHazardOn[10] = {0xA5,0x05,0x00,0x06,0xA0,0xAA,0xAA,0xAA,0xA
55 byte TxrBufferHazard_1[10] = {0x00,0xA0,0xA1,0x00,0x00,0xAA,0xAA,0xAA,0x
56 byte TxrBufferHazard_2[10] = {0x55,0xae,0x4a,0x00,0x3B,0xAa,0xaa,0xaa,0xa
57
58
59 // byte TxrBufferHazard_2[10] = {0xAA,0xAA,0xAA,0xAA,0x00,0xAA,0xAA,0xAA,0
60 byte incomingByte;
61 int i;
62 int SeqCount =0; //8 sets of def, then on, 8 defs, then off
63
64
65 //SHIFTOUT TIMING
66
67 long SETUP_TIME =11;
68
69 long CLOCK_HIGH = 96;
70 long CLOCK_LOW = 96;
71
72 void setup() {
73
74 // Initialize the digital pin as an output.
75 // Pin 13 has an LED connected on most Arduino boards
76 pinMode(13, OUTPUT);
77 TransmitFlag = 0;
78 Serial.begin(9600); // open the serial port at 9600 bps:
79 
80 Timer1.initialize(100000); // set a timer of length 100000 microseconds
81 Timer1.attachInterrupt( timerIsr ); // attach the service routine here

14 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

82 pinMode(DirPin,OUTPUT);
83  MENU
Serial.print("Started");
84
85
86 }
87
88
89 void loop() {
90
91 // send data only when you receive data:
92 if (Serial.available() > 0) {
93 // read the incoming byte:
94
95 TxrBuffer[0]= Serial.parseInt();
96 TxrBuffer[1]= Serial.parseInt();
97
98 TxrBuffer[2]= Serial.parseInt();
99
100 TxrBuffer[3]= Serial.parseInt();
101 TxrBuffer[4] = TxrBuffer[0] ^ TxrBuffer[1] ^ TxrBuffer[2]
102 // say what you got:
103 Serial.print("I received: ");
104 for (i = 0; i < 9; i = i + 1) {
105 Serial.print(TxrBuffer[i],HEX);
106 Serial.print(" ");
107 }
108 Serial.println();
109 }
110
111
112 }
113
114
115
116
117 /// --------------------------
118 /// Custom ISR Timer Routine
119 /// --------------------------
120 void timerIsr()
121 {
122 uint8_t i;
123 // Timer1.stop(); //stop the counter
124 // Toggle LED
125 digitalWrite( 13, digitalRead( 13 ) ^ 1 );
126 if (TransmitFlag == 0 ){
127 //set the pinmode to out put
128 TransmitFlag = 2;
129
130 digitalWrite(DirPin,HIGH);
131 digitalWrite(ClkPin,LOW);
132 digitalWrite(TxrPin,LOW);
133 pinMode(TxrPin,OUTPUT);
134 pinMode(ClkPin,OUTPUT); 
135 Timer1.initialize(DataDir_Period_start_txr);
136

15 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

137
138 } else if(TransmitFlag MENU
== 1){
139 //set to rxr input
140 TransmitFlag = 0;
141 pinMode(TxrPin,INPUT);
142 pinMode(ClkPin,INPUT);
143 digitalWrite(DirPin,LOW);
144 Timer1.initialize(DataDir_Period_rxr);
145 delayMicroseconds(4900);
146 for (i = 0; i < 51; i = i + 1) {
147 digitalWrite(ClkPin, HIGH);
148 delayMicroseconds(CLOCK_HIGH);
149 digitalWrite(ClkPin, LOW);
150 delayMicroseconds(CLOCK_LOW);
151
152
153 }
154
155
156
157 } else {
158 //set to 5ms delay to start transmit
159 TransmitFlag = 1;
160 Timer1.initialize(DataDir_Period_txr);
161 // now tranmit the buffer bytes
162
163 TransmitBuffer();
164 }
165
166
167 //Timer1.restart();
168 }
169
170 void TransmitBuffer(){
171
172
173 // after transmit fill the buffer with the idle transmit 0xAA 0xAA 0xAA
174 // for both 5 byte lumps
175 SeqCount = SeqCount + 1;
176
177
178
179
180 if (SeqCount == 19){
181
182 for (i = 0; i < 10; i = i + 1) {
183 TxrBuffer[i] = TxrBufferHazardOn[i];
184 CS_calc();
185 SeqCount =0;
186 }
187 } else if ( SeqCount == 17){
188 /*TxrBufferHazard_1[1]++;
189 //TxrBufferHazard_1[2]++; 
190 //TxrBufferHazard_1[3]++;
191 Serial.print(TxrBufferHazard_1[2]);

16 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

192 Serial.print("\n");
193 if (TxrBufferHazard_1[1]  MENU
== 10){
194 TxrBufferHazard_1[1]=0;
195 }
196 */
197 for (i = 0; i < 10; i = i + 1) {
198 TxrBuffer[i] = TxrBufferHazardOff[i];
199 CS_calc();
200 }
201 } else if ( SeqCount == 1 ){
202 for (i = 0; i < 10; i = i + 1) {
203 TxrBuffer[i] = TxrBufferHazard_1[i];
204 CS_calc();
205 }
206
207 } else if ( SeqCount == 2){
208 for (i = 0; i < 10; i = i + 1) {
209 TxrBuffer[i] = TxrBufferHazard_2[i];
210 CS_calc();
211
212 }
213
214 } else {
215 for (i = 0; i < 10; i = i + 1) {
216 TxrBuffer[i] = TxrBufferDefault[i];
217 CS_calc();
218
219 }
220 }
221
222 // transmits two 5 byte blocks together @4800 bps and controlls the cl
223 // using shiftout
224
225 for (i = 0; i < 10; i = i + 1) {
226 // shiftOut(TxrPin,ClkPin,MSBFIRST,TxrBuffer[i]);
227 putByteInvert(TxrBuffer[i]);
228 }
229
230
231 }
232
233 //------------------------------ CHECKSUM --------------------------------
234 void CS_calc(){
235
236 TxrBuffer[4] = TxrBuffer[0] ^ TxrBuffer[1] ^ TxrBuffer[2] ^ TxrBuffer[3];
237 TxrBuffer[9] = TxrBuffer[5] ^ TxrBuffer[6] ^ TxrBuffer[7] ^ TxrBuffer[8];
238
239
240
241
242 }
243
244 
245 void putByte(uint8_t value) {
246 uint8_t mask = 0x01, i;

17 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

247 // start bits


248  MENU
249 digitalWrite(ClkPin, LOW);
250 delayMicroseconds(SETUP_TIME);
251 digitalWrite(TxrPin,LOW);
252 delayMicroseconds(CLOCK_LOW-SETUP_TIME);
253
254 digitalWrite(ClkPin, HIGH);
255 delayMicroseconds(CLOCK_HIGH);
256
257
258
259
260 for (i = 8; i > 0; i--) {
261 // decide if delay is needed on gpoing low by 15.8ms
262 //if ((value & mask) != 0){
263 digitalWrite(TxrPin, value & mask);
264 digitalWrite(ClkPin, LOW);
265 delayMicroseconds(CLOCK_LOW);
266 /* }else {
267 digitalWrite(ClkPin, LOW);
268 delayMicroseconds(SETUP_TIME);
269 digitalWrite(TxrPin, value & mask);
270 delayMicroseconds(CLOCK_LOW-SETUP_TIME);
271 }
272 */
273 digitalWrite(ClkPin, HIGH);
274 delayMicroseconds(CLOCK_HIGH);
275
276 mask <<= 1;
277 }
278 //stop bits
279 digitalWrite(TxrPin,HIGH);
280 digitalWrite(ClkPin, LOW);
281 delayMicroseconds(CLOCK_LOW);
282 digitalWrite(ClkPin, HIGH);
283 delayMicroseconds(CLOCK_HIGH);
284
285
286
287
288 }
289
290
291 void putByteInvert(uint8_t value) {
292 uint8_t mask = 0x01, i;
293 // Serial.write(value);
294
295 // for use with bc547 drive tranny
296 // start bits
297
298 digitalWrite(ClkPin, HIGH);
299 delayMicroseconds(SETUP_TIME); 
300 digitalWrite(TxrPin,HIGH);
301 delayMicroseconds(CLOCK_HIGH-SETUP_TIME);

18 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

302
303  MENU
digitalWrite(ClkPin, LOW);
304 delayMicroseconds(CLOCK_LOW);
305
306
307
308
309 for (i = 8; i > 0; i--) {
310 // decide if delay is needed on gpoing low by 15.8ms
311
312 digitalWrite(TxrPin, !(value & mask));
313 digitalWrite(ClkPin, HIGH);
314 delayMicroseconds(CLOCK_HIGH);
315
316 digitalWrite(ClkPin, LOW);
317 delayMicroseconds(CLOCK_LOW);
318
319 mask <<= 1;
320 }
321 //stop bits
322 digitalWrite(TxrPin,LOW);
323 digitalWrite(ClkPin, HIGH);
324 delayMicroseconds(CLOCK_HIGH);
325 digitalWrite(ClkPin, LOW);
326 delayMicroseconds(CLOCK_LOW);
327
328
329
330
331 }

Please add/correct me on any info here so we can build


a good knowledge of this subject
Share your joy of knowledge with the world. .

Previous Post Next Post

One thought on “P38 BECM communications”

P38 Autobox Comms With The M57 Engine – BeaDy



7th April 2020 at 11:30 am

19 of 20 9/30/2022, 8:47 PM
P38 BECM communications - BeaDy http://www.beady.com/blog/p38-becm-communications/

[…] Simple hack for the P38 BECM serial communications […]
 MENU
Reply

Leave a Reply
Your email address will not be published. Required �ields are marked *

Comment *

wwww.BeaDy.com Masonry Blog, WordPress theme by Perfectwpthemes

Name

Email

Website

Post Comment

20 of 20 9/30/2022, 8:47 PM

You might also like