duzgun.org/blog
Blue&Me replacement/ Alfa Romeo Giulietta 940/ 2011 · 2.0 JTDm 140

From broken hardware to music and calls in the car

I replaced the broken Magneti Marelli Blue&Me module (50521871) with a Raspberry Pi Zero W. It responds to the Body Computer, reads the steering-wheel buttons, plays Bluetooth music and handles phone calls through the original radio and the car's own microphone.

Status, 2026-10-12: installed in my car since 1 October 2026. The car accepts it, and music, track text and the wheel buttons work. Calls work again: I tested them on 2026-10-11 with the unit fully installed, after fixing two ground faults on the bench (step 15). The person I call still hears a slight echo, which I have left for later.
  • 3.3 V rail
  • 5 V rail
  • Ground
  • Hazard

01 Read this first

In the previous post I explained what this project is and why I built it. In this guide I explain how I did it, in fifteen steps from the first checks to music and calls in the car.

The measurements come from my hardware and my car. Another car may give different results. That is why I started with measurements and recordings before transmitting messages or making further connections.

The software is on GitHub: github.com/crimeofheart/giulietta-blue-me.

Listening first

I could not find published CAN information for the Giulietta 940. I started from fmntf/fiatcan for the Fiat Doblò 263 and karolkrupa/alfa-blue-me for the Alfa 159. But they describe other cars and differ on many message identifiers. I compared the messages with recordings from my own car. Each message in the software's tables has a reference to its recording, and the transmit gate only allows messages supported by those recordings.

A fresh install is listen-only, in two layers: the CAN controller is in listen-only mode, and the application's list of frames it may send is empty. Wired to a live car it receives and decodes, and cannot transmit. Transmitting is switched on in step 12, by a command, and switched off by the same command.

Why the usual approach is unavailable

At the start, I did not have a working module to record, and the car was configured without Blue&Me. So I recorded the car twice: first as it was, then after telling the Body Computer to expect a Blue&Me module. Comparing those recordings with blueandme-diff showed what the car was looking for (step 10). Later, the broken module's remaining traffic gave me more frame IDs, as I describe in the post.

One value is your car's alone

The PROXI value comes from the car being fitted, not from my build. It is the six bytes the modules send when the Body Computer asks. I left mine out of the published code, which reads the value from a setting instead. Step 10 shows how it is read from a recording; step 12 shows where it goes in the Pi's configuration.

Legend used throughout: bench cannot affect the car · car touches the vehicle bus. Steps 1–6 are bench work. Step 7 is the first contact, listen-only. Step 12 is the first time the Pi transmits anything.

Required components

Sorted from what you cannot do without to what you can skip. Tools come last.

ComponentQtyNotes
Crucial
Raspberry Pi Zero W, with its 40-pin header1Bluetooth and Wi-Fi on board, one core, about 1 W. Not the Zero without W.
microSD card, 16 GB or more1For Raspberry Pi OS Lite, 32-bit (step 3). 16 GB is the minimum Raspberry Pi recommends for the Lite image. Mine is a SanDisk 64 GB.
MCP2515 + TJA1050 CAN module1The common blue board. Note its crystal, 8 or 16 MHz. Needs two modifications (steps 1–2). An SN65HVD230 board avoids them.
USB sound card with audio output and microphone input1Any card that Linux detects as a USB audio device should work, C-Media based or not. Mine is a Ugreen USB-A adapter with a C-Media HS-100B: stereo out, mono microphone in. Two things to check on another card: its headphone sleeve must be a true ground, and its name in aplay -l (step 13). The microphone input matters only for calls.
3.5 mm stereo cable1From the card's headphone jack to the radio's audio pins (step 14).
12 V to 5 V buck converter, USB output1Mine is a TECNOIOT 6–24 V to 5 V USB step-down module. The Pi draws up to about 0.3 A. The converter must hold its output while the engine cranks: test it on a bench supply first (step 15).
Header pins, 2.54 mm, 0.64 mm square32Four strips of eight. They fit the car's plug directly.
Perfboard strip, 2 × 16 holes with a 5 mm frame1Cut from a piece of perfboard. It holds the 32 pins and is the connector to the car's plug (step 15).
Hook-up wire, heat-shrink, glueThin wire for the 5 V modification in step 2.
Recommended
Electrolytic capacitor, 2200 µF, 35 V or more1Crank hold-up, across the buck's input (step 15).
Diode, 1N5822 or 1N40071Crank hold-up, between pin 16 and the capacitor.
PN2222 transistor1Ignition wake: the key restarts the Pi after a parking longer than three days. Without it, pull and refit fuse F36.
Diode, 1N40071Ignition wake, across base and emitter.
Resistor, 100 kΩ2Ignition wake.
Perfboard, 3 × 7 cm110 × 24 holes, 2.54 mm. Carries the crank hold-up and the ignition wake.
The original Blue&Me case1The broken module's own. It fits the factory bracket and Bluetooth passes through its plastic.
Printed sled: frame and tray1PETG or ASA. PLA softens in a parked car.
M3 screws and standoffs, cable ties4 mm standoffs under the CAN module, 5 mm under the Pi. Ties hold the buck and the sound card.
Optional: hands-free calls
3.5 mm cable1From the microphone circuit into the card's microphone jack.
Resistor, 2 kΩ1Microphone feed.
Resistor, 1 kΩ2One beside the 2 kΩ in the feed, one in the divider.
Resistor, 10 kΩ1Microphone divider.
Electrolytic capacitor, 10 µF, 10 V or more1Keeps the microphone's DC off the card.
Optional: convenience
Micro-USB OTG adapter1For the bench. In the case the card is soldered to the Pi (step 15).
Ceramic capacitor, 100 nF1Only if the CAN transceiver has none at its supply (step 2).
Tools
Multimeter, soldering iron, scalpelCrucial. The meter is the important one.
A phone1Crucial. The one that will play the music.
USB power bank1Crucial. Powers the Pi for all work at the car until step 15.
OBD adapter and MultiEcuScan on a Windows tablet1Crucial for the alignment in step 10.
Adjustable bench supply1Recommended. To sweep the buck converter before it goes in the car.
3D printer1Optional. For the sled and its test sheets.

02 Bench build steps 1–6

Step 1 — Identify your MCP2515 module

Two facts to establish before anything is wired.

a) Crystal frequency

I started with the crystal marking on the CAN board: 8.000 means 8 MHz, 16.000 means 16 MHz. A well-lit close-up helps if the marking is hard to read. This value has to be right in the installer; otherwise the bus will look silent later, even with the wiring correct.

b) Terminating resistor

With nothing connected, measure resistance between the CAN-H and CAN-L screw terminals with a multimeter.

  • ~120 Ω → there is a terminator on the board. Remove it. On the common blue MCP2515+TJA1050 board it sits directly between the two terminals, silkscreened 120R and marked 121. Desolder it, or lift one leg.
  • Tens of kΩ → no terminator. This is the pass, and it is not an open circuit: the TJA1050's own differential input resistance stays across the pins permanently, roughly 20–100 kΩ. With the transceiver fitted you will never read infinity, so do not go hunting for a resistor that is not there.
Why the terminator has to go

The car's B-CAN is already terminated at both ends. Adding a third terminator lowers the differential impedance and can stop the bus working for every module on it, not just yours. Two builders before me hit exactly this: karolkrupa on the Alfa 159 and a fiatcan user on the Doblò. Note the contrast with fmntf, who added a 120 Ω jumper: he was probing a single isolated ECU on a bench, where nothing else terminates the bus. Bench and car want opposite things here.

Established for this build

ValueConsequence
Crystal8 MHzinstall.sh --oscillator 8000000
Terminator (121, 120 Ω)desolderedCAN-H↔CAN-L then read 45 kΩ — transceiver only, terminator gone
Stop condition

You know the crystal frequency, and CAN-H↔CAN-L reads far above 120 Ω — tens of kΩ is correct, a true open circuit is not expected.

Step 2 — Solve the 5 V problem

The board has a single VCC pin feeding both chips. That is the whole problem.

The TJA1050 transceiver needs 5 V to drive a CAN bus — it is specified for 4.75–5.25 V and has no 3.3 V mode. So the board gets fed 5 V, the MCP2515 controller runs at 5 V too, and a chip running at 5 V drives its outputs to 5 V. One of those outputs is MISO, and MISO goes straight into the Pi's GPIO9, which is not 5 V tolerant and has no clamping diodes.

Unmodified — one rail at 5 VMCP2515VCC = 5.0 VMISO5.0 VGPIO9max 3.3damages the SoCSplit rails — controller at 3.3 VMCP2515VCC = 3.3 VMISO3.3 VGPIO9in specTJA1050 still on 5 V
The only edge that changes is the voltage on MISO. The SPI wiring, the transceiver's 5 V supply and the CAN side all stay as they were.
"It seems to work" is not evidence

Over-voltage on a GPIO may not fail immediately or visibly. It can leak current through the input's protection structures and damage the pin over time. A module that has run fine for an hour proves nothing. Do the modification before the first power-up.

Three ways out

Option A · recommended

Split the rails

Cut the copper track between the board's VCC pin and the TJA1050, then solder a wire to feed the transceiver 5 V separately.

One cut, one wire, no extra parts.

Option B

Level shifter on MISO

Leave the board at 5 V and put a 3.3 V/5 V shifter on the MISO line only — the one line driving toward the Pi.

No board surgery, but an extra part and three more joints in the SPI path.

Option C · no surgery

Buy a 3.3 V board

An SN65HVD230-based module runs natively at 3.3 V, controller and transceiver both.

Nothing to modify at all. Cheap. If cutting the board does not appeal, buy this instead.

Only MISO strictly matters. MOSI, SCK and CS are Pi outputs and MCP2515 inputs — the Pi drives 3.3 V into a 5 V chip, which reads it happily as a logic high. MISO and INT are the two lines pointing the other way, and INT is open-drain. That is why Option B works on MISO alone. Splitting the rails fixes all of them at once.

What "cut the trace" actually means

A trace is a printed copper track on the surface of the circuit board. It does the job of a wire: it is flat, a fraction of a millimetre wide, glued to the board, and covered by the green lacquer you can see (the solder mask). Every connection on the module is one of these.

Cutting it means physically severing that copper with a sharp blade so current can no longer flow along it — you scrape a small gap across the track, right through to the bare fibreglass underneath. It is not cutting the board itself, and nothing is bent or removed; you are making a deliberate break in one connection, roughly a millimetre wide, in a track thinner than a pencil line.

Once broken, the two ends are electrically separate. You then solder a wire to one of those ends and feed it from somewhere else. That is the entire modification: break one connection, then re-feed one side of it.

Before — one unbroken trackVCC pinTJA1050copper track, under green lacquerAfter — about 1 mm of copper scraped awaythe gapstill feeds the MCP2515 — your 3.3 V innow isolated — solder the 5 V wire here
Two views of the same track, magnified. The break is small — a scalpel scratch — but it is a real, permanent electrical separation, and a meter will show it as an open circuit.

Finding the right track without guessing

I located the track with the meter rather than relying on a board drawing. The same check works even when a module's layout differs from mine. With the meter on continuity, the sequence is:

  1. Put one probe on the board's VCC header pin and leave it there.
  2. Touch the other probe to each pin of the TJA1050 (the small 8-pin chip nearest the CAN screw terminals) until it beeps. That pin is its supply — pin 3 in the TJA1050's datasheet.
  3. Do the same on the MCP2515 (the larger chip) to find its supply pin. Note both.
  4. The copper running between the VCC pin and the TJA1050's supply pin is what you are cutting. Follow it by eye.

Now you know the two pins that must end up separated, and you can prove it afterwards rather than hoping.

Cut the transceiver side, not the controller side

Both directions give the same split rail. But leaving the header pin attached to the MCP2515 means the pin your jumper wire plugs into is the 3.3 V one — harder to get backwards later, and it matches every published write-up.

Cut on the correct side of the decoupling capacitor

There may be a small capacitor across the TJA1050's supply. It must stay with the transceiver, on the 5 V side of the cut. If the board has no capacitor there, solder a 100 nF between the transceiver's supply pin and ground once you are done.

What you need

  • Fine-tipped soldering iron and thin solder
  • Scalpel or hobby knife for the cut
  • Multimeter with continuity beep the important one
  • Thin insulated wire 28–30 AWG, ~60 mm
  • 100 nF ceramic capacitor only if there isn't one already
  • Magnifier or phone camera to find the track and check the cut
  1. Photograph the board first

    Close up, well lit, before you touch anything. If you lose track of which side is which mid-cut, that photo is the only way back.

  2. Scrape through the copper

    Scratch away the green lacquer across the track, then cut the copper beneath it. Two or three light passes with the blade held across the track, not along it. Aim for a gap about a millimetre wide, down to bare board.

    Light passes beat one heavy pass that gouges the board or slips into a neighbouring track.

  3. Prove the cut with the meter

    VCC header pin to TJA1050 supply pin: must now read open, no beep. VCC header pin to MCP2515 supply pin: must still beep. If either is the wrong way round, stop and re-read the board.

  4. Solder the 5 V wire

    Tin the exposed copper on the TJA1050 side of the gap and solder your wire to it. Keep it short, and anchor it with hot glue or tape — a wire that works loose in a car will take the pad with it.

  5. Check for shorts before applying power

    The two supply pins must now be independent of each other, and neither should be shorted to ground. Only then connect anything to the Pi.

12315 V wire soldered to theTJA1050 supply (red circle)2TJA1050 transceiver,marked NXP TJA1050/C3120R terminator, marked121 — removed in step 1photo: terilenard/mcp2515-tja1050-wiring
The same modification on a real board. The red circle is the original author's, marking where the 5 V wire lands — on the transceiver's side of the cut. Note 120R silkscreened below the chip: that is the terminator, and the part marked 121 is what you already desoldered in step 1.
Stop condition

MISO cannot present more than 3.3 V to the Pi. With the module powered and the Pi disconnected, the MCP2515's supply pin measures 3.3 V and the TJA1050's measures 5 V.

Step 3 — Flash the SD card

Use Raspberry Pi Imager on your dev machine.

  • OS: Raspberry Pi OS Lite (32-bit). Not the desktop version. 32-bit is required — the Zero W is ARMv6.
  • Open "Edit Settings" and set: hostname blueandme; SSH enabled (key or password); username and password; Wi-Fi SSID, password and country.

Boot the Pi from USB power with nothing else connected and wait about two minutes, then ssh <user>@blueandme.local.

Stop condition

You have an SSH shell on the Pi.

Step 4 — Install

# on your dev machine
git clone https://github.com/crimeofheart/giulietta-blue-me
cd giulietta-blue-me
rsync -a --exclude .git --exclude .venv ./ <user>@blueandme.local:~/giulietta-blue-me/

# on the Pi
cd ~/giulietta-blue-me
sudo ./install.sh --dry-run --oscillator 8000000     # read what it will do
sudo ./install.sh --oscillator 8000000               # 8 MHz, confirmed in step 1
sudo reboot

First run takes a while on a Zero W — the apt step is the slow part. On an OS release with no prebuilt package in packages/, it also compiles bluez-alsa for wideband calls, about ten more minutes (step 13). And it trims boot for a headless car unit: no initramfs, no display or camera drivers, none of the modem, disk or keyboard services, and the CAN and Bluetooth drivers loaded first (times in step 15). Run again on a working Pi, it takes about two minutes: it skips apt when every package is there and reinstalls only the application.

Stop condition

install.sh ends with "configuration is valid".

Step 5 — Wire the MCP2515 to the Pi

Power the Pi off first (sudo poweroff, wait for the LED to stop).

Find pin 1 before you count anything

Every number below is a physical pin position, and they are only meaningful once you know which end of the header is pin 1. Three ways to find it, in order of reliability:

  1. The square pad. Pin 1 is the only square pad on the board; all thirty-nine others are round. If the header is already soldered on, turn the board over and look at the solder joints from underneath.
  2. The J8 silkscreen outline. Pin 1 is the corner inside it nearest the microSD card slot.
  3. The card slot itself. Pin 1 is at that end of the header, never the far end where the RUN pads and the second mounting hole are.

From there, numbering advances in pairs along the header, away from the card slot: 1 and 2 at the corner, then 3 and 4, then 5 and 6. Odd numbers stay in the row nearer the card slot; even numbers in the row nearer the board's outer edge.

board's outer long edgeJ839GND45V22INT24CS13V319MOSI21MISO23SCK◀ microSD card slot is at this end — pin 1 is herefar end — RUN pads, 2nd mounting hole ▶Physical pin numbers, shown inside each pad. Odd pins are the row nearer the card slot.
Drawn the way the board actually sits: the row nearer the outer edge carries the even pins, the row nearer the microSD slot carries the odd ones, and pin 1 is at the card-slot end. Physical pin numbers, not GPIO numbers. The eight pins fall in three places — power at the pin-1 corner, SPI plus the interrupt two thirds along, and the module's ground at the far end, pin 39 (pin 6 carries the car's ground, step 7). The photograph below is the same header, same eight pads.
PIN 1the one square pad,at the microSD end14391921222324THE EIGHT PINS YOU USE — PHYSICAL NUMBERS13V3 → module VCC45V → TJA1050 wire39GND19MOSI21MISO22INT / GPIO2523SCK24CS / CE0Odd pins run along the row nearer the microSD slot. Even pins run along the row nearer the board's outer edge.Numbering advances in pairs away from the card slot: 1/2 at the corner, then 3/4, 5/6, and so on to 39/40.photo: Gareth Halfacree, CC BY-SA 2.0, via Wikimedia Commons — annotated
The same eight pins on a real Pi Zero W. This board has bare pads rather than a soldered header, which is what makes pin 1 visible: it is the only square pad on the whole board, and it sits at the end nearest the microSD card slot, inside the silkscreen outline marked J8. Every other pad is round. If your header is already soldered on, turn the board over — the square pad shows from underneath.
ModulePi signalPhysical pinNotes
VCC (MCP2515, after the cut)3.3 V1Feeds the controller only
TJA1050 supply — your added wire5 V4Pin 2 is equivalent
GNDGND39One ground is enough; any ground pin works. On this build pin 6 carries the car's ground (step 7)
CSGPIO8 / CE024Matches spi0-0 in the overlay
MOSIGPIO1019Pi drives, module listens
MISOGPIO921The line the modification exists for
SCKGPIO1123Clock
INTGPIO2522Must match interrupt=25 in the overlay
123451CAN-H / CAN-L screw terminals2the added 5 V wire, in yellow3crystal — 8.000 or 16.0004MCP2515 controller58-pin header, ribbon to the Piphoto: terilenard/mcp2515-tja1050-wiring
The finished article. The yellow flying wire is the whole modification — it leaves the board at the transceiver and goes to a 5 V pin on the Pi, while the header strip below carries 3.3 V, ground and the four SPI lines.
Easy to get wrong

MOSI and MISO swapped. It does no damage, it just produces a bus that never initialises — and it looks identical to a wrong crystal value. Check twice now rather than debugging it later.

Power up and check:

blueandme-status

Expect interface present ok, link state UP, bitrate 50000, bus errors 0, spidev present ok. If can0 does not exist:

dmesg | grep -i -E "mcp251|spi"      # driver probe failures show here
ls /dev/spidev*                       # SPI enabled?
grep -E "spi|mcp2515" /boot/firmware/config.txt

mcp251x spi0.0: MCP2515 successfully initialized is what you want. Cannot initialize MCP2515 points to the wiring or to a wrong oscillator value.

Stop condition

blueandme-status shows can0 up at 50000 with zero errors.

Step 6 — Prove the software works, with no car

Everything can be exercised over a virtual CAN interface before the car is involved.

sudo modprobe vcan
sudo ip link add dev vcan0 type vcan && sudo ip link set up vcan0
tests/fixtures/fetch.sh               # once: the Doblò recordings some tests read
python3 -m pytest                     # the vcan0 tests now run too
blueandme-protocol-map                # the profile tables, generated from code
Stop condition

Full suite green, and the protocol map prints the Giulietta profile's frames.

03 In the car steps 7–10

Power, every time

Power the Pi from a USB power bank for all capture work. Do not connect vehicle 12 V to the Pi. Do not connect the Pi's USB to the car. If you are driving it from a tablet, keep that on its own battery too — a tablet charging from the car while tethered to the Pi creates exactly the ground path the power bank exists to avoid.

Step 7 — First contact: listen only

Two connectors in my car matter, and they are for two different machines. Do not confuse them.

Pi and connected boards beside the open dashboard.
The temporary replacement during an early test in the car. The sound card and the breadboard seen here are not part of this step; they come later in the guide.
THE PI — records the busBlue&Meconnectorvacant —module removedCAN-H · pin 30CAN-L · pin 14GND · pin 15 — goes past the module, straight to a Pi ground pinMCP2515 moduleH L2-wayscrew blockSPIPi Zero Wlisten-onlyUSBpower bankTHE TABLET — talks to the ECUs (step 10 only)OBD2 socketunder the dashpins 6 / 14USB OBD adapterWindows tabletAlfaOBD / MultiEcuScanThe two paths never touch. Both connectors are live at once in step 10, which is why the Pi does not use OBD2.
The Pi taps the vacant Blue&Me connector. The tablet uses the OBD2 socket. Keeping them separate is what lets capture H record the bus while the alignment that changes it is being performed.

What you are looking for

The harness-side plug is the half that stays in the car: a blue housing with a black locking lever, the loom entering from the back and two rows of small square cavities on the mating face. Since the original module was removed it is vacant and hanging loose, which is what makes this tap possible without cutting into the loom.

The photographs identify the two connectors and their moulded numbers. They do NOT tell you what each pin carries: that is the map below. The two photos were not taken the same way up, so compare the moulded numbers, not the positions.

Blue male connector recessed in the original module housing.
The module-side connector, viewed from the mating face.
Blue female connector with visible corner numbers and latch landmarks.
The car-side connector, viewed from the mating face; the moulded corner numbers remain visible.
Car plug, 32 ways — pin 16 top left, pin 32 bottom left, pin n+16 directly below pin n16+12V PERM515GND314CAN-L31312111098MIC TIP1765AUD L24GND32132IGNITION43130CAN-H3292827262524MIC GND12322AUD R221AUD GND2201918171 mic2 audio3 CAN4 ignition5 12 V to the buckgroundnot wired
StepPinLabelWire to
18MIC TIP (mic +)Joint A of the mic circuit: 2 kΩ ‖ 1 kΩ (about 670 Ω, kept at the car) from Pi pin 2 (5 V), and the 10 µF's + leg. The signal leaves joint B for the mic plug's tip
124MIC GND (mic −)Joint G, the ground joint
25AUD LAudio plug tip
222AUD RAudio plug ring (middle)
221AUD GNDAudio plug sleeve. The plug goes in the sound card's headphone jack
330CAN-HMCP2515 screw terminal H
314CAN-LMCP2515 screw terminal L
315GNDJoint G, which also carries the Pi's ground (pin 6). Step 5 adds a second wire here, to the board's K1 (crank hold-up, then buck IN−)
432IGNITIONThe ignition wake: its 100 kΩ to the PN2222 base. 12 V in MAR, never onto a Pi pin
516+12V PERMThe board's I10: diode and 2200 µF (crank hold-up), then buck IN+. F36 out while wiring it
–4GNDNothing: a spare. It is the glovebox USB socket's ground and not proven to reach chassis, so every return stays on 15
Pin 16 is top left and pin 32 bottom left; pins 1 (top) and 17 (bottom) are at the right-hand end: match those to the plug's moulded "1" and "17". Wire in the order of the numbers: mic, audio, CAN, ignition, and the buck's 12 V last. Dashed cavities get no wire.

The pin map

Corroborated by two independent sources: a German Alfa 159/Brera thread documenting the M162 module's connector, and an Italian ClubAlfa thread about fitting Blue&Me to a Giulietta specifically. They agree with each other and with the numbers this project already used.

PinsFunctionNeeded for
30 / 14CAN-H / CAN-L — "CAN alta" / "CAN bassa"Step 7, the tap
15GroundStep 7, the tap
16 / 3212 V permanent / 12 V ignitionStep 15 only. Stay off these until then.
5 / 22 / 21Audio left / right / groundStep 14
7 / 23 / 25Audio+ / Audio− / MUTE, to the radioPossibly step 14
8 / 24Microphone, from the headliner. Amplified; needs its own 5–8 V supplyStep 14, calls
3 / 19 / 20 / 4 / 31USB D+ / D− / VCC / ground / shield, to the car's USB socketNot used. The module fed VCC, so the socket probably has no power while it is out (unverified)

Why the layout can be trusted even though the photo is at an angle. The housing is reported as TE/AMP 968265-1, which TE lists as 32 positions in two rows at 2.54 mm. The mating face in the photograph shows two rows. And the functions pair up exactly as two rows of sixteen would predict: 3/19 is the USB differential pair, 4/20 its power pair, 8/24 the microphone pair, 14/30 the CAN pair, 16/32 the two 12 V feeds. Every pair lands in one column. Three independent lines of evidence agreeing is why this is drawn rather than guessed.

If you want a clean tap rather than probing, the mating parts are reported as housing 929053-2 and contacts 144969-1.

Find the 12 V pins first

Column 16 carries both 12 V feeds and sits directly beside the ground you want in column 15. One cavity across is the difference between a working tap and shorting a permanent battery feed.

So identify 16 and 32 before you go looking for 30, 14 and 15. Meter against chassis with the key in MAR: those two sit at battery voltage and nothing else on this connector should. Once you know where they are, count away from them.

Where each wire actually lands

Car sideBlue&Me pinGoes to
CAN-H30Screw terminal H on the MCP2515 module
CAN-L14Screw terminal L on the MCP2515 module
GND15Not the screw block — it is 2-way, H and L only. Straight to a spare ground pin on the Pi header: 6 on this build (or 9, 14, 20, 25, 30, 34, 39 — all the same net)

The ground connection is required. On a battery bank, the Pi's ground is separate from the car's. CAN is differential, but the transceiver's input voltages must still stay within a range referenced to the car's ground. I therefore connected the two grounds. Without that connection, messages may be read incorrectly or not at all.

Any free ground pin will do: they are all one net. On this build the car ground is on pin 6, and the module's own ground on pin 39.

These pin numbers were inherited; the car has confirmed them

30 / 14 / 15 come from fmntf's write-up of the Doblò 263. On my car they are right: every capture since 2026-09-13 was taken there, with zero bus errors, and the connector carries all of B-CAN, the diagnostics (18DA…) included. The OBD socket carries body traffic only, with no diagnostics at all, so captures from the two taps are never compared.

The cost of being wrong is low and the failure is quiet: candump shows nothing. The tap is listen-only, the CAN controller cannot transmit, and swapping CAN-H and CAN-L is harmless. What is not harmless is touching pins 16 and 32, which are the 12 V feeds. Identify those first and stay off them.

If you have a meter and the car is asleep, a CAN pair reads roughly 60 Ω between the two lines — two 120 Ω terminators in parallel — and each line reads open to chassis. That is a useful confirmation when it appears, but B-CAN is a low-speed bus and may be terminated differently, so a reading that is not 60 Ω does not prove you have the wrong pins.

Then listen

candump -e can0,#FFFFFFFF     # errors and data, everything

Turn the key to MAR. Frames should appear.

Use the same tap point for every capture

Step 10 diffs capture H against capture E, and two captures taken at different points on the bus are not comparable — the diff would mix "frames the Body Computer now expects" with "frames visible somewhere else".

The OBD2 socket, and why the Pi does not use it

OBD2 / J1962, viewed facing the socket in the car1B-CAN-H234GND5GND6CAN-H789B-CAN-L1011121314CAN-L1516+12V6 / 14 — the high-speed CAN the tablet's adapter uses for AlfaOBD1 / 9 — body B-CAN, H / L. Measured on my car (capture M); body traffic only16 — permanent 12 V. Never probe this with the Pi attachedPin 1 is top-left facing the socket; the top row runs 1–8, the bottom row 9–16
The tablet's adapter takes pins 6 and 14. There is one socket, and step 10 needs it for the ECU software while the Pi is recording — which is the whole reason the Pi taps the Blue&Me connector instead.

The body B-CAN is on OBD2 pins 1 (CAN-H) and 9 (CAN-L), with ground from pin 4 or 5. It was measured on my car on 2026-09-21 at 122 frames/s carrying the familiar IDs (capture M), and the pinout was confirmed on the car. An earlier version of this guide guessed pins 3 / 11, which was wrong. It is a valid tap for body traffic, but it cannot hear diagnostics. Capture N contains no 18DA… frames at all across a PROXI alignment, a fault-code read and a fault-code clear. So any alignment work needs the Pi on the Blue&Me connector, and the tablet's adapter needs an OBD2 Y-splitter if it is to share the socket. Captures M and N are the only ones tapped here; do not diff them against the connector-tapped captures.

If you see nothing

  1. Is the car awake? Key to MAR, or open a door.
  2. Swap CAN-H and CAN-L. Harmless to try.
  3. Is the ground wire connected? Without it the bus reads as nothing.
  4. ip -details -statistics link show can0 — a rising bus-error count means the bitrate or oscillator is wrong; a flat zero with no frames means you are not electrically connected.
  5. Re-check the crystal marking against what you passed to install.sh.
Stop condition

candump shows a stream of frames when the key is in MAR.

Step 8 — Capture A: 11-bit or 29-bit?

Start recording with the key out, then turn to MAR and wait 60 seconds.

Wait for "recording can0 ->" before turning the key

I waited for the capture tool to say it was recording before turning the key. It takes about four seconds to start on a Zero W, and the PROXI challenge arrives in the first few seconds after the network wakes. Turning the key straight after Enter can miss the very message capture A is meant to catch. The same timing matters for the recordings below.

mkdir -p ~/captures
TAP="Blue&Me connector 30/14/15"    # the same tap point for every capture

blueandme-capture --scenario A --out ~/captures/A-ignition-on.log \
                  --tap-point "$TAP" --duration 90

Read the last lines of the output:

ID widths seen: {'29-bit': 4127}   <- the answer

Check the identifier width. The expected value is 29-bit. The alfa-blue-me author reported it for the Giulietta, and I confirmed it on mine. A recording showing 11-bit is a different bus; the messages in this guide do not apply. The difference needs to be understood before continuing.

blueandme-decode ~/captures/A-ignition-on.log --profile doblo263 --summary

The Doblò profile is the structural template. Expect some IDs to match by luck and most not to — what matters is whether the topic<<16|node shape holds: do the IDs cluster into a small set of 0x40xx low halves?

Stop condition

You know the identifier width and you have the node list.

On my car (2026-09-13): 29-bit.

Capture A: 4157 of 4157 frames 29-bit, zero bus errors. The IDs are topic<<16 | node, as on the Doblò. Nodes: 4000 Body Computer, 4003 cluster, 4005 radio, and 4001 4002 4006 400A 4018 401A; Blue&Me is 4021.

Step 9 — The rest of the captures

Each is one recording. Take your time; the diffs are only as good as these.

# B — key MAR -> OFF, start recording first
blueandme-capture --scenario B --out ~/captures/B-ignition-off.log \
   --tap-point "$TAP" --duration 90

# E — baseline: key in MAR, engine off, touch nothing at all
blueandme-capture --scenario E --out ~/captures/E-baseline.log \
   --tap-point "$TAP" --duration 180

# C — one button at a time, 3 presses each, 2 seconds between
blueandme-capture --scenario C --out ~/captures/C-buttons.log \
   --tap-point "$TAP" --duration 180 \
   --label "vol+ x3, vol- x3, next x3, prev x3, src x3, mute x3, menu x3"

# F — radio: change source, volume up/down, mute
blueandme-capture --scenario F --out ~/captures/F-radio.log \
   --tap-point "$TAP" --duration 120 \
   --label "FM, volume, mute, source cycling"

Then find the button frame:

blueandme-diff ~/captures/E-baseline.log ~/captures/C-buttons.log --by bits

Look for an ID whose payload returns to all-zero between presses and whose volatile bits form a clean bitmask. Compare against the masks both reference platforms share: 0x8000 vol+, 0x4000 vol−, 0x2000 mute, 0x0400 source, 0x0080 menu, 0x0040 windows.

Stop condition

Four captures on disk plus a button-frame candidate.

On my car (2026-09-13).

Captures A, B, E, C and F are on disk. The wheel frame is 06354000, from the Body Computer: the Doblò's own ID, with the same masks, plus next 1000 and prev 0800. It repeats at 2 Hz, with an extra frame on every change. Capture C holds short presses only.

Step 10 — Capture H: re-align PROXI with Blue&Me

This deliberately makes the odometer blink

It is reversible: align back without Blue&Me and the blinking stops.

Using your OBD2 adapter and ECU software, run PROXI alignment with Blue&Me present in the Body Computer's configuration. The module is still physically absent, so the Body Computer will look for a node that never answers.

The Pi is tapped at the Blue&Me connector, so the OBD2 socket is free for the tablet and both can be connected at once. Start the capture first, then run the alignment inside it.

blueandme-capture --scenario H --out ~/captures/H-proxi-with-bm.log \
   --tap-point "$TAP" --duration 180
blueandme-diff ~/captures/E-baseline.log ~/captures/H-proxi-with-bm.log

If $TAP differs between E and H the diff is meaningless — check the two .meta.json sidecars agree before trusting it.

The H − E comparison showed the messages the Body Computer expects from Blue&Me: the PROXI challenge, its retries and status queries to the missing node. I used this comparison in place of a working original module's recording; my broken module could not provide a working example.

While you are in the ECU software, also check:

  • whether the radio has its own Blue&Me / media-source configuration item (if the radio needs it too, no amount of CAN will help)
  • whether the Blue&Me node's stored PROXI value is readable (the fallback, should the nodes not share one value)
Stop condition

A non-empty H − E diff, and you have seen what the ECU software shows for the radio.

On my car (2026-09-21): PROXI is solved.

About a second after the network wakes, the Body Computer sends 1E114000#. Nodes 400A 4003 401A answer within milliseconds with the same six-byte value: the value is shared. A node that stays silent gets three retries, and a mismatch is what makes the odometer blink.

Note the six bytes your own car's nodes answer with. In a capture they are the frames 1E11400A, 1E114003 and 1E11401A right after 1E114000#. That is your PROXI value; it goes into the Pi's configuration in step 12.

The blink was fixed in the Body Computer itself. Its PROXI record 2023 needs group 6F 04 00 05 at 02, "telematic present"; experiments/node61/write_bc_record.py wrote it, with an undo file kept. That script changes the car's configuration: read experiments/README.md in the repository before you use it, and read the record out and keep it first. During alignment the Pi also answered diagnostics as the telematic unit, 61, the way the cluster 60 does. Since then the car expects a Blue&Me node, so the blink comes back whenever the Pi is absent. The radio needs nothing of its own (step 12).

04 Profile and first transmission steps 11–12

Step 11 — Check the profile against your captures bench

The frames the Pi expects and sends are in blueandme/protocol/profiles/giulietta940.py, each with the recording of my car it was seen in: the 29-bit width, the wheel frame and its masks, and every frame the Blue&Me node exchanges with the car. Received: the Body Computer's status poll and PROXI challenge, and the radio's media request. Sent: the status, the PROXI answer, the watchdog, track time, the audio channel and the track text.

I compared the profile with my recordings before allowing any transmission. The commands below print the profile and decode the captures. This comparison needs to be repeated for the car being fitted:

blueandme-protocol-map --profile giulietta940
blueandme-decode ~/captures/A-ignition-on.log --summary
blueandme-decode ~/captures/C-buttons.log --summary

The recordings must contain the status poll 0E094000, the PROXI challenge 1E114000 and the wheel frame 06354000. The wheel bits must also match the buttons pressed in capture C. If either check fails, the car differs from mine: this is the point to stop, with transmission still disabled.

Stop condition

Your captures show the frames the profile names, and blueandme-giulietta --check passes.

How fast the Pi answers. With my car's traffic replayed to the application on a virtual bus (experiments/node4021/app_replay.sh): PROXI answered in 3.3 ms, the radio's request in 3.1 ms (its window is about 100 ms), all 62 status polls in a median 3.5 ms. The application reads only the profile's frames; the kernel filters the rest, or the Zero W answers the radio too late.

Step 12 — First transmission, one frame at a time

Log every step

If anything unexpected happens — warning lights, a module dropping out, the radio behaving oddly — go back to listen-only immediately and write down what you saw.

First, two things. The original module is unplugged: two nodes with the same address contend. And your PROXI value from step 10 is in the Pi's configuration, /etc/blueandme/config.yaml, under can:, as 12 hex digits in quotes. While it is empty the Pi does not answer the PROXI question. On my own Pi the value is built into the copy it runs. This setting exists only in the published code: tests cover it, but I have not yet run it in the car.

can:
  proxi_value: "............"    # your car's six bytes, 12 hex digits, in quotes
blueandme-giulietta --config /etc/blueandme/config.yaml --check

Then one command takes the controller out of listen-only and lets the application send the frames named, all six by default; off reverses both:

sudo ~/giulietta-blue-me/tx.sh on                        # all six node frames
sudo ~/giulietta-blue-me/tx.sh on bm_status_response     # or one at a time
sudo ~/giulietta-blue-me/tx.sh status
journalctl -fu blueandme-giulietta             # every transmitted frame is logged
sudo ~/giulietta-blue-me/tx.sh off                       # back to listen-only

My car accepted all six, so on with all of them is the normal case. One at a time, in this order, if anything looks wrong:

#FrameQuestion it answers
1bm_status_responseDoes the Body Computer stop treating the node as missing?
2bm_proxi_responseDoes the odometer stop blinking?
3bm_watchdogAny change?
4bm_audio_channelDoes the radio now offer, and accept, the Blue&Me source?
5bm_track_time, bm_text_messageDoes text appear on the displays?

At item 2, I had a replacement the car accepted. Item 4 opened the radio's audio input. Only then was it worth connecting the sound card to the car.

How the radio and the Pi agree on the source. The radio asks with 06314005#0C…, the Pi answers 06314021#…84 within 3–5 ms, the display frame 0A114005 turns to E2, and the radio confirms with 04…10. Leaving is 24, answered …80. The Pi answers only when asked: …84 sent unprompted was ignored. Sometimes the radio skips its 0C; pressing MEDIA again works.

The script from before the application. The first transmissions on my car came from a script run by hand, experiments/node4021/node4021_full.py. It remains for tests the application does not have. Copy it and car_tx.sh from that folder to the Pi's home; car_tx.sh lets can0 transmit for the run, puts back the mode it found on any exit, and refuses on a quiet bus: sudo ~/car_tx.sh 1800 --value <your PROXI value> --text.

On the car, transmitting is the normal state

Once the car expects the module, the Pi stays tx.sh on, across reboots and reinstalls: without its PROXI answer the odometer blinks. Listen-only (tx.sh off) only while CAN leads are newly connected, until ip -s -d link show can0 shows frames arriving and no errors. preflight.sh checks that the controller and the app agree, and it and car_tx.sh put back whatever mode they found (car_tx.sh stops the app for its run if the app itself transmits, and starts it again after). tx.sh status shows the controller and the app.

Emergency stop

sudo ~/giulietta-blue-me/tx.sh off
# or, if that script is not there:
sudo sed -i 's/^  mode:.*/  mode: listen-only/' /etc/blueandme/config.yaml
sudo systemctl restart blueandme-giulietta

Physically: pull CAN-H and CAN-L.

05 Audio and permanent install steps 13–15

Step 13 — Sound card bench

Do this in parallel with the CAN work; it needs no car. The Pi Zero W has no analog audio at all, and the car is analog on both sides: the radio takes Blue&Me audio on connector pins 5 / 22 / 21, and the microphone arrives on pins 8 / 24. A USB sound card handles both directions. Audio cannot travel over CAN: B-CAN runs at 50 kbit/s, and CD-quality stereo needs 1.4 Mbit/s.

The card is a Ugreen USB-A adapter built on a C-Media HS-100B. It plugs into the Zero W's micro-USB data port — the one marked USB, not PWR — through an OTG adapter.

  • Ugreen USB sound card C-Media HS-100B
  • Micro-USB OTG adapter micro-B plug to USB-A socket
  • Headphones for the output test
  • A headset with a microphone for the recording test
  • Multimeter for the sleeve check
HS-100B
USB ID0d8c:0014 (C-Media), USB 1.1 full speed, 100 mA
ALSA nameDevice, so plughw:CARD=Device
Outputstereo, headphone jack. Speaker volume −37 to 0 dB
Inputmono microphone jack. Mic Capture −12 to +23 dB; Auto Gain Control on by default; install.sh switches it off, because calls need fixed mic gain
Sample rates48 and 44.1 kHz only. Calls arrive at 8 or 16 kHz, so the Pi resamples them

Mic Playback must stay off. It loops the mic input straight to the output. It is off by default, but in the car it would send the cabin mic into the radio. blueandme-status warns if it is on.

The headphone sleeve is a true ground. The HS-100B can run a "cap-less" output, in which the sleeve sits at a bias voltage instead of ground. This card does not: with it powered, the sleeve reads 0 V against the metal shell of its USB plug. Re-check that if the card is ever replaced, because a biased sleeve must never touch pin 21.

The mic jack carries about 3 V of bias, open circuit, for plain electret mics. That is too weak for the car's amplified mic, which must never be wired straight to it.

  1. On a PC first

    lsusb lists the card with vendor ID 0d8c. Then meter the headphone sleeve against the USB plug's shell: 0 V.

  2. On the Pi: find the card

    Plug it in through the OTG adapter. aplay -l and arecord -l must both list it, as card N: Device [USB Audio Device].

  3. Play and record

    A tone into headphones, then five seconds from the headset mic, played back.

speaker-test -D plughw:CARD=Device -c 2 -t sine -f 440 -l 1
arecord -D plughw:CARD=Device -f S16_LE -r 48000 -c 1 -d 5 /tmp/mic.wav
aplay -D plughw:CARD=Device /tmp/mic.wav

install.sh makes the card the Pi's default sound device, by its name Device. It also sets up Bluetooth for both music and calls:

ServiceDoes
bluealsamusic sink and the hands-free side of calls (-p a2dp-sink -p hfp-hf), in bluez-alsa 4.3.1 built with mSBC for wideband calls
bluealsa-aplayplays music to the card
blueandme-sco-routeat boot, tells the Zero W's Bluetooth chip to carry call audio over HCI; without it, calls are silent
blueandme-sco-aplayplays the caller to the card, with a 150 ms buffer
blueandme-sco-uplinksends the card's mic to the phone. It holds the call channel open for as long as the phone is connected, and it never lets stale mic audio build up into delay
blueandme-bt-reconnectafter boot, calls the paired phone until it connects. My phone reconnected by itself only when its own Bluetooth came on, not to a kit that starts after it

Calls are wideband. Debian's bluez-alsa (4.0) carries calls only at 8 kHz. install.sh puts bluez-alsa 4.3.1 built with mSBC into /usr/local, from the prebuilt package in packages/ or by compiling it, and swaps it over Debian's files with dpkg-divert. The phone then picks mSBC, 16 kHz, on the Zero W's own Bluetooth chip: on the bench quiet words came through that 8 kHz lost, and the few damaged packets (about three in 75 s) were concealed. sudo ./install.sh --no-wideband puts Debian's files back.

Pair the phone once. Nothing answers pairing requests while the app is listen-only, so blueandme-pair opens pairing for a while, trusts the phone that pairs, and closes it again. Pair after install.sh has run, so that the phone sees the hands-free profile; a phone paired earlier shows only "Media audio" and has to be forgotten and paired again.

sudo blueandme-pair --seconds 120
# on the phone: pair with "blueandme", then check Phone calls and Media audio are on

I tested music first, then a call, using headphones on the sound card and a mic in its input. Both directions need to work before the audio wiring goes into the car. During a call, journalctl -u blueandme-sco-uplink shows how much microphone audio was sent.

The Pi can also control the call, by AT command over the hands-free link: blueandme-call answer, blueandme-call hangup, and blueandme-call calls to list them. Each prints the phone's reply and succeeds on OK. After a reboot, blueandme-bt-reconnect brings the phone back without touching it.

Call audio timing

The microphone relay drops audio that has waited more than 120 ms. A plain arecord | aplay pipeline retained four seconds of audio between calls in my test. Keep separate players for music and calls; the shared player did not return to music. Polling Bluetooth state every three seconds, with higher priority for the microphone relay, avoided overloading the single core.

The steering wheel

The installed app turns the wheel's buttons into phone actions, as the Giulietta Blue&Me manual describes them (604_38_194, p. 9): the action comes when the button is let go, and a press held over a second is a long press. At each press it asks the phone which calls exist (AT+CLCC), so it never falls out of step with it. It sends nothing on CAN, so it works in listen-only too. On the bench, with buttons injected through the controller's loopback (sudo ~/press.sh phone 1.5), each of these worked with a real phone and a real call (2026-09-26). In the car, with the real wheel buttons, I have since confirmed answering a normal call, hanging up, rejecting a call, muting the mic, moving a call to the phone and back, and the assistant through the roof microphone.

ButtonDoes
☎ phonePress: answer a ringing call, or take the waiting one. Hold: reject a ringing call (the caller hears busy), or end the call.
mute / ESCIn a call, mute and unmute your mic. Otherwise pause and resume the music. Also closes the assistant.
voice ("Windows")Opens the phone's own assistant (AT+BVRA=1), which hears you through the car's mic and answers through the speakers. The phone ends the session itself once it has answered; its page stays on the phone's screen.
▲ ▼Next and previous track. Previous restarts the song first, as my phone does.
SRC / OKIn a call, move it to the phone's earpiece and back. Outside calls the radio uses it to change source.
+ / −Nothing on the Pi: the radio sets its own volume.

Moving a call to the phone is done at the radio link: the Pi drops the call's audio link (hcitool, HCI Disconnect), and the phone takes the call to its earpiece. Bringing it back is AT+BCC, which asks the phone to set the link up again. Merely stopping the players does not do it with bluez-alsa 4.3.1: the link stays up and the call goes silent on both sides.

Stop condition

The card is listed for playback and capture, the sleeve reads 0 V, and both the tone and the recorded voice are heard in headphones. Then, with the phone paired, music plays, and a call stays on Bluetooth with both sides heard and no noticeable delay.

Step 14 — Connect audio and the mic to the car

The card's headphone output goes to the Blue&Me connector's audio pins.

SignalBlue&Me pin
Left5
Right22
Audio GND21

The sleeve is a true ground (step 13), so the plug wires straight across: tip is left, to pin 5; ring is right, to pin 22; sleeve to pin 21.

I started with the card's volume low, selected Blue&Me and compared its loudness with FM by ear. The level is adjusted on the Pi with the card's own volume control. The next check is for alternator whine with the engine running. If it is present, a 1:1 audio isolation transformer (a "ground loop isolator") between the card and the car breaks the ground loop.

The microphone. Pins 8 (MIC+) and 24 (MIC−) carry the roof-console microphone, which is amplified. It needs its own 5–8 V supply on its signal wire, and a divider before the card's input, because the card cannot power it and its signal is close to line level. The circuit below does both. On other cars of the group the capsule is a Telicom MIC-98, which its datasheet runs on 5–8 V through 680 Ω; I found no confirmation that the 940 has the same one, so the circuit is built to be measured before it is trusted. During a call the application also tells the radio on CAN that a call is on, with the value the Doblò's module uses.

The mic test board

A breadboard that powers the roof microphone the way the module did, only more gently, and feeds it to the sound card's mic jack through a capacitor (keeps the mic's DC off the card) and two resistors (turn its level down about twelve times). The Pi then measures it, plays it back and carries a test call. The ignition wake of step 15 sits on rows 20–27 of the same breadboard.

−abcde1234567891011121314151617jumper → Pi pin 2 (5 V) · car only2 kΩ ‖ 1 kΩ1 kΩ in b: about 670 Ω+10 µFlong leg (+) up10 kΩ1 kΩlead → car pin 8mic cable · tipplug in the card's MIC jackmic cable · sleevelead → car pin 24jumper → Pi pin 6 (GND)lead → car pin 15 (CAN ground) · car only
Each row's holes a–e are joined; rows are not joined to each other; the − strip is one long connection. Teal: signal; grey: ground; dashed: only at the car. Pi pin 6 on the strip is the Pi's ground, which reaches the car through the pin 15 lead.
PartWhereCheck
2 kΩ1c to 5cmeter on Ω, resistor lying on the table (fingers on both legs read low): about 2.0 k
1 kΩ1b to 5b, beside the 2 kΩabout 1.0 k; with both in, row 1 to row 5 reads about 670 Ω. Added at the car (2026-09-27): the mic then sat at 2.37 V instead of 2.16 V
10 µF+ in 5d, − in 8dlong leg is +, the stripe marks −; rated 10 V or more
10 kΩ8c to 12cabout 10 k
1 kΩ12d to the − stripabout 1.0 k
Mic cabletip in 12e, sleeve in the − stripan old 3.5 mm cable, cut; its middle wire taped, not connected; plug in the card's MIC jack
Car leads5e (pin 8), − strip (pins 24 and 15)dupont jumper wires
Ground jumper− strip to Pi pin 6stays on
5 V jumper1a to Pi pin 2car only: pin 2 is the outer row, first pin from the microSD end

Home test, done 2026-09-27. With the 5 V jumper off, the audio lead's tip in row 5 and its sleeve in the − strip, the card played a 200 Hz tone into the board: 520 mV at row 5, 41.6 mV at row 12, twelve and a half times less, and the recording through the mic jack was clean (−37.5 dBFS at 0 dB gain, no clipping). At that gain the card's mic input takes about 2 V before it clips, so at the car the recording starts at full gain; if speech comes out quiet, a larger 1 kΩ weakens the reduction.

Measurements from my car

MeasuredValue
Pin 8 to pin 24, module out6.5 kΩ both ways, open to chassis
Fed from 5 V through 2 kΩ2.16 V, 1.4 mA
Fed through 2 kΩ ‖ 1 kΩ (670 Ω, kept)2.37 V, 4.0 mA
Divider, 10 kΩ over 1 kΩ÷ 12.5 (520 mV in, 41.6 mV out)
Silence, card mic gain at +23 dB−60 dBFS
Normal speech−41 to −55 dBFS, peaks about −25
Loud whistlepeaks −0.8 dBFS, nothing clipped

To test the roof microphone, I recorded myself talking and whistling towards it, then made a call. I set the relay to add 15 dB before sending the audio to the phone (--gain-db 15 in /etc/blueandme/sco-uplink.env). The person on the other end said it sounded great. That was a much more useful result than a level reading alone.

At the car, in order

I brought the audio and power tests together for the car visit: step 14 and the car work from step 15. The order below keeps the Pi on its power bank until the buck is connected last.

At home, before leaving

  1. Take the audio lead's wires out of the breadboard (tip out of its row, sleeve out of the − strip): from now on it serves the car's audio pins 5, 22, 21.
  2. Take the 5 V stand-in jumper out of row 26 (the ignition wake's bench test).
  3. Leave unconnected for the trip: the mic's 5 V jumper (row 1) and the four car leads (pins 8, 24, 15, 32). The Pi pin 5 wire and the Pi pin 6 ground stay on.
  4. Buck: solder a red wire to IN+ and a black one to IN−, heat-shrink over the pads, dupont pins on the ends.
  5. Pack: the Pi with MCP2515 and sound card, the breadboard, power bank, buck with a USB cable to the Pi's PWR port, audio lead, dupont wires, a spare 1 kΩ resistor, multimeter, phone, tablet, a fuse puller.
  6. sudo ~/giulietta-blue-me/preflight.sh ends in PREFLIGHT PASS, then sudo ~/giulietta-blue-me/tx.sh off: the Pi stays listen-only while the CAN leads go on. Make sure you can reach the Pi at the car, for example over the phone's hotspot.

At the car, first measure (Pi on the power bank)

  1. Blue&Me module unplugged, can0 still listen-only from home (tx.sh status) while the CAN leads go on.
  2. DC volts, black probe on bare metal: pin 16 about 12 V with the key off and in MAR (permanent); pin 32 0 V off, about 12 V in MAR (ignition).
  3. Pull F36 (the fuse box below): pin 16 drops to 0 V. Put it back.
  4. CAN: 30 to H, 14 to L, and the − strip lead to pin 15.
  5. When ip -s -d link show can0 shows frames arriving and no errors: tx.sh on. The Pi answers the car from here on. Key off and on again: the odometer must not blink.

Then the mic

  1. Meter only, board not on pins 8 and 24 yet: Ω pin 8 to 24, both ways; pin 8 and pin 24 to bare metal (OL).
  2. Board leads onto pins 8 and 24; row 1 jumper to Pi pin 2; mic plug in the card's MIC jack.
  3. DC volts, black on the − strip, red on row 5: clearly under 5 V means the mic is alive. Around 3–4 V is good. Under about 2.5 V, or a recording that distorts on loud whistling, means the 2 kΩ starves it: swap it for 1 kΩ, or put the 1 kΩ beside it (also rows 1 to 5): together about 670 Ω, the datasheet's 680 Ω.
  4. Record on the Pi while someone whistles and talks towards the roof console, play it back, and if it sounds clean, a test call with the car's mic.

Then audio and the app

  1. Audio lead onto pins 5 (tip), 22 (middle), 21 (sleeve), plug in the card's headphone jack. Select Blue&Me on the radio: the phone plays (if its music app was recently used), the radio shows the track. Set the level, listen for whine with the engine running (on the power bank that verdict is provisional).
  2. The wheel: skip, pause, the assistant, answer and reject a call.

Then the ignition (step 15)

  1. Key off. The row 26 lead onto pin 32.
  2. Set the Pi to read the ignition on GPIO3 and watch it while the key goes to MAR and back: low in MAR, high off.

Last, the buck (step 15)

12 V only ever goes to the buck's IN+

Never to the breadboard or a Pi pin. Pull F36 before touching pin 16.

  1. Key out. Pull F36.
  2. Buck IN+ (red) onto pin 16; buck IN− (black) into a free hole of the − strip, which reaches pin 15 through its lead (about 0.1 A; the permanent install gives the buck its own ground wire).
  3. Halt the Pi. When its LED is out, move the Pi's PWR cable from the power bank to the buck's USB socket.
  4. Refit F36: the Pi boots from the car. Check the supply voltage measured at the Pi; Zero W has no under-voltage detector.
  5. Start the engine: the Pi must keep running. Mine reset until the converter was replaced; see the diode, the capacitor and the test results in step 15.
  6. Leaving it: either it stays, running from the car with tx.sh on, or it comes home: halt it, then pull F36 before unplugging anything.
The Blue&Me fuse, F36: bottom of the right-hand column in this fuse box (diagram from the owner's manual). Pulled, it cuts the Pi's permanent 12 V on pin 16; check that once with the meter.
Stop condition

Music through the car speakers at a sane level, no whine.

Radio controls and display

I matched the card's Speaker level to FM by ear. At −20 dB the music was too quiet; I ended up at 0 dB, the card's maximum, and saved it with alsactl store. Then I listened with the engine running. There was no whine, so I did not need a ground-loop isolator. That first check was on the power bank. With the unit on the car's supply and the engine running there is no whine either.

The radio handles some buttons itself. Outside a call, it reports its mute state over CAN and the Pi pauses the phone until the radio unmutes. I also read the radio's arrow buttons from these messages. Left and right change tracks; up and down adjust Bluetooth volume.

Track text uses the Doblò module's format with its 6-bit character set, as decoded in fiatcan, and the Giulietta's radio accepts it. The top line shows the first twelve characters of one text field, so the Pi runs "artist - title" through it every quarter of a second. The bottom line shows another field, which carries the time as M:SS. Four character codes of that set show nothing on this radio and none of them is a bracket, so brackets in a title become *.

Behaviour that depends on the phone. The first press of Previous restarts the current song. If the music app has been idle for a while, the phone ignores Play until I open the app. YouTube Music does not act on fast-forward or rewind commands. A WhatsApp call cannot currently be answered from the wheel: the phone button answers a normal call, but my phone lists a ringing WhatsApp call in a state the application does not treat as incoming.

Step 15 — Permanent install

Once I had verified the audio in step 14, I connected the permanent supply. The Pi runs from the car's permanent 12 V line through fuse F36. It stays in standby for up to 72 hours while parked, ready to answer PROXI when the car wakes. After that it halts. I added further parts as tests showed a need for them.

Why the Pi stays on while parked

The car asks for PROXI about a second after it wakes, which is when it is unlocked, before the key turns. It asks three times within a few seconds. A Pi that has to boot at that moment is far too late: from a cold power-on on 2026-09-27 the firmware took about 3.8 s, the kernel 5.6 s, and the app was on the bus about 53 s after power-on.

A Pi that is already running answers at once: 3.3 ms in the bench replay of the car's traffic (step 11), 8 ms from the supervised script in capture ZB. In every test so far the Pi was running when the car woke, so PROXI was always answered and the odometer never blinked. What the car does when a Pi starts only after it woke, as it would after a parking longer than the hold, has not been tested.

Cold boot against the car's PROXI check, measured on this Pithe car asks for PROXI, three times← a running Pi answers in 3 mscold Pi: firmware 3.8 s, then kernel 5.6 sits app on the bus at ~53 s, off the scale →0 spower on10 s20 s30 s40 sCold boot 2026-09-27: systemd-analyze and the journal; firmware time from the power log.
The car's check is over before the kernel has even started. fmntf answers PROXI from initramfs, before /sbin/init; that only helps a kernel that boots in about two seconds, and this one takes five and a half. Hence standby.

Standby, measured

Measured on the bench with a USB power meter at the Pi's 5 V input (experiments/standby/). Standby switches off Bluetooth and Wi-Fi, sets the CPU to its slowest and turns the LED off; the CAN interface stays up, in the mode tx.sh set, to notice the car waking (on the car: transmitting, so PROXI is answered at once).

StateAt the PiFrom the battery
Working: phone connected, music or a call1.0–1.07 Wengine running
Parked, standby0.63 Wabout 65 mA, 1.6 Ah a day
72 hours of standbyabout 4.7 Ah, some 7 % of a 70 Ah battery
Halted, after the hold0.22 Wabout 25 mA, 0.6 Ah a day, until F36 is pulled and refitted (or the ignition wake, if fitted)

For the battery calculation I assumed 12.4 V and a buck converter with 80 % efficiency. The battery's actual capacity needs checking on its label. The halted Pi still draws roughly a third of its running current. Three weeks parked use about 4.7 + 11 Ah, roughly 22 %. If I will be away longer, I pull F36 to disconnect the supply.

Blue&Me is unavailable while the Pi is halted. The radio cannot use the source and PROXI goes unanswered. Removing and refitting F36 restarts the Pi, which is ready in about a minute. If long parking is frequent, the ignition-wake circuit below can be added; turning the key then restarts it.

Waking from standby. blueandme-standby enters standby after a minute of bus silence with the ignition off. It wakes on a CAN message when the car is unlocked, or through the ignition line if connected. In my bench test with a message, music was ready in 3.3 s and calls in 3.7 s. A cold start takes 33.5 and 34.2 s. The service only arms after seeing car traffic, so a bench setup with a silent bus never enters standby.

The install

ConcernHow
Power12 V→5 V buck, automotive-rated, low idle current, from Blue&Me pin 16 (permanent 12 V) and pin 15 (ground), always on. At the end of the hold the Pi halts (about 25 mA from the battery) until F36 is pulled and refitted, or, with the ignition wake fitted, until key-on. The original 6–32 V USB module was replaced after an unloaded dropout test, by a TECNOIOT 6–24 V to 5 V USB step-down module; the replacement resolved the crank resets (2026-10-01). Keep the converter mounted inside the case a few centimetres from the connector, so the car's own fuse for the Blue&Me feed covers the short lead as it covered the original module's wiring; an inline 2 A fuse only if the leads ever run outside the case. On the bench, from a 12 V adapter, it held the Pi at 4.90–4.92 V from boot through music (0.12–0.32 A), with negligible idle current (original converter, 2026-09-25); that 12 V test did not establish low-input operation. Pulling the car's fuse, F36, is the power cut for long absences. Never feed 12 V to a GPIO pin.
PROXIAnswered by the running Pi, because it is in standby rather than off (3.3 ms on the bench). After a parking longer than the hold the Pi is halted until restarted; what the car does with a late answer has not been tested.
MicThe step 14 circuit, soldered, with the values measured at the car, feeding the sound card's mic jack.
Ignition sensingCAN traffic wakes a Pi in standby, with no wire. Only a halted Pi, after a parking longer than the hold, needs the ignition: added only if such parkings turn out to be common; until then, pull the fuse and put it back. The circuit is an NPN transistor and two resistors (PN2222 from a starter kit): pin 32 → 100 kΩ → base, 100 kΩ base to ground, collector to GPIO3 (header pin 5), emitter to ground; a 1N4007 across base and emitter (cathode to base) keeps negative spikes off the base (power.ignition_gpio: 3, ignition_active_low: true). GPIO3 is the one pin that boots a halted Pi when pulled low, and has its own 1.8 kΩ pull-up. No optocoupler: the Pi's ground is the car's ground anyway.

I have not made the root filesystem read-only yet. The card has survived the power cuts so far, but that does not establish that it is safe from damage.

The ignition wake

Optional: it lets the ignition restart a Pi that has halted after a parking longer than 72 hours; without it, pull F36 and put it back. Three kit parts on rows 20–27 of the mic board's breadboard, sharing its − strip. When the key is in MAR, the transistor pulls Pi pin 5 (GPIO3) to ground, and a halted Pi boots on that.

−abcde20212223242526271N4007100 kΩEBCPN2222100 kΩwire → Pi pin 5 (GPIO3)pulled to ground while the key is in MARwire → car pin 32 (ignition)12 V in MAR: never onto a Pi pin
Amber: 12 V from the car, never onto a Pi pin; teal: to the Pi; grey: ground. On a long breadboard, check the − strip has no gap (a break in the blue line) before row 27.
PartWhereCheck
PN2222E in 21c, B in 22c, C in 23cmeter on diode (→|): red on one leg, black on each other leg; the leg that reads about 0.6–0.7 V to both is the base (the middle one on a PN2222). With red on the base, the leg reading slightly higher is the emitter. Black on the base: both OL (an NPN).
1N4007stripe in 22b, other end in 21bthe stripe goes to the base's row
100 kΩ22a to the − stripabout 100 k, measured off the board
100 kΩ22d to 26dabout 100 k
Jumper21a to the − stripthe emitter's ground
Wire23e to Pi pin 5pin 5: the inner row, third pin from the microSD end
Wire26e to car pin 32the ignition line, as measured at the car

Bench-tested 2026-09-27. The Pi's own 5 V (pin 2) on row 26, standing in for the ignition, set GPIO3 to 0; without it, 1. A halted Pi booted the moment it went in (halted 14:38:48, back on the network 14:39:56). That stand-in comes out afterwards, or the Pi restarts whenever it halts. At the car it only needs the pin 32 wire and two lines of config (ignition_gpio: 3, ignition_active_low: true).

12 V to 5 V

The buck module stays off the breadboard: it has its own solder pads and a USB socket, and keeping 12 V off the board keeps it away from the Pi's pins.

FromToNote
Car pin 16 (permanent 12 V)buck IN+behind the car's fuse F36. For good, through the crank hold-up: pin 16 → board I10, board L10 → buck IN+
Car groundbuck IN−the − strip for the car test. For good: pin 15 → board K1, board L1 → buck IN−
Buck USB socketPi PWR porta USB cable; the Pi's other port keeps the sound card

Soldered, without a breadboard

For the permanent install the mic circuit is soldered, each joint covered with heat-shrink: a breadboard shakes loose in a car. The ignition wake goes onto the perfboard of the next part. Values as kept at the car (2026-09-27): with a 1 kΩ beside the 2 kΩ the mic sat at 2.37 V (2.16 V on the 2 kΩ alone) and recorded clean at full gain, loud whistles included.

2 kΩ1 kΩside by side: about 670 Ωwire → Pi pin 2 (5 V)car pin 8+10 µF+ toward A10 kΩmic plug tip1 kΩcar pin 24 · car pin 15mic plug sleevePi ground (pin 6)ABG
The mic circuit as three joints: A (the 2 kΩ and 1 kΩ side by side, the capacitor's + leg, car pin 8), B (10 kΩ, the lower 1 kΩ, the mic plug tip), G (the grounds). Blue: heat-shrink over each joint and part.
  1. Cut the wires to length. Before soldering, slide a sleeve onto each wire that ends at A, B or G, and one over each part you will join.
  2. The 2 kΩ and a 1 kΩ side by side, their legs twisted together at both ends (about 670 Ω); one end to the Pi pin 2 wire.
  3. A: the pair's other end, the capacitor's + leg and the car pin 8 wire, twisted and soldered. The capacitor's − leg to one end of the 10 kΩ.
  4. B: the 10 kΩ's other end, the second 1 kΩ and the mic plug tip wire.
  5. G: that 1 kΩ's other end, car pins 24 and 15, the mic plug sleeve and the Pi ground wire.
  6. Slide each sleeve over its joint or part and shrink it (heat gun, or a lighter held below, not in the flame).
  7. Meter on Ω before the car: Pi pin 2 wire to car pin 8 wire about 670 Ω; mic tip to ground about 1 k; car pin 8 to ground open.
Two grounds to check before closing the case

With the unit built into its case, the person I called heard a low, motor-like noise and not my voice. Back on the bench (2026-10-11) the mic input's noise floor was −34 dBFS at +23 dB gain with nothing on car pin 8. At the car on 2026-09-27, with the roof microphone connected and the cabin quiet, it had been about −60. On the bench it was the same on the power bank and with car pin 8 held to pin 24, and it was gone (−82) with the mic plug out of the card. So it came in through the mic plug, and both causes were grounds.

I had taken the mic plug's sleeve to car pin 24 alone and not to joint G; joined, the floor was −40. And the sound card's own ground stood above the Pi's, 60–80 mV with the mic plug out and 30–38 mV with it in: about 2 Ω in the ground of its USB cable, which I had cut short and soldered to the Pi to fit the case. A short wire soldered from the card's ground to joint G brought that to 4.5 mV with the mic plug in, and the floor to −59 dBFS with pin 8 held to pin 24. That is close to the −60 of 2026-09-27, but it is not the same test: there the microphone was connected, here there was none and the two pins were joined.

Two readings find both, with the power on. Mic plug out: plug tip to car pin 24, about 1 kΩ. Mic plug in: DC millivolts between car pin 21 (the card's ground, through the audio lead) and car pin 24, a few millivolts and steady. Tens of millivolts that hover are the noise itself.

Since both fixes the calls work again, tested in the car with the unit fully installed (2026-10-11). The person I call reports a slight echo. I have not measured it, and I will deal with it later.

Ignition wake and crank hold-up on one perfboard

Both circuits that touch the car's 12 V, on one piece of the kit's perfboard (plated holes, none joined): 10 columns × 24 rows, the size of the 3 × 7 cm board (count yours). The ignition wake takes rows A–G; row H stays empty; the crank hold-up takes rows I–X, most of it the capacitor lying flat. Parts go on top, connections are made underneath with bent leads and solder bridges. With the capacitor lying down the board stands about 21 mm tall.

Crank hold-up and converter fix (2026-10-01). The installed Pi reset during cranking despite an added 2200 µF capacitor. The original converter, advertised for 6–32 V, produced 0 V at a 10 V bench supply even with the Pi disconnected and the supply in constant-voltage mode. Output returned by 11 V; at 12 V supply the multimeter measured 5.09 V output. Replacing the converter resolved the resets. The replacement, a TECNOIOT 6–24 V to 5 V USB step-down module, kept the Pi running down to 5 V at the bench supply; the Pi's rail voltage at that input has not been recorded. Buck IN− was also found disconnected and reconnected before these tests; it needs its own return to pin 15. Pin 16 reaches the buck through a diode, with the fitted 2200 µF capacitor across IN+/IN− after it. Use a capacitor rated at least 35 V; the diode's stripe faces the capacitor. No increase in capacitance is required by the reported fix. The car's crank waveform remains unmeasured; do not assume an advertised 6 V input limit when calculating hold-up time.

Parts on top; coloured joints and tracks are made underneath12345678910ABCDEFGHIJKLMNOPQRSTUVWX→ Pi pin 5 (GPIO3)→ car pin 32ignition, 12 V in MAR→ car pin 16permanent 12 V (F36)→ buck IN+Pi ground ←car pin 15 ←buck IN− ←100 kΩ100 kΩ1N4007 · stripe F5diode · stripe J6PN2222flatEBC−−−−−2200 µF35 V−+lying flat on the board,stripe (−) toward column 1;glue or tie it down. Its farend may overhang a little.IGNITION WAKECRANK HOLD-UPcoloured = joined underneath:groundbaseGPIO3pin 32 (12 V in MAR)pin 16 (12 V)dot = solder joint; band = track
Seen from the top. Each coloured dot is a joint, each coloured band a track to make underneath between those holes; uncoloured holes stay empty. Turned over, column 1 is on the right: go by the hole names. Grey: ground (the Pi's on the ignition side, the car's pin 15 on the crank side, not joined on the board: the buck's current stays off the Pi's ground wire); blue: base; teal: GPIO3; amber: pin 32; red: pin 16. Neither 12 V may reach a Pi pin.
PartHolesCheck
PN2222E in B3, B in B5, C in B7; flat face toward row CE, B, C found with the meter first, as in the breadboard table above
100 kΩD1 to D5 (base to ground)about 100 k, measured off the board
100 kΩE5 to E9 (from pin 32)about 100 k
1N4007F1 to F5, stripe at F5the stripe goes to the base's column
DiodeJ10 to J6, stripe at J61N5822 or 1N4007; the stripe toward the capacitor
2200 µF 35 V+ in L6, − in L3; body lying flat over rows M–Xthe long lead is +, the stripe on the body marks −. Backwards it can burst
WiresPi pin 5 B9, Pi ground G1, car pin 32 G9; car pin 16 I10, car pin 15 K1, buck IN+ L10, buck IN− L1in from the top, soldered underneath
TracksB3–B1–G1, B5–F5, B7–B9, E9–G9; I10–J10, J6–K6–L6–L10, K1–L1–L3underneath; no other hole joined
  1. Transistor first: bend E and C outwards so the legs sit in B3, B5, B7, flat face toward row C. Solder underneath, keeping the three blobs apart.
  2. The two resistors and the 1N4007, flat on the board, stripe at F5; the crank diode in J10–J6, stripe at J6. Solder, leaving the leads long until the tracks are done.
  3. The capacitor: bend both leads 90° about 3 mm from the body, + into L6 and − into L3, body lying flat toward row X. Solder, then a line of glue (or a tie through two free holes) holds the body.
  4. Tracks underneath: lay each long lead along its track and solder it into the next holes; bridge the rest with solder or a bare offcut. Ignition: B3–B1–G1, B5–F5, B7–B9, E9–G9. Crank: I10–J10, J6–K6–L6–L10, K1–L1–L3. Row H and everything else stay apart.
  5. The seven wires in from the top, soldered underneath.
  6. Meter on Ω, nothing connected: C to E open both ways; Pi pin 5 wire to Pi ground wire open; car pin 32 wire to B5 about 100 k. Crank side: car pin 16 wire to buck IN− wire must not read near 0 (the capacitor charges from the meter, so the reading climbs); buck IN+ to buck IN− the same; on the diode range, I10 to L10 about 0.3–0.7 V one way, nothing the other. Then a dab of glue over the wire joints.
  7. At the car, F36 out: wires on, F36 back in. Read GPIO3 while the key goes to MAR and back (0 in MAR, 1 off). Confirm the Pi stays running through a crank; the Zero W has no low-voltage detector, so get_throttled=0x0 is not proof of a stable supply. If it resets, measure buck input and Pi 5 V with a scope.
Cranking is a separate problem from key-off

Cranking lowers the supply even while the Pi is running in standby. The original buck lost its output near 10 V supply on the bench; replacing it resolved the reported resets. Keep the fitted diode and 2200 µF capacitor, and ensure buck IN− is wired to pin 15. If resets return, capture the buck input and Pi 5 V during cranking. The Zero W cannot report supply undervoltage through vcgencmd get_throttled: Raspberry Pi documents the Zero-range exclusion.

The Zero W has no real-time clock. Until NTP sets the time, each recording's started_at is the image build date. The phone hotspot provides internet and corrects the clock, but recordings made earlier keep the wrong dates. A DS3231 costing about €2 could solve this; I have not fitted one yet. Used with ignition wake, it needs a separate I2C bus (dtoverlay=i2c-gpio), because wake uses pins 3 and 5.

  • I have not completed the long-parking test yet. The battery needs checking after one night and then four days parked. The Pi must halt after 72 hours; blueandme-standby should log the halt and Wi-Fi should stop responding. Refitting F36, or turning the key with ignition wake fitted, must restart the Pi. Working in daily use does not establish that it will avoid draining the battery during a longer stay.

Case and connector fitting

The original case is 150 × 175 × 40 mm, with four M3 mounting bosses. Its PP-TD40 plastic passes Bluetooth. Use PETG or ASA for the printed frame and tray; PLA can soften in a parked car. Check the real cable and plug clearances as well as the model, and secure the parts and wiring before closing the lid.

Black Blue&Me housing with its blue connector.
The original Blue&Me case, reused for the replacement.
Empty housing with original posts and connector opening.
Inside the empty case, before fitting the printed mount.
Housing interior with annotated dimensions and mounting positions.
The case measurements I recorded during the build. They are a record for checking against the CAD, not the authoritative dimensions.
White printed frame fitted in the empty black housing.
One of the printed mounting frames tried inside the original case. It is one iteration, not the final version.
Pi, blue CAN board and black USB sound card arranged in the housing.
A component-placement study: Pi, CAN module and USB sound card on the printed mount. The red marks are the collisions found in this test fit. It is not the final layout, wiring or grounding.
Wired electronics under a white printed frame in the black housing.
The assembled replacement in the original case, on the workbench on 1 October 2026. That is before the ground repair of 11 October, which this photo does not show.
Two views of the case floor with coloured overlays marking where the buck converter, sound card, CAN module and Pi with perfboard sit, the right view with the printed frame in place.
The layout over the case floor. Blue: Pi and perfboard. Purple: CAN module. Green: sound card with its plugs. Orange: the buck, hanging from the frame on two cable ties. Circles: bosses and posts to stay clear of.
3D model of the sled: a yellow frame on four posts above a blue tray holding coloured blocks for the Pi, CAN module, sound card and buck converter.
The sled model. Yellow: the frame on the four bosses. Blue: the tray. Red: the case's own posts. The model is checked for overlaps between frame, tray, parts, case and lid.

The fix for the adapter: the card's USB cable is cut short and soldered to the test pads on the Pi's underside. PP1 is 5 V, PP6 ground, PP22 D+ and PP23 D−. The buck's 5 V goes to header pins 4 and 6.

Wires and connector assembly seen from a low angle inside the housing.
A side view of the assembly and cable routing inside the case.

The car connector uses 32 square header pins, 0.64 mm wide and 2.54 mm apart, in perfboard cut to 2 × 16 holes with about a 5 mm border. Only the needed pins have wires. Mark pins 1 and 17 and match them to the plug’s moulded "1" and "17" before mating the connector.

Small perfboard with connector pins and wires passing into the case.
The connector carrier and perfboard at the case opening.

Support and insulate the USB pad wires. If the card disappears with device descriptor read/64, error -71, check the data wires and their solder joints. Do not reset the Zero W’s USB controller by unbinding it: that crashed the kernel in my test and USB stayed unavailable until the power was cut.

Wi-Fi while audio is playing

The Zero W shares one radio between Bluetooth and Wi-Fi. I measured the following packet losses while connected to the phone’s hotspot; switching Wi-Fi off removed the gaps in the music.

Wi-FiAudio packets lost per minute
On, idle on the hotspot150–320
On, with SSH traffic500–1200
Off0

I added a small service to handle that for me. It checks the Bluetooth audio streams every three seconds and switches Wi-Fi off during music or a call. Thirty seconds after the audio stops, it brings Wi-Fi back. It only restores Wi-Fi if it disabled it itself, so it leaves standby's decision alone.

At the car it goes off two seconds after the music starts. The price: to reach the Pi over SSH, pause the music and wait about 40 seconds.